From dbf7d2b9a36433b19694134a22fef2ff0b5ac19d Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 21 Feb 2020 22:33:51 -0500 Subject: [PATCH 01/51] Add DJGPP to configure scripts --- configure | 9 +++++++++ configure.ac | 9 +++++++++ test/configure | 5 +++++ test/configure.ac | 5 +++++ 4 files changed, 28 insertions(+) diff --git a/configure b/configure index 4ecefec717a82..f39a51428cdb6 100755 --- a/configure +++ b/configure @@ -29762,6 +29762,15 @@ printf "%s\n" "#define SDL_JOYSTICK_OS2 1" >>confdefs.h have_joystick=yes fi ;; + *-*-msdosdjgpp*) + ARCH=dos + CheckVisibilityHidden + CheckDeclarationAfterStatement + CheckDummyVideo + CheckDiskAudio + CheckDummyAudio + CheckDLOPEN + ;; *) as_fn_error $? " *** Unsupported host: Please add to configure.ac diff --git a/configure.ac b/configure.ac index cd58faa21acda..f3f7d4ff07bd8 100644 --- a/configure.ac +++ b/configure.ac @@ -4673,6 +4673,15 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works. --ryan. have_joystick=yes fi ;; + *-*-msdosdjgpp*) + ARCH=dos + CheckVisibilityHidden + CheckDeclarationAfterStatement + CheckDummyVideo + CheckDiskAudio + CheckDummyAudio + CheckDLOPEN + ;; *) AC_MSG_ERROR([ *** Unsupported host: Please add to configure.ac diff --git a/test/configure b/test/configure index 8ea80bc27ea2d..6f12d61bf3b1f 100755 --- a/test/configure +++ b/test/configure @@ -3664,6 +3664,11 @@ fi MATHLIB="" SYS_GL_LIBS="" ;; + *-*-msdosdjgpp*) + EXE=".exe" + MATHLIB="-lm" + SYS_GL_LIBS="" + ;; *) ISUNIX="true" EXE="" diff --git a/test/configure.ac b/test/configure.ac index e9890163e6999..ef72653434010 100644 --- a/test/configure.ac +++ b/test/configure.ac @@ -82,6 +82,11 @@ case "$host" in MATHLIB="" SYS_GL_LIBS="" ;; + *-*-msdosdjgpp*) + EXE=".exe" + MATHLIB="-lm" + SYS_GL_LIBS="" + ;; *) dnl Oh well, call it Unix... ISUNIX="true" From 593979d21b08d6453e4e7fd49fb221e476a84c16 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 22 Feb 2020 02:12:31 -0500 Subject: [PATCH 02/51] Do not use MMX or SSE on x86 hosts by default --- configure | 12 ++++++------ configure.ac | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/configure b/configure index f39a51428cdb6..59c64b7fa863f 100755 --- a/configure +++ b/configure @@ -1671,9 +1671,9 @@ Optional Features: --enable-assembly Enable assembly routines [default=yes] --enable-ssemath Allow GCC to use SSE floating point math [default=maybe] - --enable-mmx use MMX assembly routines [default=yes] - --enable-3dnow use 3DNow! assembly routines [default=no] - --enable-sse use SSE assembly routines [default=yes] + --enable-mmx use MMX assembly routines [default=maybe] + --enable-3dnow use 3DNow! assembly routines [default=maybe] + --enable-sse use SSE assembly routines [default=maybe] --enable-sse2 use SSE2 assembly routines [default=maybe] --enable-sse3 use SSE3 assembly routines [default=maybe] --enable-altivec use Altivec assembly routines [default=yes] @@ -20647,7 +20647,7 @@ if test ${enable_mmx+y} then : enableval=$enable_mmx; else $as_nop - enable_mmx=yes + enable_mmx=$default_ssemath fi if test x$enable_mmx = xyes; then @@ -20703,7 +20703,7 @@ if test ${enable_3dnow+y} then : enableval=$enable_3dnow; else $as_nop - enable_3dnow=no + enable_3dnow=$default_ssemath fi if test x$enable_3dnow = xyes; then @@ -20754,7 +20754,7 @@ if test ${enable_sse+y} then : enableval=$enable_sse; else $as_nop - enable_sse=yes + enable_sse=$default_ssemath fi if test x$enable_sse = xyes; then diff --git a/configure.ac b/configure.ac index f3f7d4ff07bd8..f2ca7e08a6c9b 100644 --- a/configure.ac +++ b/configure.ac @@ -664,8 +664,8 @@ if test x$enable_assembly = xyes; then dnl Check for various instruction support AC_ARG_ENABLE(mmx, -[AS_HELP_STRING([--enable-mmx], [use MMX assembly routines [default=yes]])], - , enable_mmx=yes) +[AS_HELP_STRING([--enable-mmx], [use MMX assembly routines [[default=maybe]]])], + , enable_mmx=$default_ssemath) if test x$enable_mmx = xyes; then save_CFLAGS="$CFLAGS" have_gcc_mmx=no @@ -698,8 +698,8 @@ dnl Check for various instruction support fi AC_ARG_ENABLE(3dnow, -[AS_HELP_STRING([--enable-3dnow], [use 3DNow! assembly routines [default=no]])], - , enable_3dnow=no) +[AS_HELP_STRING([--enable-3dnow], [use 3DNow! assembly routines [[default=maybe]]])], + , enable_3dnow=$default_ssemath) if test x$enable_3dnow = xyes; then save_CFLAGS="$CFLAGS" have_gcc_3dnow=no @@ -727,8 +727,8 @@ dnl Check for various instruction support fi AC_ARG_ENABLE(sse, -[AS_HELP_STRING([--enable-sse], [use SSE assembly routines [default=yes]])], - , enable_sse=yes) +[AS_HELP_STRING([--enable-sse], [use SSE assembly routines [[default=maybe]]])], + , enable_sse=$default_ssemath) if test x$enable_sse = xyes; then save_CFLAGS="$CFLAGS" have_gcc_sse=no From 8c297b5ec61375f196dc4d1109f8ebfb33bcfa44 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 23 Feb 2020 17:24:32 -0500 Subject: [PATCH 03/51] djgpp: Get testfile (mostly) passing --- configure | 25 +++++++++++++++++++------ configure.ac | 12 +++++++++++- test/testfile.c | 4 ++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 59c64b7fa863f..118cbe1d60d63 100755 --- a/configure +++ b/configure @@ -19358,6 +19358,25 @@ printf "%s\n" "#define HAVE_MPROTECT 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + case "$host" in + *-*-msdosdjgpp*) + { $as_echo "$as_me:${as_lineno-$LINENO}: skipping unfinished fseeko64 in DJGPP" >&5 +$as_echo "$as_me: skipping unfinished fseeko64 in DJGPP" >&6;} + ;; + *) + for ac_func in fseeko64 +do : + ac_fn_c_check_func "$LINENO" "fseeko64" "ac_cv_func_fseeko64" +if test "x$ac_cv_func_fseeko64" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FSEEKO64 1 +_ACEOF + +fi +done + + ;; + esac fi ac_fn_c_check_func "$LINENO" "malloc" "ac_cv_func_malloc" @@ -19743,12 +19762,6 @@ if test "x$ac_cv_func_fseeko" = xyes then : printf "%s\n" "#define HAVE_FSEEKO 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "fseeko64" "ac_cv_func_fseeko64" -if test "x$ac_cv_func_fseeko64" = xyes -then : - printf "%s\n" "#define HAVE_FSEEKO64 1" >>confdefs.h - fi ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" if test "x$ac_cv_func_sigaction" = xyes diff --git a/configure.ac b/configure.ac index f2ca7e08a6c9b..088eac0dde875 100644 --- a/configure.ac +++ b/configure.ac @@ -359,7 +359,17 @@ dnl Checks for library functions. AC_DEFINE(HAVE_MPROTECT, 1, [ ]) ],[]), ) - AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv bsearch qsort abs bcopy memset memcmp memcpy memmove wcslen wcslcpy wcslcat _wcsdup wcsdup wcsstr wcscmp wcsncmp wcscasecmp _wcsicmp wcsncasecmp _wcsnicmp strlen strlcpy strlcat _strrev _strupr _strlwr index rindex strchr strrchr strstr strtok_r itoa _ltoa _uitoa _ultoa strtod strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp strcasestr vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction sigtimedwait setjmp nanosleep sysconf sysctlbyname getauxval elf_aux_info poll memfd_create posix_fallocate _Exit) + + case "$host" in + *-*-msdosdjgpp*) + AC_MSG_NOTICE(skipping unfinished fseeko64 in DJGPP) + ;; + *) + AC_CHECK_FUNCS(fseeko64) + ;; + esac + + AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv bsearch qsort abs bcopy memset memcmp memcpy memmove wcslen wcslcpy wcslcat _wcsdup wcsdup wcsstr wcscmp wcsncmp wcscasecmp _wcsicmp wcsncasecmp _wcsnicmp strlen strlcpy strlcat _strrev _strupr _strlwr index rindex strchr strrchr strstr strtok_r itoa _ltoa _uitoa _ultoa strtod strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp strcasestr vsscanf vsnprintf fopen64 fseeko sigaction sigtimedwait setjmp nanosleep sysconf sysctlbyname getauxval elf_aux_info poll memfd_create posix_fallocate _Exit) AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"]) AC_CHECK_FUNCS(acos acosf asin asinf atan atanf atan2 atan2f ceil ceilf copysign copysignf cos cosf exp expf fabs fabsf floor floorf trunc truncf fmod fmodf log logf log10 log10f lround lroundf pow powf round roundf scalbn scalbnf sin sinf sqrt sqrtf tan tanf) diff --git a/test/testfile.c b/test/testfile.c index 67ef4ae3b4942..f4e89f1c29bb6 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -152,7 +152,11 @@ int main(int argc, char *argv[]) RWOP_ERR_QUIT(rwops); } if (0 != rwops->read(rwops, test_buf, 1, 1)) { + #ifdef __DJGPP__ + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DJGPP allowed read on write only file\n"); + #else RWOP_ERR_QUIT(rwops); /* we are in write only mode */ + #endif } rwops->close(rwops); From 63f0003141120ae6d3849b734787c882cd43e334 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 23 Feb 2020 23:37:44 -0500 Subject: [PATCH 04/51] dos: Add support for basic timing functions Timers remain unsupported due to lack of multithreading. --- configure | 37 +++++++++++++++ configure.ac | 19 ++++++++ include/SDL_config.h.in | 2 + src/timer/dos/SDL_systimer.c | 87 ++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 src/timer/dos/SDL_systimer.c diff --git a/configure b/configure index 118cbe1d60d63..1dd4be4a7bc75 100755 --- a/configure +++ b/configure @@ -952,6 +952,7 @@ enable_wasapi enable_hidapi_joystick enable_hidapi_libusb enable_clock_gettime +enable_uclock enable_rpath enable_backgrounding_signal enable_foregrounding_signal @@ -1779,6 +1780,8 @@ Optional Features: --enable-clock_gettime use clock_gettime() instead of gettimeofday() on UNIX [default=yes] --enable-rpath use an rpath when linking SDL [default=yes] + --enable-uclock use uclock() for performance counter on DOS + [default=yes] --enable-backgrounding-signal number to use for magic backgrounding signal or 'no' [default=no] @@ -28566,6 +28569,30 @@ printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h fi } +CheckUCLOCK() +{ + # Check whether --enable-uclock was given. +if test "${enable_uclock+set}" = set; then : + enableval=$enable_uclock; +else + enable_uclock=yes +fi + + if test x$enable_uclock = xyes; then + for ac_func in uclock +do : + ac_fn_c_check_func "$LINENO" "uclock" "ac_cv_func_uclock" +if test "x$ac_cv_func_uclock" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UCLOCK 1 +_ACEOF + +fi +done + + fi +} + CheckLinuxVersion() { ac_fn_c_check_header_compile "$LINENO" "linux/version.h" "ac_cv_header_linux_version_h" "$ac_includes_default" @@ -29783,6 +29810,16 @@ printf "%s\n" "#define SDL_JOYSTICK_OS2 1" >>confdefs.h CheckDiskAudio CheckDummyAudio CheckDLOPEN + CheckUCLOCK + + # Set up files for the timer library + if test x$enable_timers = xyes; then + +$as_echo "#define SDL_TIMER_DOS 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/timer/dos/*.c" + have_timers=yes + fi ;; *) as_fn_error $? " diff --git a/configure.ac b/configure.ac index 088eac0dde875..0d217c33d7784 100644 --- a/configure.ac +++ b/configure.ac @@ -3704,6 +3704,17 @@ CheckClockGettime() fi } +dnl Check for uclock() +CheckUCLOCK() +{ + AC_ARG_ENABLE(uclock, +AS_HELP_STRING([--enable-uclock], [use uclock() for performance counter on DOS [[default=yes]]]), + , enable_uclock=yes) + if test x$enable_uclock = xyes; then + AC_CHECK_FUNCS(uclock) + fi +} + dnl Check for a valid linux/version.h CheckLinuxVersion() { @@ -4691,6 +4702,14 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works. --ryan. CheckDiskAudio CheckDummyAudio CheckDLOPEN + CheckUCLOCK + + # Set up files for the timer library + if test x$enable_timers = xyes; then + AC_DEFINE(SDL_TIMER_DOS, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/timer/dos/*.c" + have_timers=yes + fi ;; *) AC_MSG_ERROR([ diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 35281d158d869..b990d69be8576 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -202,6 +202,7 @@ #undef HAVE_SYSCONF #undef HAVE_SYSCTLBYNAME #undef HAVE_CLOCK_GETTIME +#undef HAVE_UCLOCK #undef HAVE_GETPAGESIZE #undef HAVE_MPROTECT #undef HAVE_ICONV @@ -370,6 +371,7 @@ #undef SDL_TIMER_UNIX #undef SDL_TIMER_WINDOWS #undef SDL_TIMER_OS2 +#undef SDL_TIMER_DOS /* Enable various video drivers */ #undef SDL_VIDEO_DRIVER_HAIKU diff --git a/src/timer/dos/SDL_systimer.c b/src/timer/dos/SDL_systimer.c new file mode 100644 index 0000000000000..90978059559a6 --- /dev/null +++ b/src/timer/dos/SDL_systimer.c @@ -0,0 +1,87 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if defined(SDL_TIMER_DOS) + +#include +#include + +#include "SDL_timer.h" + +static clock_t start; +static SDL_bool ticks_started = SDL_FALSE; + +void +SDL_TicksInit(void) +{ + if (ticks_started) { + return; + } + start = clock(); + ticks_started = SDL_TRUE; +} + +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + +Uint32 +SDL_GetTicks(void) +{ + if (!ticks_started) { + SDL_TicksInit(); + } + + return (clock() - start) * 1000 / CLOCKS_PER_SEC; +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ +#ifdef HAVE_UCLOCK + return uclock(); +#else + return SDL_GetTicks(); +#endif +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ +#ifdef HAVE_UCLOCK + return UCLOCKS_PER_SEC; +#else + return return 1000; +#endif +} + +void +SDL_Delay(Uint32 ms) +{ + delay(ms); +} + +#endif /* SDL_TIMER_DOS */ + +/* vi: set ts=4 sw=4 expandtab: */ From 1ae45fe0137500c6953d1194c7a2d2b9a12cabf1 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Thu, 27 Feb 2020 00:01:26 -0500 Subject: [PATCH 05/51] Create SVGA video driver (cloned from dummy driver) --- configure | 13 +++ configure.ac | 12 +++ include/SDL_config.h.in | 1 + src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 3 + src/video/svga/SDL_svgaevents.c | 38 ++++++++ src/video/svga/SDL_svgaevents_c.h | 33 +++++++ src/video/svga/SDL_svgaframebuffer.c | 89 ++++++++++++++++++ src/video/svga/SDL_svgaframebuffer_c.h | 33 +++++++ src/video/svga/SDL_svgavideo.c | 122 +++++++++++++++++++++++++ src/video/svga/SDL_svgavideo.h | 30 ++++++ 11 files changed, 375 insertions(+) create mode 100644 src/video/svga/SDL_svgaevents.c create mode 100644 src/video/svga/SDL_svgaevents_c.h create mode 100644 src/video/svga/SDL_svgaframebuffer.c create mode 100644 src/video/svga/SDL_svgaframebuffer_c.h create mode 100644 src/video/svga/SDL_svgavideo.c create mode 100644 src/video/svga/SDL_svgavideo.h diff --git a/configure b/configure index 1dd4be4a7bc75..055a05f8654b2 100755 --- a/configure +++ b/configure @@ -26000,6 +26000,18 @@ printf "%s\n" "#define SDL_AUDIO_DRIVER_QSA 1" >>confdefs.h fi } +CheckSVGAVideo() +{ + if test x$enable_video = xyes; then + +$as_echo "#define SDL_VIDEO_DRIVER_SVGA 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/video/svga/*.c" + have_video=yes + SUMMARY_video="${SUMMARY_video} svga" + fi +} + # Check whether --enable-video-opengl was given. if test ${enable_video_opengl+y} then : @@ -29809,6 +29821,7 @@ printf "%s\n" "#define SDL_JOYSTICK_OS2 1" >>confdefs.h CheckDummyVideo CheckDiskAudio CheckDummyAudio + CheckSVGAVideo CheckDLOPEN CheckUCLOCK diff --git a/configure.ac b/configure.ac index 0d217c33d7784..dc7e2a9c12123 100644 --- a/configure.ac +++ b/configure.ac @@ -2518,6 +2518,17 @@ CheckQNXAudio() fi } +dnl Set up the SVGA video driver if enabled +CheckSVGAVideo() +{ + if test x$enable_video = xyes; then + AC_DEFINE(SDL_VIDEO_DRIVER_SVGA, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/video/svga/*.c" + have_video=yes + SUMMARY_video="${SUMMARY_video} svga" + fi +} + dnl Check to see if OpenGL support is desired AC_ARG_ENABLE(video-opengl, [AS_HELP_STRING([--enable-video-opengl], [include OpenGL support [default=yes]])], @@ -4701,6 +4712,7 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works. --ryan. CheckDummyVideo CheckDiskAudio CheckDummyAudio + CheckSVGAVideo CheckDLOPEN CheckUCLOCK diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index b990d69be8576..e5a877892a2d5 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -418,6 +418,7 @@ #undef SDL_VIDEO_DRIVER_OS2 #undef SDL_VIDEO_DRIVER_QNX #undef SDL_VIDEO_DRIVER_RISCOS +#undef SDL_VIDEO_DRIVER_SVGA #undef SDL_VIDEO_RENDER_D3D #undef SDL_VIDEO_RENDER_D3D11 diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 1018fd78c12cb..014a5b7031545 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -481,6 +481,7 @@ extern VideoBootStrap NACL_bootstrap; extern VideoBootStrap VIVANTE_bootstrap; extern VideoBootStrap Emscripten_bootstrap; extern VideoBootStrap QNX_bootstrap; +extern VideoBootStrap SVGA_bootstrap; extern VideoBootStrap OFFSCREEN_bootstrap; extern VideoBootStrap NGAGE_bootstrap; extern VideoBootStrap OS2DIVE_bootstrap; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 4e22f28c580e7..717ca02298a29 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -143,6 +143,9 @@ static VideoBootStrap *bootstrap[] = { &OS2DIVE_bootstrap, &OS2VMAN_bootstrap, #endif +#if SDL_VIDEO_DRIVER_SVGA + &SVGA_bootstrap, +#endif #ifdef SDL_VIDEO_DRIVER_NGAGE &NGAGE_bootstrap, #endif diff --git a/src/video/svga/SDL_svgaevents.c b/src/video/svga/SDL_svgaevents.c new file mode 100644 index 0000000000000..8c743ecea7779 --- /dev/null +++ b/src/video/svga/SDL_svgaevents.c @@ -0,0 +1,38 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_SVGA + +#include "../../events/SDL_events_c.h" + +#include "SDL_svgavideo.h" +#include "SDL_svgaevents_c.h" + +void +SVGA_PumpEvents(_THIS) +{ + /* do nothing. */ +} + +#endif /* SDL_VIDEO_DRIVER_SVGA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgaevents_c.h b/src/video/svga/SDL_svgaevents_c.h new file mode 100644 index 0000000000000..849d6393b6bbb --- /dev/null +++ b/src/video/svga/SDL_svgaevents_c.h @@ -0,0 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_svgaevents_c_h_ +#define SDL_svgaevents_c_h_ + +#include "../../SDL_internal.h" + +#include "SDL_svgavideo.h" + +extern void SVGA_PumpEvents(_THIS); + +#endif /* SDL_svgaevents_c_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgaframebuffer.c b/src/video/svga/SDL_svgaframebuffer.c new file mode 100644 index 0000000000000..29b097ca62576 --- /dev/null +++ b/src/video/svga/SDL_svgaframebuffer.c @@ -0,0 +1,89 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_SVGA + +#include "../SDL_sysvideo.h" +#include "SDL_svgaframebuffer_c.h" + + +#define SVGA_SURFACE "_SDL_SVGASurface" + +int SDL_SVGA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) +{ + SDL_Surface *surface; + const Uint32 surface_format = SDL_PIXELFORMAT_INDEX8; + int w, h; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + /* Free the old framebuffer surface */ + surface = (SDL_Surface *) SDL_GetWindowData(window, SVGA_SURFACE); + SDL_FreeSurface(surface); + + /* Create a new one */ + SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + SDL_GetWindowSize(window, &w, &h); + surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask); + if (!surface) { + return -1; + } + + /* Save the info and return! */ + SDL_SetWindowData(window, SVGA_SURFACE, surface); + *format = surface_format; + *pixels = surface->pixels; + *pitch = surface->pitch; + return 0; +} + +int SDL_SVGA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) +{ + static int frame_number; + SDL_Surface *surface; + + surface = (SDL_Surface *) SDL_GetWindowData(window, SVGA_SURFACE); + if (!surface) { + return SDL_SetError("Couldn't find SVGA surface for window"); + } + + /* Send the data to the display */ + if (SDL_getenv("SDL_VIDEO_SVGA_SAVE_FRAMES")) { + char file[128]; + SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", + SDL_GetWindowID(window), ++frame_number); + SDL_SaveBMP(surface, file); + } + return 0; +} + +void SDL_SVGA_DestroyWindowFramebuffer(_THIS, SDL_Window * window) +{ + SDL_Surface *surface; + + surface = (SDL_Surface *) SDL_SetWindowData(window, SVGA_SURFACE, NULL); + SDL_FreeSurface(surface); +} + +#endif /* SDL_VIDEO_DRIVER_SVGA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgaframebuffer_c.h b/src/video/svga/SDL_svgaframebuffer_c.h new file mode 100644 index 0000000000000..76cbb37f4a4ae --- /dev/null +++ b/src/video/svga/SDL_svgaframebuffer_c.h @@ -0,0 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_svgaframebuffer_c_h_ +#define SDL_svgaframebuffer_c_h_ + +#include "../../SDL_internal.h" + +extern int SDL_SVGA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch); +extern int SDL_SVGA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); +extern void SDL_SVGA_DestroyWindowFramebuffer(_THIS, SDL_Window * window); + +#endif /* SDL_svgaframebuffer_c_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgavideo.c b/src/video/svga/SDL_svgavideo.c new file mode 100644 index 0000000000000..7a4f429acad34 --- /dev/null +++ b/src/video/svga/SDL_svgavideo.c @@ -0,0 +1,122 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_SVGA + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_svgavideo.h" +#include "SDL_svgaevents_c.h" +#include "SDL_svgaframebuffer_c.h" + +#define SVGAVID_DRIVER_NAME "svga" + +/* Initialization/Query functions */ +static int SVGA_VideoInit(_THIS); +static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +static void SVGA_VideoQuit(_THIS); + +/* SVGA driver bootstrap functions */ + +static int +SVGA_Available(void) +{ + return 1; +} + +static void +SVGA_DeleteDevice(SDL_VideoDevice * device) +{ + SDL_free(device); +} + +static SDL_VideoDevice * +SVGA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (!device) { + SDL_OutOfMemory(); + return 0; + } + + /* Set the function pointers */ + device->VideoInit = SVGA_VideoInit; + device->VideoQuit = SVGA_VideoQuit; + device->SetDisplayMode = SVGA_SetDisplayMode; + device->PumpEvents = SVGA_PumpEvents; + device->CreateWindowFramebuffer = SDL_SVGA_CreateWindowFramebuffer; + device->UpdateWindowFramebuffer = SDL_SVGA_UpdateWindowFramebuffer; + device->DestroyWindowFramebuffer = SDL_SVGA_DestroyWindowFramebuffer; + + device->free = SVGA_DeleteDevice; + + return device; +} + +VideoBootStrap SVGA_bootstrap = { + SVGAVID_DRIVER_NAME, "SDL SVGA video driver", + SVGA_Available, SVGA_CreateDevice +}; + + +int +SVGA_VideoInit(_THIS) +{ + SDL_DisplayMode mode; + + mode.format = SDL_PIXELFORMAT_INDEX8; + mode.w = 320; + mode.h = 200; + mode.refresh_rate = 0; + mode.driverdata = NULL; + if (SDL_AddBasicVideoDisplay(&mode) < 0) { + return -1; + } + + SDL_zero(mode); + SDL_AddDisplayMode(&_this->displays[0], &mode); + + /* We're done! */ + return 0; +} + +static int +SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + return 0; +} + +void +SVGA_VideoQuit(_THIS) +{ +} + +#endif /* SDL_VIDEO_DRIVER_SVGA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgavideo.h b/src/video/svga/SDL_svgavideo.h new file mode 100644 index 0000000000000..a23113eb3350b --- /dev/null +++ b/src/video/svga/SDL_svgavideo.h @@ -0,0 +1,30 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_svgavideo_h_ +#define SDL_svgavideo_h_ + +#include "../SDL_sysvideo.h" + +#endif /* SDL_svgavideo_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ From 3d40fe7b735ba9966dd4fc8cc0d487275fdf1fbe Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 29 Feb 2020 00:24:38 -0500 Subject: [PATCH 06/51] svga: Add VBE types --- src/video/svga/SDL_svga_vbe.h | 108 ++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/video/svga/SDL_svga_vbe.h diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h new file mode 100644 index 0000000000000..c93387586e8bf --- /dev/null +++ b/src/video/svga/SDL_svga_vbe.h @@ -0,0 +1,108 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_svga_vbe_h_ +#define SDL_svga_vbe_h_ + +#include "../SDL_sysvideo.h" + +#define VBE_SIGNATURE "VESA" + +typedef Uint32 VBEFarPtr; + +typedef struct VBEInfo { + char vbe_signature[4]; /* 'VESA' 4 byte signature */ + Uint16 vbe_version; /* VBE version number */ + VBEFarPtr oem_string_ptr; /* Pointer to OEM string */ + Uint32 capabilities; /* Capabilities of video card */ + VBEFarPtr video_mode_ptr; /* Pointer to supported modes */ + Uint16 total_memory; /* Number of 64kb memory blocks */ + + /* VBE 2.0 and above: */ + Uint16 oem_software_rev; /* OEM Software revision number */ + VBEFarPtr oem_vendor_name_ptr; /* Pointer to vendor name string */ + VBEFarPtr oem_product_name_ptr; /* Pointer to product name string */ + VBEFarPtr oem_product_rev_ptr; /* Pointer to product revision string */ + char reserved[222]; /* VBE implementatino scratch data */ + char oem_data[256]; /* Data for OEM strings */ +} __attribute__ ((packed)) VBEInfo; + +typedef struct VBEModeInfo { + Uint16 mode_attributes; /* Mode attributes */ + Uint8 win_a_attributes; /* Window A attributes */ + Uint8 win_b_attributes; /* Window B attributes */ + Uint16 win_granularity; /* Window granularity */ + Uint16 win_size; /* Window size */ + Uint16 win_a_segment; /* Window A start segment */ + Uint16 win_b_segment; /* Window B start segment */ + VBEFarPtr win_func_ptr; /* Pointer to window function */ + Uint16 bytes_per_scan_line; /* Bytes per scan line */ + + /* VBE 1.2 and above: */ + Uint16 x_resolution; /* Horizontal resolution in pixels or chars */ + Uint16 y_resolution; /* Vertical resolution in pixels or chars */ + Uint8 x_char_size; /* Character cell width in pixels */ + Uint8 y_char_size; /* Character cell height in pixels */ + Uint8 number_of_planes; /* Number of memory planes */ + Uint8 bits_per_pixel; /* Bits per pixel */ + Uint8 number_of_banks; /* Number of banks */ + Uint8 memory_model; /* Memory model type */ + Uint8 bank_size; /* Bank size in KiB */ + Uint8 number_of_image_pages; /* Number of images */ + Uint8 reserved; /* Reserved for page function */ + + /* Direct color fields (required for direct/6 and YUV/7 memory models) */ + Uint8 red_mask_size; /* Size of direct color red mask in bits */ + Uint8 red_field_position; /* Bit position of lsb of red mask */ + Uint8 green_mask_size; /* Size of direct color green mask in bits */ + Uint8 green_field_position; /* Bit position of lsb of green mask */ + Uint8 blue_mask_size; /* Size of direct color blue mask in bits */ + Uint8 blue_field_position; /* Bit position of lsb of blue mask */ + Uint8 rsvd_mask_size; /* Size of direct color reserved mask in bits */ + Uint8 rsvd_field_position; /* Bit position of lsb of reserved mask */ + Uint8 direct_color_mode_info; /* Direct color mode attributes */ + + /* VBE 2.0 and above: */ + VBEFarPtr phys_base_ptr; /* Physical address for flat frame buffer */ + Uint32 off_screen_mem_offset; /* Offset to start of off screen memory */ + Uint16 off_screen_mem_size; /* Amount of off screen memory in KiB */ + + /* VBE 3.0 and above: */ + Uint16 lin_bytes_per_scan_line; /* Bytes per scan line for linear modes */ + Uint8 bnk_number_of_image_pages; /* Number of images for banked modes */ + Uint8 lin_number_of_image_pages; /* Number of images for linear modes */ + Uint8 lin_red_mask_size; /* Size of direct color red mask (linear modes) */ + Uint8 lin_red_field_position; /* Bit position of lsb of red mask (linear modes) */ + Uint8 lin_green_mask_size; /* Size of direct color green mask (linear modes) */ + Uint8 lin_green_field_position; /* Bit position of lsb of green mask (linear modes) */ + Uint8 lin_blue_mask_size; /* Size of direct color blue mask (linear modes) */ + Uint8 lin_blue_field_position; /* Bit position of lsb of blue mask (linear modes) */ + Uint8 lin_rsvd_mask_size; /* Size of direct color reserved mask (linear modes) */ + Uint8 lin_rsvd_field_position; /* Bit position of lsb of reserved mask (linear modes) */ + Uint32 max_pixel_clock; /* Maximum pixel clock (in Hz) for graphics mode */ + + char reserved_end[189]; +} __attribute__ ((packed)) VBEModeInfo; + +#endif /* SDL_svga_vbe_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ From 0b4fd9d417fb4ac89c2292be28fb32322e53f89e Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 29 Feb 2020 00:37:38 -0500 Subject: [PATCH 07/51] svga: Tweak file names --- src/video/svga/{SDL_svgaevents.c => SDL_svga_events.c} | 4 ++-- src/video/svga/{SDL_svgaevents_c.h => SDL_svga_events.h} | 8 ++++---- .../{SDL_svgaframebuffer.c => SDL_svga_framebuffer.c} | 2 +- .../{SDL_svgaframebuffer_c.h => SDL_svga_framebuffer.h} | 6 +++--- src/video/svga/{SDL_svgavideo.c => SDL_svga_video.c} | 6 +++--- src/video/svga/{SDL_svgavideo.h => SDL_svga_video.h} | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) rename src/video/svga/{SDL_svgaevents.c => SDL_svga_events.c} (95%) rename src/video/svga/{SDL_svgaevents_c.h => SDL_svga_events.h} (90%) rename src/video/svga/{SDL_svgaframebuffer.c => SDL_svga_framebuffer.c} (98%) rename src/video/svga/{SDL_svgaframebuffer_c.h => SDL_svga_framebuffer.h} (92%) rename src/video/svga/{SDL_svgavideo.c => SDL_svga_video.c} (97%) rename src/video/svga/{SDL_svgavideo.h => SDL_svga_video.h} (92%) diff --git a/src/video/svga/SDL_svgaevents.c b/src/video/svga/SDL_svga_events.c similarity index 95% rename from src/video/svga/SDL_svgaevents.c rename to src/video/svga/SDL_svga_events.c index 8c743ecea7779..d3ba4e84a2d12 100644 --- a/src/video/svga/SDL_svgaevents.c +++ b/src/video/svga/SDL_svga_events.c @@ -24,8 +24,8 @@ #include "../../events/SDL_events_c.h" -#include "SDL_svgavideo.h" -#include "SDL_svgaevents_c.h" +#include "SDL_svga_video.h" +#include "SDL_svga_events.h" void SVGA_PumpEvents(_THIS) diff --git a/src/video/svga/SDL_svgaevents_c.h b/src/video/svga/SDL_svga_events.h similarity index 90% rename from src/video/svga/SDL_svgaevents_c.h rename to src/video/svga/SDL_svga_events.h index 849d6393b6bbb..c79258ed3920e 100644 --- a/src/video/svga/SDL_svgaevents_c.h +++ b/src/video/svga/SDL_svga_events.h @@ -19,15 +19,15 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SDL_svgaevents_c_h_ -#define SDL_svgaevents_c_h_ +#ifndef SDL_svga_events_h_ +#define SDL_svga_events_h_ #include "../../SDL_internal.h" -#include "SDL_svgavideo.h" +#include "SDL_svga_video.h" extern void SVGA_PumpEvents(_THIS); -#endif /* SDL_svgaevents_c_h_ */ +#endif /* SDL_svga_events_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgaframebuffer.c b/src/video/svga/SDL_svga_framebuffer.c similarity index 98% rename from src/video/svga/SDL_svgaframebuffer.c rename to src/video/svga/SDL_svga_framebuffer.c index 29b097ca62576..c363024fa2d98 100644 --- a/src/video/svga/SDL_svgaframebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -23,7 +23,7 @@ #if SDL_VIDEO_DRIVER_SVGA #include "../SDL_sysvideo.h" -#include "SDL_svgaframebuffer_c.h" +#include "SDL_svga_framebuffer.h" #define SVGA_SURFACE "_SDL_SVGASurface" diff --git a/src/video/svga/SDL_svgaframebuffer_c.h b/src/video/svga/SDL_svga_framebuffer.h similarity index 92% rename from src/video/svga/SDL_svgaframebuffer_c.h rename to src/video/svga/SDL_svga_framebuffer.h index 76cbb37f4a4ae..bd9c3f4afa7cc 100644 --- a/src/video/svga/SDL_svgaframebuffer_c.h +++ b/src/video/svga/SDL_svga_framebuffer.h @@ -19,8 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SDL_svgaframebuffer_c_h_ -#define SDL_svgaframebuffer_c_h_ +#ifndef SDL_svga_framebuffer_h_ +#define SDL_svga_framebuffer_h_ #include "../../SDL_internal.h" @@ -28,6 +28,6 @@ extern int SDL_SVGA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * extern int SDL_SVGA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); extern void SDL_SVGA_DestroyWindowFramebuffer(_THIS, SDL_Window * window); -#endif /* SDL_svgaframebuffer_c_h_ */ +#endif /* SDL_svga_framebuffer_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svgavideo.c b/src/video/svga/SDL_svga_video.c similarity index 97% rename from src/video/svga/SDL_svgavideo.c rename to src/video/svga/SDL_svga_video.c index 7a4f429acad34..ee9c9133f1999 100644 --- a/src/video/svga/SDL_svgavideo.c +++ b/src/video/svga/SDL_svga_video.c @@ -28,9 +28,9 @@ #include "../SDL_pixels_c.h" #include "../../events/SDL_events_c.h" -#include "SDL_svgavideo.h" -#include "SDL_svgaevents_c.h" -#include "SDL_svgaframebuffer_c.h" +#include "SDL_svga_video.h" +#include "SDL_svga_events.h" +#include "SDL_svga_framebuffer.h" #define SVGAVID_DRIVER_NAME "svga" diff --git a/src/video/svga/SDL_svgavideo.h b/src/video/svga/SDL_svga_video.h similarity index 92% rename from src/video/svga/SDL_svgavideo.h rename to src/video/svga/SDL_svga_video.h index a23113eb3350b..a006deab28a21 100644 --- a/src/video/svga/SDL_svgavideo.h +++ b/src/video/svga/SDL_svga_video.h @@ -20,11 +20,11 @@ */ #include "../../SDL_internal.h" -#ifndef SDL_svgavideo_h_ -#define SDL_svgavideo_h_ +#ifndef SDL_svga_video_h_ +#define SDL_svga_video_h_ #include "../SDL_sysvideo.h" -#endif /* SDL_svgavideo_h_ */ +#endif /* SDL_svga_video_h_ */ /* vi: set ts=4 sw=4 expandtab: */ From a55ec2b3d28cabe3012f3f397befa05742dc3eda Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 29 Feb 2020 01:42:19 -0500 Subject: [PATCH 08/51] svga: Read VBE info and require VBE 2.0 --- src/video/svga/SDL_svga_vbe.c | 73 +++++++++++++++++++++++++++++++++ src/video/svga/SDL_svga_vbe.h | 11 +++-- src/video/svga/SDL_svga_video.c | 10 ++++- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 src/video/svga/SDL_svga_vbe.c diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c new file mode 100644 index 0000000000000..e3de47845d5e6 --- /dev/null +++ b/src/video/svga/SDL_svga_vbe.c @@ -0,0 +1,73 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_SVGA + +#include "SDL_svga_vbe.h" + +#include +#include +#include +#include + +int +SDL_SVGA_GetVBEInfo(VBEInfo *info) +{ + __dpmi_regs r; + + dosmemput("VBE2", 4, __tb); + + r.x.ax = 0x4F00; + r.x.di = __tb_offset; + r.x.es = __tb_segment; + + __dpmi_int(0x10, &r); + + /* VBE not installed */ + if (r.h.al != 0x4F) { + return -1; + } + + /* VBE call failed */ + if (r.h.ah != 0) { + return r.h.ah; + } + + dosmemget(__tb, sizeof(*info), info); + + /* Unexpected signature */ + if (strncmp(info->vbe_signature, "VESA", 4) != 0) { + return -1; + } + + return 0; +} + +int +SDL_SVGA_GetVBEModeInfo(Uint16 mode, VBEModeInfo *info) +{ + return 0; +} + +#endif /* SDL_VIDEO_DRIVER_SVGA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index c93387586e8bf..089a3310e729b 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -25,11 +25,10 @@ #include "../SDL_sysvideo.h" -#define VBE_SIGNATURE "VESA" - typedef Uint32 VBEFarPtr; -typedef struct VBEInfo { +typedef struct VBEInfo +{ char vbe_signature[4]; /* 'VESA' 4 byte signature */ Uint16 vbe_version; /* VBE version number */ VBEFarPtr oem_string_ptr; /* Pointer to OEM string */ @@ -46,7 +45,8 @@ typedef struct VBEInfo { char oem_data[256]; /* Data for OEM strings */ } __attribute__ ((packed)) VBEInfo; -typedef struct VBEModeInfo { +typedef struct VBEModeInfo +{ Uint16 mode_attributes; /* Mode attributes */ Uint8 win_a_attributes; /* Window A attributes */ Uint8 win_b_attributes; /* Window B attributes */ @@ -103,6 +103,9 @@ typedef struct VBEModeInfo { char reserved_end[189]; } __attribute__ ((packed)) VBEModeInfo; +extern int SDL_SVGA_GetVBEInfo(VBEInfo *info); +extern int SDL_SVGA_GetVBEModeInfo(Uint16 mode, VBEModeInfo *info); + #endif /* SDL_svga_vbe_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index ee9c9133f1999..f91d645e55845 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -31,6 +31,7 @@ #include "SDL_svga_video.h" #include "SDL_svga_events.h" #include "SDL_svga_framebuffer.h" +#include "SDL_svga_vbe.h" #define SVGAVID_DRIVER_NAME "svga" @@ -44,7 +45,9 @@ static void SVGA_VideoQuit(_THIS); static int SVGA_Available(void) { - return 1; + VBEInfo info; + + return SDL_SVGA_GetVBEInfo(&info) == 0 && info.vbe_version >= 0x0200; } static void @@ -57,6 +60,11 @@ static SDL_VideoDevice * SVGA_CreateDevice(int devindex) { SDL_VideoDevice *device; + VBEInfo info; + + if (SDL_SVGA_GetVBEInfo(&info) || info.vbe_version < 0x0200) { + return 0; + } /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); From 773715c1f58d9a2c14d9ea9fdfcbbc834d94a3a6 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 1 Mar 2020 21:14:39 -0500 Subject: [PATCH 09/51] svga: Use structs for special VBE fields --- src/video/svga/SDL_svga_vbe.h | 12 ++++++++++-- src/video/svga/SDL_svga_video.c | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 089a3310e729b..4da91f86a20d4 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -25,12 +25,20 @@ #include "../SDL_sysvideo.h" -typedef Uint32 VBEFarPtr; +typedef struct VBEFarPtr { + Uint16 offset; + Uint16 segment; +} __attribute__ ((packed)) VBEFarPtr; + +typedef struct VBEVersion { + Uint8 minor; + Uint8 major; +} __attribute__ ((packed)) VBEVersion; typedef struct VBEInfo { char vbe_signature[4]; /* 'VESA' 4 byte signature */ - Uint16 vbe_version; /* VBE version number */ + VBEVersion vbe_version; /* VBE version number */ VBEFarPtr oem_string_ptr; /* Pointer to OEM string */ Uint32 capabilities; /* Capabilities of video card */ VBEFarPtr video_mode_ptr; /* Pointer to supported modes */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index f91d645e55845..864a5db5d6ffa 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -47,7 +47,7 @@ SVGA_Available(void) { VBEInfo info; - return SDL_SVGA_GetVBEInfo(&info) == 0 && info.vbe_version >= 0x0200; + return SDL_SVGA_GetVBEInfo(&info) == 0 && info.vbe_version.major >= 2; } static void @@ -62,7 +62,7 @@ SVGA_CreateDevice(int devindex) SDL_VideoDevice *device; VBEInfo info; - if (SDL_SVGA_GetVBEInfo(&info) || info.vbe_version < 0x0200) { + if (SDL_SVGA_GetVBEInfo(&info) || info.vbe_version.major < 2) { return 0; } From 8236e8ad0b81ce8eeffd69c4ece8915ee651a7d3 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 1 Mar 2020 22:16:11 -0500 Subject: [PATCH 10/51] svga: Assert VBE struct sizes at compile time --- src/video/svga/SDL_svga_vbe.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 4da91f86a20d4..640d5e1f0e536 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -30,14 +30,18 @@ typedef struct VBEFarPtr { Uint16 segment; } __attribute__ ((packed)) VBEFarPtr; +SDL_COMPILE_TIME_ASSERT(VBEFarPtr, sizeof(VBEFarPtr) == 4); + typedef struct VBEVersion { Uint8 minor; Uint8 major; } __attribute__ ((packed)) VBEVersion; +SDL_COMPILE_TIME_ASSERT(VBEVersion, sizeof(VBEVersion) == 2); + typedef struct VBEInfo { - char vbe_signature[4]; /* 'VESA' 4 byte signature */ + char vbe_signature[4]; /* "VESA" 4 byte signature */ VBEVersion vbe_version; /* VBE version number */ VBEFarPtr oem_string_ptr; /* Pointer to OEM string */ Uint32 capabilities; /* Capabilities of video card */ @@ -49,10 +53,12 @@ typedef struct VBEInfo VBEFarPtr oem_vendor_name_ptr; /* Pointer to vendor name string */ VBEFarPtr oem_product_name_ptr; /* Pointer to product name string */ VBEFarPtr oem_product_rev_ptr; /* Pointer to product revision string */ - char reserved[222]; /* VBE implementatino scratch data */ + Uint8 reserved[222]; /* VBE implementation scratch data */ char oem_data[256]; /* Data for OEM strings */ } __attribute__ ((packed)) VBEInfo; +SDL_COMPILE_TIME_ASSERT(VBEInfo, sizeof(VBEInfo) == 512); + typedef struct VBEModeInfo { Uint16 mode_attributes; /* Mode attributes */ @@ -108,9 +114,11 @@ typedef struct VBEModeInfo Uint8 lin_rsvd_field_position; /* Bit position of lsb of reserved mask (linear modes) */ Uint32 max_pixel_clock; /* Maximum pixel clock (in Hz) for graphics mode */ - char reserved_end[189]; + Uint8 reserved_end[190]; } __attribute__ ((packed)) VBEModeInfo; +SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); + extern int SDL_SVGA_GetVBEInfo(VBEInfo *info); extern int SDL_SVGA_GetVBEModeInfo(Uint16 mode, VBEModeInfo *info); From 58edca8ce4c44273c2a42cdda68212289135ce94 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Mon, 2 Mar 2020 00:16:31 -0500 Subject: [PATCH 11/51] svga: Implement `GetVBEModeInfo` --- src/video/svga/SDL_svga_vbe.c | 42 ++++++++++++++++++++++++++--------- src/video/svga/SDL_svga_vbe.h | 7 +++++- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index e3de47845d5e6..47359baf8b342 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -29,6 +29,12 @@ #include #include +/* Check the DPMI registers for an error after a VBE function call. */ +/* Returns -1 if VBE is not installed or the non-zero VBE error code. */ +#define RETURN_IF_VBE_CALL_FAILED(regs) \ + if ((regs).h.al != 0x4F) return -1; \ + if ((regs).h.ah != 0) return (regs).h.ah; + int SDL_SVGA_GetVBEInfo(VBEInfo *info) { @@ -42,15 +48,7 @@ SDL_SVGA_GetVBEInfo(VBEInfo *info) __dpmi_int(0x10, &r); - /* VBE not installed */ - if (r.h.al != 0x4F) { - return -1; - } - - /* VBE call failed */ - if (r.h.ah != 0) { - return r.h.ah; - } + RETURN_IF_VBE_CALL_FAILED(r); dosmemget(__tb, sizeof(*info), info); @@ -62,9 +60,33 @@ SDL_SVGA_GetVBEInfo(VBEInfo *info) return 0; } +VBEMode +SDL_SVGA_GetVBEModeAtIndex(const VBEInfo *info, int index) +{ + VBEMode mode; + VBEFarPtr ptr = info->video_mode_ptr; + + dosmemget(ptr.segment * 16 + ptr.offset + index * sizeof(mode), sizeof(mode), &mode); + + return mode; +} + int -SDL_SVGA_GetVBEModeInfo(Uint16 mode, VBEModeInfo *info) +SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info) { + __dpmi_regs r; + + r.x.ax = 0x4F01; + r.x.cx = mode; + r.x.di = __tb_offset; + r.x.es = __tb_segment; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + dosmemget(__tb, sizeof(*info), info); + return 0; } diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 640d5e1f0e536..a377a90c2ba3c 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -25,6 +25,10 @@ #include "../SDL_sysvideo.h" +typedef Uint16 VBEMode; + +#define VBE_MODE_LIST_END 0xFFFF + typedef struct VBEFarPtr { Uint16 offset; Uint16 segment; @@ -120,7 +124,8 @@ typedef struct VBEModeInfo SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); extern int SDL_SVGA_GetVBEInfo(VBEInfo *info); -extern int SDL_SVGA_GetVBEModeInfo(Uint16 mode, VBEModeInfo *info); +extern VBEMode SDL_SVGA_GetVBEModeAtIndex(const VBEInfo *info, int index); +extern int SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info); #endif /* SDL_svga_vbe_h_ */ From 7906114f33884ddcc1e55be07a0429ca90a83b71 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Tue, 3 Mar 2020 01:23:00 -0500 Subject: [PATCH 12/51] svga: Add `GetCurrentVBEMode` --- src/video/svga/SDL_svga_vbe.c | 20 ++++++++++++++++++++ src/video/svga/SDL_svga_vbe.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 47359baf8b342..8d107ba23996f 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -90,6 +90,26 @@ SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info) return 0; } +int +SDL_SVGA_GetCurrentVBEMode(VBEMode *mode, VBEModeInfo *info) +{ + __dpmi_regs r; + + r.x.ax = 0x4F03; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + *mode = r.x.bx & 0x3FFF; /* High bits are flags */ + + if (!info) { + return 0; + } + + return SDL_SVGA_GetVBEModeInfo(*mode, info); +} + #endif /* SDL_VIDEO_DRIVER_SVGA */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index a377a90c2ba3c..b541688a27182 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -126,6 +126,7 @@ SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); extern int SDL_SVGA_GetVBEInfo(VBEInfo *info); extern VBEMode SDL_SVGA_GetVBEModeAtIndex(const VBEInfo *info, int index); extern int SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info); +extern int SDL_SVGA_GetCurrentVBEMode(VBEMode *mode, VBEModeInfo *info); #endif /* SDL_svga_vbe_h_ */ From 4e0797aa4bb3e6c03665e10c85c549abdfdef8f1 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Tue, 3 Mar 2020 01:24:55 -0500 Subject: [PATCH 13/51] svga: Implement `GetDisplayModes` --- src/video/svga/SDL_svga_video.c | 82 +++++++++++++++++++++++++-------- src/video/svga/SDL_svga_video.h | 14 ++++++ 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 864a5db5d6ffa..55df8b34079af 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -31,12 +31,12 @@ #include "SDL_svga_video.h" #include "SDL_svga_events.h" #include "SDL_svga_framebuffer.h" -#include "SDL_svga_vbe.h" #define SVGAVID_DRIVER_NAME "svga" /* Initialization/Query functions */ static int SVGA_VideoInit(_THIS); +static void SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display); static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); static void SVGA_VideoQuit(_THIS); @@ -60,22 +60,33 @@ static SDL_VideoDevice * SVGA_CreateDevice(int devindex) { SDL_VideoDevice *device; - VBEInfo info; + SDL_DeviceData *devdata; + + devdata = (SDL_DeviceData *) SDL_calloc(1, sizeof(*devdata)); + if (!devdata) { + SDL_OutOfMemory(); + return NULL; + } - if (SDL_SVGA_GetVBEInfo(&info) || info.vbe_version.major < 2) { - return 0; + if (SDL_SVGA_GetVBEInfo(&devdata->vbe_info) || devdata->vbe_info.vbe_version.major < 2) { + SDL_free(devdata); + return NULL; } /* Initialize all variables that we clean on shutdown */ - device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); + device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(*device)); if (!device) { + SDL_free(devdata); SDL_OutOfMemory(); - return 0; + return NULL; } + device->driverdata = devdata; + /* Set the function pointers */ device->VideoInit = SVGA_VideoInit; device->VideoQuit = SVGA_VideoQuit; + device->GetDisplayModes = SVGA_GetDisplayModes; device->SetDisplayMode = SVGA_SetDisplayMode; device->PumpEvents = SVGA_PumpEvents; device->CreateWindowFramebuffer = SDL_SVGA_CreateWindowFramebuffer; @@ -92,28 +103,62 @@ VideoBootStrap SVGA_bootstrap = { SVGA_Available, SVGA_CreateDevice }; - int SVGA_VideoInit(_THIS) { - SDL_DisplayMode mode; - - mode.format = SDL_PIXELFORMAT_INDEX8; - mode.w = 320; - mode.h = 200; - mode.refresh_rate = 0; - mode.driverdata = NULL; - if (SDL_AddBasicVideoDisplay(&mode) < 0) { + /* TODO: Query for current mode. */ + + if (SDL_AddBasicVideoDisplay(NULL) < 0) { return -1; } - SDL_zero(mode); - SDL_AddDisplayMode(&_this->displays[0], &mode); + /* TODO: Save original video state. */ - /* We're done! */ return 0; } +static void +SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + SDL_DeviceData *devdata = _this->driverdata; + VBEMode vbe_mode; + int index = 0; + + vbe_mode = SDL_SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); + + while (vbe_mode != VBE_MODE_LIST_END) { + SDL_DisplayMode mode; + SDL_DisplayModeData *modedata; + VBEModeInfo info; + + if (SDL_SVGA_GetVBEModeInfo(vbe_mode, &info)) { + return; + } + + /* TODO: Filter out banked memory and weird color formats. */ + + modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(*modedata)); + if (!modedata) { + return; + } + + mode.w = info.x_resolution; + mode.h = info.y_resolution; + mode.format = SDL_PIXELFORMAT_INDEX8; /* FIXME: Select correct color format. */ + mode.refresh_rate = 0; + mode.driverdata = modedata; + modedata->vbe_mode = vbe_mode; + modedata->framebuffer_phys_addr = (void *)(info.phys_base_ptr.segment * 16 + info.phys_base_ptr.offset); + modedata->framebuffer_size = 0x1000; /* FIXME: Set correct framebuffer memory size. */ + + if (!SDL_AddDisplayMode(display, &mode)) { + SDL_free(modedata); + } + + vbe_mode = SDL_SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); + } +} + static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) { @@ -123,6 +168,7 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) void SVGA_VideoQuit(_THIS) { + /* TODO: Restore original video state. */ } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index a006deab28a21..406b1ec702529 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -25,6 +25,20 @@ #include "../SDL_sysvideo.h" +#include "SDL_svga_vbe.h" + +typedef struct +{ + VBEInfo vbe_info; +} SDL_DeviceData; + +typedef struct +{ + VBEMode vbe_mode; + void *framebuffer_phys_addr; + size_t framebuffer_size; +} SDL_DisplayModeData; + #endif /* SDL_svga_video_h_ */ /* vi: set ts=4 sw=4 expandtab: */ From 3d99753746dc912a962bd88b6a22251e2b081ddf Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Tue, 3 Mar 2020 01:32:46 -0500 Subject: [PATCH 14/51] svga: Remove `SDL` prefix from VBE functions A few other minor style things were tweaked too. --- src/video/svga/SDL_svga_vbe.c | 10 +++++----- src/video/svga/SDL_svga_vbe.h | 8 ++++---- src/video/svga/SDL_svga_video.c | 14 +++++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 8d107ba23996f..8b8a01071fd2e 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -36,7 +36,7 @@ if ((regs).h.ah != 0) return (regs).h.ah; int -SDL_SVGA_GetVBEInfo(VBEInfo *info) +SVGA_GetVBEInfo(VBEInfo * info) { __dpmi_regs r; @@ -61,7 +61,7 @@ SDL_SVGA_GetVBEInfo(VBEInfo *info) } VBEMode -SDL_SVGA_GetVBEModeAtIndex(const VBEInfo *info, int index) +SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index) { VBEMode mode; VBEFarPtr ptr = info->video_mode_ptr; @@ -72,7 +72,7 @@ SDL_SVGA_GetVBEModeAtIndex(const VBEInfo *info, int index) } int -SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info) +SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info) { __dpmi_regs r; @@ -91,7 +91,7 @@ SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info) } int -SDL_SVGA_GetCurrentVBEMode(VBEMode *mode, VBEModeInfo *info) +SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info) { __dpmi_regs r; @@ -107,7 +107,7 @@ SDL_SVGA_GetCurrentVBEMode(VBEMode *mode, VBEModeInfo *info) return 0; } - return SDL_SVGA_GetVBEModeInfo(*mode, info); + return SVGA_GetVBEModeInfo(*mode, info); } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index b541688a27182..bc01d86bc943f 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -123,10 +123,10 @@ typedef struct VBEModeInfo SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); -extern int SDL_SVGA_GetVBEInfo(VBEInfo *info); -extern VBEMode SDL_SVGA_GetVBEModeAtIndex(const VBEInfo *info, int index); -extern int SDL_SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo *info); -extern int SDL_SVGA_GetCurrentVBEMode(VBEMode *mode, VBEModeInfo *info); +extern int SVGA_GetVBEInfo(VBEInfo * info); +extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); +extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); +extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 55df8b34079af..2d47e96cb3a13 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -47,7 +47,7 @@ SVGA_Available(void) { VBEInfo info; - return SDL_SVGA_GetVBEInfo(&info) == 0 && info.vbe_version.major >= 2; + return SVGA_GetVBEInfo(&info) == 0 && info.vbe_version.major >= 2; } static void @@ -68,7 +68,7 @@ SVGA_CreateDevice(int devindex) return NULL; } - if (SDL_SVGA_GetVBEInfo(&devdata->vbe_info) || devdata->vbe_info.vbe_version.major < 2) { + if (SVGA_GetVBEInfo(&devdata->vbe_info) || devdata->vbe_info.vbe_version.major < 2) { SDL_free(devdata); return NULL; } @@ -103,7 +103,7 @@ VideoBootStrap SVGA_bootstrap = { SVGA_Available, SVGA_CreateDevice }; -int +static int SVGA_VideoInit(_THIS) { /* TODO: Query for current mode. */ @@ -124,14 +124,14 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) VBEMode vbe_mode; int index = 0; - vbe_mode = SDL_SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); + vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); while (vbe_mode != VBE_MODE_LIST_END) { SDL_DisplayMode mode; SDL_DisplayModeData *modedata; VBEModeInfo info; - if (SDL_SVGA_GetVBEModeInfo(vbe_mode, &info)) { + if (SVGA_GetVBEModeInfo(vbe_mode, &info)) { return; } @@ -155,7 +155,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) SDL_free(modedata); } - vbe_mode = SDL_SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); + vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); } } @@ -165,7 +165,7 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) return 0; } -void +static void SVGA_VideoQuit(_THIS) { /* TODO: Restore original video state. */ From 3dcab18a514db2b8c22fae7e0f839c80d1052801 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Tue, 3 Mar 2020 22:09:29 -0500 Subject: [PATCH 15/51] svga: Only use color graphics modes with linear memory --- src/video/svga/SDL_svga_vbe.h | 9 +++++++++ src/video/svga/SDL_svga_video.c | 22 ++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index bc01d86bc943f..60173c3ded15c 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -123,6 +123,15 @@ typedef struct VBEModeInfo SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); +/* Mode attribute bit flags */ +#define VBE_MODE_ATTR_HARDWARE_SUPPORT 0x0001 +#define VBE_MODE_ATTR_TTY_BIOS_SUPPORT 0x0004 +#define VBE_MODE_ATTR_COLOR_MODE 0x0008 +#define VBE_MODE_ATTR_GRAPHICS_MODE 0x0010 +#define VBE_MODE_ATTR_NO_VGA_COMPAT 0x0020 +#define VBE_MODE_ATTR_NO_WINDOWED_MEM 0x0040 +#define VBE_MODE_ATTR_LINEAR_MEM_AVAIL 0x0080 + extern int SVGA_GetVBEInfo(VBEInfo * info); extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 2d47e96cb3a13..e58c9e5c5be99 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -34,6 +34,13 @@ #define SVGAVID_DRIVER_NAME "svga" +/* Mandatory mode attributes */ +#define VBE_MODE_ATTRS ( \ + VBE_MODE_ATTR_COLOR_MODE | \ + VBE_MODE_ATTR_GRAPHICS_MODE | \ + VBE_MODE_ATTR_LINEAR_MEM_AVAIL \ +) + /* Initialization/Query functions */ static int SVGA_VideoInit(_THIS); static void SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display); @@ -124,9 +131,11 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) VBEMode vbe_mode; int index = 0; - vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); - - while (vbe_mode != VBE_MODE_LIST_END) { + for ( + vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); + vbe_mode != VBE_MODE_LIST_END; + vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++) + ) { SDL_DisplayMode mode; SDL_DisplayModeData *modedata; VBEModeInfo info; @@ -135,7 +144,10 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) return; } - /* TODO: Filter out banked memory and weird color formats. */ + /* Mode must support color graphics with a linear framebuffer. */ + if ((info.mode_attributes & VBE_MODE_ATTRS) != VBE_MODE_ATTRS) { + continue; + } modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(*modedata)); if (!modedata) { @@ -154,8 +166,6 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) if (!SDL_AddDisplayMode(display, &mode)) { SDL_free(modedata); } - - vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); } } From b6943f3260177e7b9cc35f63791bd9ea74067031 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Tue, 3 Mar 2020 23:04:26 -0500 Subject: [PATCH 16/51] svga: Convert from VBE to SDL pixel format This implementation is probably wrong, but it lays the foundation for doing it better, eventually. --- src/video/svga/SDL_svga_vbe.c | 22 ++++++++++++++++++++++ src/video/svga/SDL_svga_vbe.h | 11 +++++++++++ src/video/svga/SDL_svga_video.c | 15 ++++++++------- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 8b8a01071fd2e..e95591a1ba580 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -110,6 +110,28 @@ SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info) return SVGA_GetVBEModeInfo(*mode, info); } +SDL_PixelFormatEnum +SVGA_ConvertPixelFormat(const VBEModeInfo * info) +{ + if (info->memory_model == VBE_MEM_MODEL_PACKED) { + switch (info->bits_per_pixel) { + /* FIXME: Is it MSB or LSB? */ + case 1: return SDL_PIXELFORMAT_INDEX1MSB; + case 4: return SDL_PIXELFORMAT_INDEX4MSB; + case 8: return SDL_PIXELFORMAT_INDEX8; + } + } else if (info->memory_model == VBE_MEM_MODEL_DIRECT) { + switch (info->bits_per_pixel) { + /* FIXME: Check the color component field positions and size. */ + case 8: return SDL_PIXELFORMAT_RGB332; + case 15: return SDL_PIXELFORMAT_RGB555; + case 16: return SDL_PIXELFORMAT_RGB565; + case 32: return SDL_PIXELFORMAT_RGB888; + } + } + return SDL_PIXELFORMAT_UNKNOWN; +} + #endif /* SDL_VIDEO_DRIVER_SVGA */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 60173c3ded15c..f851ce894321c 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -132,10 +132,21 @@ SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); #define VBE_MODE_ATTR_NO_WINDOWED_MEM 0x0040 #define VBE_MODE_ATTR_LINEAR_MEM_AVAIL 0x0080 +/* Memory model values */ +#define VBE_MEM_MODEL_TEXT 0 +#define VBE_MEM_MODEL_CGA 1 +#define VBE_MEM_MODEL_HERCULES 2 +#define VBE_MEM_MODEL_PLANAR 3 +#define VBE_MEM_MODEL_PACKED 4 +#define VBE_MEM_MODEL_UNCHAINED 5 +#define VBE_MEM_MODEL_DIRECT 6 +#define VBE_MEM_MODEL_YUV 7 + extern int SVGA_GetVBEInfo(VBEInfo * info); extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); +extern SDL_PixelFormatEnum SVGA_ConvertPixelFormat(const VBEModeInfo * info); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index e58c9e5c5be99..e26faa3896d1e 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -35,11 +35,7 @@ #define SVGAVID_DRIVER_NAME "svga" /* Mandatory mode attributes */ -#define VBE_MODE_ATTRS ( \ - VBE_MODE_ATTR_COLOR_MODE | \ - VBE_MODE_ATTR_GRAPHICS_MODE | \ - VBE_MODE_ATTR_LINEAR_MEM_AVAIL \ -) +#define VBE_MODE_ATTRS (VBE_MODE_ATTR_GRAPHICS_MODE | VBE_MODE_ATTR_LINEAR_MEM_AVAIL) /* Initialization/Query functions */ static int SVGA_VideoInit(_THIS); @@ -144,11 +140,17 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) return; } - /* Mode must support color graphics with a linear framebuffer. */ + /* Mode must support graphics with a linear framebuffer. */ if ((info.mode_attributes & VBE_MODE_ATTRS) != VBE_MODE_ATTRS) { continue; } + /* Mode must be a known pixel format. */ + mode.format = SVGA_ConvertPixelFormat(&info); + if (mode.format == SDL_PIXELFORMAT_UNKNOWN) { + continue; + } + modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(*modedata)); if (!modedata) { return; @@ -156,7 +158,6 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) mode.w = info.x_resolution; mode.h = info.y_resolution; - mode.format = SDL_PIXELFORMAT_INDEX8; /* FIXME: Select correct color format. */ mode.refresh_rate = 0; mode.driverdata = modedata; modedata->vbe_mode = vbe_mode; From c65fdad222ed5204493deac818ac7187c3098b7c Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Wed, 4 Mar 2020 00:26:58 -0500 Subject: [PATCH 17/51] svga: Add SetVBEMode --- src/video/svga/SDL_svga_vbe.c | 22 +++++++++++++++++++++- src/video/svga/SDL_svga_vbe.h | 1 + src/video/svga/SDL_svga_video.c | 5 ++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index e95591a1ba580..9a428a1e3106a 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -101,7 +101,7 @@ SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info) RETURN_IF_VBE_CALL_FAILED(r); - *mode = r.x.bx & 0x3FFF; /* High bits are flags */ + *mode = r.x.bx & 0x3FFF; /* High bits are status flags. */ if (!info) { return 0; @@ -110,6 +110,26 @@ SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info) return SVGA_GetVBEModeInfo(*mode, info); } +int +SVGA_SetVBEMode(VBEMode mode) +{ + __dpmi_regs r; + + mode &= 0x01FF; /* Mode number bit mask. */ + mode |= 0x4000; /* Linear frame buffer flag. */ + + r.x.ax = 0x4F02; + r.x.bx = mode; + r.x.es = 0; + r.x.di = 0; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + return 0; +} + SDL_PixelFormatEnum SVGA_ConvertPixelFormat(const VBEModeInfo * info) { diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index f851ce894321c..6db1e5ab2488c 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -146,6 +146,7 @@ extern int SVGA_GetVBEInfo(VBEInfo * info); extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); +extern int SVGA_SetVBEMode(VBEMode mode); extern SDL_PixelFormatEnum SVGA_ConvertPixelFormat(const VBEModeInfo * info); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index e26faa3896d1e..40b9f44d0c000 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -173,7 +173,10 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) { - return 0; + SDL_DisplayModeData *modedata = mode->driverdata; + + /* TODO: Use SDL_SetError. */ + return SVGA_SetVBEMode(modedata->vbe_mode) == 0 ? 0 : -1; } static void From c0707493d460c1a4af58ed7c5b7ecac3d045ad56 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Wed, 18 Mar 2020 23:11:02 -0400 Subject: [PATCH 18/51] WIP: svga: Implement framebuffer functions --- src/video/svga/SDL_svga_framebuffer.c | 79 +++++++++++++++++---------- src/video/svga/SDL_svga_framebuffer.h | 6 +- src/video/svga/SDL_svga_vbe.c | 4 +- src/video/svga/SDL_svga_vbe.h | 2 +- src/video/svga/SDL_svga_video.c | 18 +++--- src/video/svga/SDL_svga_video.h | 1 + test/testdrawchessboard.c | 2 +- 7 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index c363024fa2d98..7312e8fa07eba 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -22,66 +22,85 @@ #if SDL_VIDEO_DRIVER_SVGA -#include "../SDL_sysvideo.h" -#include "SDL_svga_framebuffer.h" - +#include +#include -#define SVGA_SURFACE "_SDL_SVGASurface" +#include "SDL_svga_video.h" +#include "SDL_svga_framebuffer.h" -int SDL_SVGA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) +int +SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) { + SDL_DeviceData *devdata = _this->driverdata; SDL_Surface *surface; - const Uint32 surface_format = SDL_PIXELFORMAT_INDEX8; + Uint32 surface_format = SDL_GetWindowPixelFormat(window); int w, h; - int bpp; - Uint32 Rmask, Gmask, Bmask, Amask; /* Free the old framebuffer surface */ - surface = (SDL_Surface *) SDL_GetWindowData(window, SVGA_SURFACE); - SDL_FreeSurface(surface); + SDL_SVGA_DestroyFramebuffer(_this, window); - /* Create a new one */ - SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + /* Create a new surface */ SDL_GetWindowSize(window, &w, &h); - surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask); + surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, surface_format); if (!surface) { return -1; } /* Save the info and return! */ - SDL_SetWindowData(window, SVGA_SURFACE, surface); + devdata->surface = surface; *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; return 0; } -int SDL_SVGA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) +int +SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) { - static int frame_number; - SDL_Surface *surface; + SDL_DeviceData *devdata = _this->driverdata; + SDL_DisplayMode mode; + SDL_DisplayModeData *modedata; + SDL_Surface *surface = devdata->surface; + + Uint8 *buf; + __dpmi_meminfo mapping; - surface = (SDL_Surface *) SDL_GetWindowData(window, SVGA_SURFACE); if (!surface) { - return SDL_SetError("Couldn't find SVGA surface for window"); + return SDL_SetError("Missing SVGA surface"); + } + + /* TODO: Copy to back buffer and swap to screen */ + + if (SDL_GetWindowDisplayMode(window, &mode)) { + return -1; } - /* Send the data to the display */ - if (SDL_getenv("SDL_VIDEO_SVGA_SAVE_FRAMES")) { - char file[128]; - SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", - SDL_GetWindowID(window), ++frame_number); - SDL_SaveBMP(surface, file); + modedata = mode.driverdata; + mapping.address = (uintptr_t)modedata->framebuffer_phys_addr; + mapping.size = modedata->framebuffer_size; + + if (__dpmi_physical_address_mapping(&mapping)) { + return -1; } + + if (!__djgpp_nearptr_enable()) { + return -1; + } + + buf = (Uint8 *)(mapping.address + __djgpp_conventional_base); + + /* TODO: Use a blit function? */ + SDL_memcpy(buf, surface->pixels, surface->w * surface->h * surface->format->BytesPerPixel); + return 0; } -void SDL_SVGA_DestroyWindowFramebuffer(_THIS, SDL_Window * window) +void +SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window) { - SDL_Surface *surface; - - surface = (SDL_Surface *) SDL_SetWindowData(window, SVGA_SURFACE, NULL); - SDL_FreeSurface(surface); + SDL_DeviceData *devdata = _this->driverdata; + SDL_FreeSurface(devdata->surface); + devdata->surface = NULL; } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_framebuffer.h b/src/video/svga/SDL_svga_framebuffer.h index bd9c3f4afa7cc..3932d20cc5d89 100644 --- a/src/video/svga/SDL_svga_framebuffer.h +++ b/src/video/svga/SDL_svga_framebuffer.h @@ -24,9 +24,9 @@ #include "../../SDL_internal.h" -extern int SDL_SVGA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch); -extern int SDL_SVGA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); -extern void SDL_SVGA_DestroyWindowFramebuffer(_THIS, SDL_Window * window); +extern int SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch); +extern int SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); +extern void SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window); #endif /* SDL_svga_framebuffer_h_ */ diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 9a428a1e3106a..31edaf79496dd 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -131,7 +131,7 @@ SVGA_SetVBEMode(VBEMode mode) } SDL_PixelFormatEnum -SVGA_ConvertPixelFormat(const VBEModeInfo * info) +SVGA_GetPixelFormat(const VBEModeInfo * info) { if (info->memory_model == VBE_MEM_MODEL_PACKED) { switch (info->bits_per_pixel) { @@ -142,7 +142,7 @@ SVGA_ConvertPixelFormat(const VBEModeInfo * info) } } else if (info->memory_model == VBE_MEM_MODEL_DIRECT) { switch (info->bits_per_pixel) { - /* FIXME: Check the color component field positions and size. */ + /* FIXME: Use SDL_MasksToPixelFormatEnum. */ case 8: return SDL_PIXELFORMAT_RGB332; case 15: return SDL_PIXELFORMAT_RGB555; case 16: return SDL_PIXELFORMAT_RGB565; diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 6db1e5ab2488c..74c413cc9fbbb 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -147,7 +147,7 @@ extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); extern int SVGA_SetVBEMode(VBEMode mode); -extern SDL_PixelFormatEnum SVGA_ConvertPixelFormat(const VBEModeInfo * info); +extern SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 40b9f44d0c000..fda9b28c865ee 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -92,9 +92,9 @@ SVGA_CreateDevice(int devindex) device->GetDisplayModes = SVGA_GetDisplayModes; device->SetDisplayMode = SVGA_SetDisplayMode; device->PumpEvents = SVGA_PumpEvents; - device->CreateWindowFramebuffer = SDL_SVGA_CreateWindowFramebuffer; - device->UpdateWindowFramebuffer = SDL_SVGA_UpdateWindowFramebuffer; - device->DestroyWindowFramebuffer = SDL_SVGA_DestroyWindowFramebuffer; + device->CreateWindowFramebuffer = SDL_SVGA_CreateFramebuffer; + device->UpdateWindowFramebuffer = SDL_SVGA_UpdateFramebuffer; + device->DestroyWindowFramebuffer = SDL_SVGA_DestroyFramebuffer; device->free = SVGA_DeleteDevice; @@ -146,7 +146,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) } /* Mode must be a known pixel format. */ - mode.format = SVGA_ConvertPixelFormat(&info); + mode.format = SVGA_GetPixelFormat(&info); if (mode.format == SDL_PIXELFORMAT_UNKNOWN) { continue; } @@ -161,8 +161,8 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) mode.refresh_rate = 0; mode.driverdata = modedata; modedata->vbe_mode = vbe_mode; - modedata->framebuffer_phys_addr = (void *)(info.phys_base_ptr.segment * 16 + info.phys_base_ptr.offset); - modedata->framebuffer_size = 0x1000; /* FIXME: Set correct framebuffer memory size. */ + modedata->framebuffer_phys_addr = (void *)(info.phys_base_ptr.segment << 16 + info.phys_base_ptr.offset); + modedata->framebuffer_size = devdata->vbe_info.total_memory << 16; if (!SDL_AddDisplayMode(display, &mode)) { SDL_free(modedata); @@ -176,7 +176,11 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) SDL_DisplayModeData *modedata = mode->driverdata; /* TODO: Use SDL_SetError. */ - return SVGA_SetVBEMode(modedata->vbe_mode) == 0 ? 0 : -1; + if (SVGA_SetVBEMode(modedata->vbe_mode)) { + return -1; + } + + return 0; } static void diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index 406b1ec702529..edbeb5851e089 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -30,6 +30,7 @@ typedef struct { VBEInfo vbe_info; + SDL_Surface *surface; } SDL_DeviceData; typedef struct diff --git a/test/testdrawchessboard.c b/test/testdrawchessboard.c index db9da41c9dea7..c2fe1c1e5cdd0 100644 --- a/test/testdrawchessboard.c +++ b/test/testdrawchessboard.c @@ -121,7 +121,7 @@ int main(int argc, char *argv[]) } /* Create window and renderer for given surface */ - window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); + window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_FULLSCREEN); if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation fail : %s\n", SDL_GetError()); return 1; From 63c27e892ae029ad3909e9db1a2e0daa57bcff52 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 20 Mar 2020 14:57:42 -0400 Subject: [PATCH 19/51] svga: Use color masks to derive pixel format --- src/video/svga/SDL_svga_vbe.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 31edaf79496dd..b4ac604708000 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -140,14 +140,12 @@ SVGA_GetPixelFormat(const VBEModeInfo * info) case 4: return SDL_PIXELFORMAT_INDEX4MSB; case 8: return SDL_PIXELFORMAT_INDEX8; } - } else if (info->memory_model == VBE_MEM_MODEL_DIRECT) { - switch (info->bits_per_pixel) { - /* FIXME: Use SDL_MasksToPixelFormatEnum. */ - case 8: return SDL_PIXELFORMAT_RGB332; - case 15: return SDL_PIXELFORMAT_RGB555; - case 16: return SDL_PIXELFORMAT_RGB565; - case 32: return SDL_PIXELFORMAT_RGB888; - } + } + if (info->memory_model == VBE_MEM_MODEL_DIRECT) { + Uint32 r = ~(~(Uint32)0 << info->red_mask_size) << info->red_field_position; + Uint32 g = ~(~(Uint32)0 << info->green_mask_size) << info->green_field_position; + Uint32 b = ~(~(Uint32)0 << info->blue_mask_size) << info->blue_field_position; + return SDL_MasksToPixelFormatEnum(info->bits_per_pixel, r, g, b, 0); } return SDL_PIXELFORMAT_UNKNOWN; } From c01008a37b0b8fd56fa44edb3404225a69a2363c Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 20 Mar 2020 17:07:01 -0400 Subject: [PATCH 20/51] svga: Calculate surface size with pitch field --- src/video/svga/SDL_svga_framebuffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 7312e8fa07eba..c60ed9f384b12 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -61,6 +61,7 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i SDL_DisplayMode mode; SDL_DisplayModeData *modedata; SDL_Surface *surface = devdata->surface; + size_t surface_size; Uint8 *buf; __dpmi_meminfo mapping; @@ -69,6 +70,9 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i return SDL_SetError("Missing SVGA surface"); } + /* TODO: Support case when pitch includes off-screen padding. */ + surface_size = surface->pitch * surface->h; + /* TODO: Copy to back buffer and swap to screen */ if (SDL_GetWindowDisplayMode(window, &mode)) { @@ -90,7 +94,7 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i buf = (Uint8 *)(mapping.address + __djgpp_conventional_base); /* TODO: Use a blit function? */ - SDL_memcpy(buf, surface->pixels, surface->w * surface->h * surface->format->BytesPerPixel); + SDL_memcpy(buf, surface->pixels, surface_size); return 0; } From e10b1f26c3a232a1278033bdf777de392689db0d Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 20 Mar 2020 17:28:19 -0400 Subject: [PATCH 21/51] svga: Save framebuffer ptr in device data --- src/video/svga/SDL_svga_framebuffer.c | 15 +++------------ src/video/svga/SDL_svga_video.c | 6 ++++-- src/video/svga/SDL_svga_video.h | 4 ++-- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index c60ed9f384b12..bb775f9843326 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -58,8 +58,6 @@ int SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) { SDL_DeviceData *devdata = _this->driverdata; - SDL_DisplayMode mode; - SDL_DisplayModeData *modedata; SDL_Surface *surface = devdata->surface; size_t surface_size; @@ -73,16 +71,9 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i /* TODO: Support case when pitch includes off-screen padding. */ surface_size = surface->pitch * surface->h; - /* TODO: Copy to back buffer and swap to screen */ + mapping.address = *(Uint32 *)&devdata->framebuffer_phys_addr; + mapping.size = devdata->vbe_info.total_memory << 16; - if (SDL_GetWindowDisplayMode(window, &mode)) { - return -1; - } - - modedata = mode.driverdata; - mapping.address = (uintptr_t)modedata->framebuffer_phys_addr; - mapping.size = modedata->framebuffer_size; - if (__dpmi_physical_address_mapping(&mapping)) { return -1; } @@ -93,7 +84,7 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i buf = (Uint8 *)(mapping.address + __djgpp_conventional_base); - /* TODO: Use a blit function? */ + /* TODO: Copy to back buffer and swap to screen. */ SDL_memcpy(buf, surface->pixels, surface_size); return 0; diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index fda9b28c865ee..e5ae5208d76bb 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -161,8 +161,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) mode.refresh_rate = 0; mode.driverdata = modedata; modedata->vbe_mode = vbe_mode; - modedata->framebuffer_phys_addr = (void *)(info.phys_base_ptr.segment << 16 + info.phys_base_ptr.offset); - modedata->framebuffer_size = devdata->vbe_info.total_memory << 16; + modedata->framebuffer_phys_addr = info.phys_base_ptr; if (!SDL_AddDisplayMode(display, &mode)) { SDL_free(modedata); @@ -173,6 +172,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) { + SDL_DeviceData *devdata = _this->driverdata; SDL_DisplayModeData *modedata = mode->driverdata; /* TODO: Use SDL_SetError. */ @@ -180,6 +180,8 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) return -1; } + devdata->framebuffer_phys_addr = modedata->framebuffer_phys_addr; + return 0; } diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index edbeb5851e089..2d84c4bd35196 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -30,14 +30,14 @@ typedef struct { VBEInfo vbe_info; + VBEFarPtr framebuffer_phys_addr; SDL_Surface *surface; } SDL_DeviceData; typedef struct { VBEMode vbe_mode; - void *framebuffer_phys_addr; - size_t framebuffer_size; + VBEFarPtr framebuffer_phys_addr; } SDL_DisplayModeData; #endif /* SDL_svga_video_h_ */ From d8b2e85b6d25504912317076ccec6fa56fca0bb8 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 20 Mar 2020 17:34:15 -0400 Subject: [PATCH 22/51] svga: Add `VBE_FLAT_PTR` macro function --- src/video/svga/SDL_svga_vbe.c | 3 +-- src/video/svga/SDL_svga_vbe.h | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index b4ac604708000..5d1e47ee2b438 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -64,9 +64,8 @@ VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index) { VBEMode mode; - VBEFarPtr ptr = info->video_mode_ptr; - dosmemget(ptr.segment * 16 + ptr.offset + index * sizeof(mode), sizeof(mode), &mode); + dosmemget(VBE_FLAT_PTR(info->video_mode_ptr) + index * sizeof(mode), sizeof(mode), &mode); return mode; } diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 74c413cc9fbbb..57fa0c8566c2a 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -36,6 +36,9 @@ typedef struct VBEFarPtr { SDL_COMPILE_TIME_ASSERT(VBEFarPtr, sizeof(VBEFarPtr) == 4); +/* Convert a VBE far pointer to a flat pointer. */ +#define VBE_FLAT_PTR(far) ((far).segment * 16 + (far).offset) + typedef struct VBEVersion { Uint8 minor; Uint8 major; From 58df679140c840f9c2df8b93160164a657c8d8b8 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 20 Mar 2020 20:17:57 -0400 Subject: [PATCH 23/51] svga: Add window functions and data Windows are now always created with the fullscreen flag. --- src/video/svga/SDL_svga_framebuffer.c | 23 ++++++++++++----- src/video/svga/SDL_svga_video.c | 37 ++++++++++++++++++++++++--- src/video/svga/SDL_svga_video.h | 8 ++++-- test/testdrawchessboard.c | 2 +- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index bb775f9843326..9b4df556c7451 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -31,7 +31,7 @@ int SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) { - SDL_DeviceData *devdata = _this->driverdata; + SDL_WindowData *windata = window->driverdata; SDL_Surface *surface; Uint32 surface_format = SDL_GetWindowPixelFormat(window); int w, h; @@ -47,7 +47,7 @@ SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** } /* Save the info and return! */ - devdata->surface = surface; + windata->surface = surface; *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; @@ -58,7 +58,10 @@ int SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) { SDL_DeviceData *devdata = _this->driverdata; - SDL_Surface *surface = devdata->surface; + SDL_DisplayMode mode; + SDL_DisplayModeData *modedata; + SDL_WindowData *windata = window->driverdata; + SDL_Surface *surface = windata->surface; size_t surface_size; Uint8 *buf; @@ -68,10 +71,16 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i return SDL_SetError("Missing SVGA surface"); } + if (SDL_GetWindowDisplayMode(window, &mode)) { + return -1; + } + + modedata = mode.driverdata; + /* TODO: Support case when pitch includes off-screen padding. */ surface_size = surface->pitch * surface->h; - mapping.address = *(Uint32 *)&devdata->framebuffer_phys_addr; + mapping.address = *(Uint32 *)&modedata->framebuffer_phys_addr; mapping.size = devdata->vbe_info.total_memory << 16; if (__dpmi_physical_address_mapping(&mapping)) { @@ -93,9 +102,9 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i void SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window) { - SDL_DeviceData *devdata = _this->driverdata; - SDL_FreeSurface(devdata->surface); - devdata->surface = NULL; + SDL_WindowData *windata = window->driverdata; + SDL_FreeSurface(windata->surface); + windata->surface = NULL; } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index e5ae5208d76bb..6919139200e7f 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -42,6 +42,8 @@ static int SVGA_VideoInit(_THIS); static void SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display); static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); static void SVGA_VideoQuit(_THIS); +static int SVGA_CreateWindow(_THIS, SDL_Window * window); +static void SVGA_DestroyWindow(_THIS, SDL_Window * window); /* SVGA driver bootstrap functions */ @@ -92,6 +94,8 @@ SVGA_CreateDevice(int devindex) device->GetDisplayModes = SVGA_GetDisplayModes; device->SetDisplayMode = SVGA_SetDisplayMode; device->PumpEvents = SVGA_PumpEvents; + device->CreateSDLWindow = SVGA_CreateWindow; + device->DestroyWindow = SVGA_DestroyWindow; device->CreateWindowFramebuffer = SDL_SVGA_CreateFramebuffer; device->UpdateWindowFramebuffer = SDL_SVGA_UpdateFramebuffer; device->DestroyWindowFramebuffer = SDL_SVGA_DestroyFramebuffer; @@ -161,6 +165,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) mode.refresh_rate = 0; mode.driverdata = modedata; modedata->vbe_mode = vbe_mode; + modedata->bytes_per_scan_line = info.bytes_per_scan_line; modedata->framebuffer_phys_addr = info.phys_base_ptr; if (!SDL_AddDisplayMode(display, &mode)) { @@ -172,7 +177,6 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) { - SDL_DeviceData *devdata = _this->driverdata; SDL_DisplayModeData *modedata = mode->driverdata; /* TODO: Use SDL_SetError. */ @@ -180,8 +184,6 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) return -1; } - devdata->framebuffer_phys_addr = modedata->framebuffer_phys_addr; - return 0; } @@ -191,6 +193,35 @@ SVGA_VideoQuit(_THIS) /* TODO: Restore original video state. */ } +static int +SVGA_CreateWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *windata; + + /* TODO: Allow only one window. */ + + /* Allocate window internal data. */ + windata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); + if (!windata) { + return SDL_OutOfMemory(); + } + + window->driverdata = windata; + + /* Window is always fullscreen. */ + /* QUESTION: Is this appropriate, or should an error be returned instead? */ + window->flags |= SDL_WINDOW_FULLSCREEN; + + return 0; +} + +static void +SVGA_DestroyWindow(_THIS, SDL_Window * window) +{ + SDL_free(window->driverdata); + window->driverdata = NULL; +} + #endif /* SDL_VIDEO_DRIVER_SVGA */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index 2d84c4bd35196..b07e750a4f48b 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -30,16 +30,20 @@ typedef struct { VBEInfo vbe_info; - VBEFarPtr framebuffer_phys_addr; - SDL_Surface *surface; } SDL_DeviceData; typedef struct { VBEMode vbe_mode; + size_t bytes_per_scan_line; VBEFarPtr framebuffer_phys_addr; } SDL_DisplayModeData; +typedef struct +{ + SDL_Surface *surface; +} SDL_WindowData; + #endif /* SDL_svga_video_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/test/testdrawchessboard.c b/test/testdrawchessboard.c index c2fe1c1e5cdd0..db9da41c9dea7 100644 --- a/test/testdrawchessboard.c +++ b/test/testdrawchessboard.c @@ -121,7 +121,7 @@ int main(int argc, char *argv[]) } /* Create window and renderer for given surface */ - window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_FULLSCREEN); + window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation fail : %s\n", SDL_GetError()); return 1; From 0ff763ea3faddd0ccccf165f0824130808b3882e Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 20 Mar 2020 22:44:30 -0400 Subject: [PATCH 24/51] svga: Modes must have 4-byte aligned scan lines --- src/video/svga/SDL_svga_framebuffer.c | 6 +----- src/video/svga/SDL_svga_video.c | 12 +++++++++--- src/video/svga/SDL_svga_video.h | 1 - 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 9b4df556c7451..91c63e82b5db9 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -62,7 +62,6 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i SDL_DisplayModeData *modedata; SDL_WindowData *windata = window->driverdata; SDL_Surface *surface = windata->surface; - size_t surface_size; Uint8 *buf; __dpmi_meminfo mapping; @@ -77,9 +76,6 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i modedata = mode.driverdata; - /* TODO: Support case when pitch includes off-screen padding. */ - surface_size = surface->pitch * surface->h; - mapping.address = *(Uint32 *)&modedata->framebuffer_phys_addr; mapping.size = devdata->vbe_info.total_memory << 16; @@ -94,7 +90,7 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i buf = (Uint8 *)(mapping.address + __djgpp_conventional_base); /* TODO: Copy to back buffer and swap to screen. */ - SDL_memcpy(buf, surface->pixels, surface_size); + SDL_memcpy(buf, surface->pixels, surface->pitch * surface->h); return 0; } diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 6919139200e7f..435011512b79e 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -128,15 +128,17 @@ static void SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) { SDL_DeviceData *devdata = _this->driverdata; + SDL_DisplayMode mode; VBEMode vbe_mode; int index = 0; + SDL_zero(mode); + for ( vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++); vbe_mode != VBE_MODE_LIST_END; vbe_mode = SVGA_GetVBEModeAtIndex(&devdata->vbe_info, index++) ) { - SDL_DisplayMode mode; SDL_DisplayModeData *modedata; VBEModeInfo info; @@ -155,6 +157,12 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) continue; } + /* Scan lines must be 4-byte aligned to match SDL surface pitch. */ + if (info.bytes_per_scan_line % 4 != 0) { + continue; + } + + /* Allocate display mode internal data. */ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(*modedata)); if (!modedata) { return; @@ -162,10 +170,8 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) mode.w = info.x_resolution; mode.h = info.y_resolution; - mode.refresh_rate = 0; mode.driverdata = modedata; modedata->vbe_mode = vbe_mode; - modedata->bytes_per_scan_line = info.bytes_per_scan_line; modedata->framebuffer_phys_addr = info.phys_base_ptr; if (!SDL_AddDisplayMode(display, &mode)) { diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index b07e750a4f48b..1d82023cec463 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -35,7 +35,6 @@ typedef struct typedef struct { VBEMode vbe_mode; - size_t bytes_per_scan_line; VBEFarPtr framebuffer_phys_addr; } SDL_DisplayModeData; From 56f214a05aa0e61667c9a9070fdb95713e877ab2 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 21 Mar 2020 00:09:57 -0400 Subject: [PATCH 25/51] svga: Use safer form of memory mapping for framebuffer It ain't pretty though! --- src/video/svga/SDL_svga_framebuffer.c | 98 +++++++++++++++++---------- src/video/svga/SDL_svga_video.c | 4 +- src/video/svga/SDL_svga_video.h | 2 + 3 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 91c63e82b5db9..675367817311c 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -23,7 +23,8 @@ #if SDL_VIDEO_DRIVER_SVGA #include -#include +#include +#include #include "SDL_svga_video.h" #include "SDL_svga_framebuffer.h" @@ -31,66 +32,76 @@ int SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) { - SDL_WindowData *windata = window->driverdata; + SDL_DeviceData *devdata = _this->driverdata; + SDL_DisplayMode mode; + SDL_DisplayModeData *modedata; SDL_Surface *surface; - Uint32 surface_format = SDL_GetWindowPixelFormat(window); + SDL_WindowData *windata = window->driverdata; + __dpmi_meminfo meminfo; int w, h; - /* Free the old framebuffer surface */ + /* Free the old framebuffer surface. */ SDL_SVGA_DestroyFramebuffer(_this, window); - /* Create a new surface */ + /* Get data for current mode. */ + if (SDL_GetWindowDisplayMode(window, &mode)) { + return -1; + } + modedata = mode.driverdata; + + /* Map framebuffer's physical address to linear address. */ + meminfo.address = modedata->framebuffer_phys_addr.segment << 16; + meminfo.address += modedata->framebuffer_phys_addr.offset; + meminfo.size = devdata->vbe_info.total_memory << 16; + if (__dpmi_physical_address_mapping(&meminfo)) { + SDL_SVGA_DestroyFramebuffer(_this, window); + return -1; + } + windata->framebuffer_linear_addr = meminfo.address; + + /* Allocate local descriptor to access memory-mapped framebuffer. */ + windata->framebuffer_selector = __dpmi_allocate_ldt_descriptors(1); + if (windata->framebuffer_selector == -1) { + SDL_SVGA_DestroyFramebuffer(_this, window); + return -1; + } + + /* Setup framebuffer descriptor. */ + if (__dpmi_set_segment_base_address(windata->framebuffer_selector, meminfo.address) || + __dpmi_set_segment_limit(windata->framebuffer_selector, meminfo.size - 1)) { + SDL_SVGA_DestroyFramebuffer(_this, window); + return -1; + } + + /* Create a new surface. */ SDL_GetWindowSize(window, &w, &h); - surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, surface_format); + surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, mode.format); if (!surface) { + SDL_SVGA_DestroyFramebuffer(_this, window); return -1; } - - /* Save the info and return! */ windata->surface = surface; - *format = surface_format; + + /* Set output parameters. */ + *format = mode.format; *pixels = surface->pixels; *pitch = surface->pitch; + return 0; } int SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) { - SDL_DeviceData *devdata = _this->driverdata; - SDL_DisplayMode mode; - SDL_DisplayModeData *modedata; SDL_WindowData *windata = window->driverdata; SDL_Surface *surface = windata->surface; - Uint8 *buf; - __dpmi_meminfo mapping; - if (!surface) { return SDL_SetError("Missing SVGA surface"); } - if (SDL_GetWindowDisplayMode(window, &mode)) { - return -1; - } - - modedata = mode.driverdata; - - mapping.address = *(Uint32 *)&modedata->framebuffer_phys_addr; - mapping.size = devdata->vbe_info.total_memory << 16; - - if (__dpmi_physical_address_mapping(&mapping)) { - return -1; - } - - if (!__djgpp_nearptr_enable()) { - return -1; - } - - buf = (Uint8 *)(mapping.address + __djgpp_conventional_base); - /* TODO: Copy to back buffer and swap to screen. */ - SDL_memcpy(buf, surface->pixels, surface->pitch * surface->h); + movedata(_my_ds(), (Uint32)surface->pixels, windata->framebuffer_selector, 0, surface->pitch * surface->h); return 0; } @@ -99,8 +110,25 @@ void SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window) { SDL_WindowData *windata = window->driverdata; + + /* Destroy surface. */ SDL_FreeSurface(windata->surface); windata->surface = NULL; + + /* Deallocate local descriptor for framebuffer. */ + if (windata->framebuffer_selector != -1) { + __dpmi_free_ldt_descriptor(windata->framebuffer_selector); + windata->framebuffer_selector = -1; + } + + /* Unmap framebuffer physical address. */ + if (windata->framebuffer_linear_addr) { + __dpmi_meminfo meminfo; + + meminfo.address = windata->framebuffer_linear_addr; + __dpmi_free_physical_address_mapping(&meminfo); + windata->framebuffer_linear_addr = 0; + } } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 435011512b79e..3885dfd217c94 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -211,9 +211,11 @@ SVGA_CreateWindow(_THIS, SDL_Window * window) if (!windata) { return SDL_OutOfMemory(); } - window->driverdata = windata; + /* Set framebuffer selector to sentinel value. */ + windata->framebuffer_selector = -1; + /* Window is always fullscreen. */ /* QUESTION: Is this appropriate, or should an error be returned instead? */ window->flags |= SDL_WINDOW_FULLSCREEN; diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index 1d82023cec463..ac0df56589292 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -41,6 +41,8 @@ typedef struct typedef struct { SDL_Surface *surface; + int framebuffer_selector; + Uint32 framebuffer_linear_addr; } SDL_WindowData; #endif /* SDL_svga_video_h_ */ From 6b21e8a037ceb78b8780f6f6bd7b616c313afc7e Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 21 Mar 2020 01:39:54 -0400 Subject: [PATCH 26/51] svga: Implement double buffering --- src/video/svga/SDL_svga_framebuffer.c | 14 ++++++++++++-- src/video/svga/SDL_svga_vbe.c | 17 +++++++++++++++++ src/video/svga/SDL_svga_vbe.h | 1 + src/video/svga/SDL_svga_video.c | 5 +++++ src/video/svga/SDL_svga_video.h | 1 + 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 675367817311c..01d54313d9493 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -95,13 +95,23 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i { SDL_WindowData *windata = window->driverdata; SDL_Surface *surface = windata->surface; + size_t surface_size; if (!surface) { return SDL_SetError("Missing SVGA surface"); } - /* TODO: Copy to back buffer and swap to screen. */ - movedata(_my_ds(), (Uint32)surface->pixels, windata->framebuffer_selector, 0, surface->pitch * surface->h); + surface_size = surface->pitch * surface->h; + + /* Flip the active page flag. */ + windata->framebuffer_page = !windata->framebuffer_page; + + /* Copy pixels to hidden framebuffer page. */ + movedata(_my_ds(), (Uint32)surface->pixels, windata->framebuffer_selector, + windata->framebuffer_page ? surface_size : 0, surface_size); + + /* Display fresh page to screen. */ + SVGA_SetDisplayStart(0, windata->framebuffer_page ? surface->h : 0); return 0; } diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 5d1e47ee2b438..758fc034e9e41 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -129,6 +129,23 @@ SVGA_SetVBEMode(VBEMode mode) return 0; } +int +SVGA_SetDisplayStart(int x, int y) +{ + __dpmi_regs r; + + r.x.ax = 0x4F07; + r.x.bx = 0x80; /* Set start and wait for vertical retrace. */ + r.x.cx = x; + r.x.dx = y; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + return 0; +} + SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info) { diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 57fa0c8566c2a..513c230d229d0 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -151,6 +151,7 @@ extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); extern int SVGA_SetVBEMode(VBEMode mode); extern SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info); +extern int SVGA_SetDisplayStart(int x, int y); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 3885dfd217c94..6c9fda7c4352c 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -157,6 +157,11 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) continue; } + /* Mode must be capable of double buffering. */ + if (!info.number_of_image_pages) { + continue; + } + /* Scan lines must be 4-byte aligned to match SDL surface pitch. */ if (info.bytes_per_scan_line % 4 != 0) { continue; diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index ac0df56589292..e47298022bd6d 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -41,6 +41,7 @@ typedef struct typedef struct { SDL_Surface *surface; + SDL_bool framebuffer_page; int framebuffer_selector; Uint32 framebuffer_linear_addr; } SDL_WindowData; From 630ef227478d48aa5048c3103e43d6180121a7c5 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 22 Mar 2020 16:24:50 -0400 Subject: [PATCH 27/51] WIP: svga: Support indexed color formats --- src/video/svga/SDL_svga_framebuffer.c | 21 +++++++---- src/video/svga/SDL_svga_vbe.c | 50 +++++++++++++++++++++++++-- src/video/svga/SDL_svga_vbe.h | 8 +++++ src/video/svga/SDL_svga_video.c | 4 +++ src/video/svga/SDL_svga_video.h | 2 +- 5 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 01d54313d9493..371efcb2bf41a 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -80,9 +80,18 @@ SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** SDL_SVGA_DestroyFramebuffer(_this, window); return -1; } - windata->surface = surface; - - /* Set output parameters. */ + + /* Populate color palette for indexed pixel formats. */ + if (surface->format->palette) { + SDL_Palette *palette = surface->format->palette; + if (SVGA_GetPaletteData(palette->colors, palette->ncolors)) { + SDL_SVGA_DestroyFramebuffer(_this, window); + return -1; + } + } + + /* Save data and set output parameters. */ + window->surface = surface; *format = mode.format; *pixels = surface->pixels; *pitch = surface->pitch; @@ -94,7 +103,7 @@ int SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) { SDL_WindowData *windata = window->driverdata; - SDL_Surface *surface = windata->surface; + SDL_Surface *surface = window->surface; size_t surface_size; if (!surface) { @@ -122,8 +131,8 @@ SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window) SDL_WindowData *windata = window->driverdata; /* Destroy surface. */ - SDL_FreeSurface(windata->surface); - windata->surface = NULL; + SDL_FreeSurface(window->surface); + window->surface = NULL; /* Deallocate local descriptor for framebuffer. */ if (windata->framebuffer_selector != -1) { diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 758fc034e9e41..964e8a614cb38 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -43,8 +43,8 @@ SVGA_GetVBEInfo(VBEInfo * info) dosmemput("VBE2", 4, __tb); r.x.ax = 0x4F00; - r.x.di = __tb_offset; r.x.es = __tb_segment; + r.x.di = __tb_offset; __dpmi_int(0x10, &r); @@ -77,8 +77,8 @@ SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info) r.x.ax = 0x4F01; r.x.cx = mode; - r.x.di = __tb_offset; r.x.es = __tb_segment; + r.x.di = __tb_offset; __dpmi_int(0x10, &r); @@ -146,6 +146,52 @@ SVGA_SetDisplayStart(int x, int y) return 0; } +int +SVGA_SetDACPaletteFormat(int bits) +{ + __dpmi_regs r; + + r.x.ax = 0x4F08; + r.h.bl = 0; /* Flag to set format */ + r.h.bh = bits; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + return r.h.bh; +} + +int +SVGA_GetPaletteData(SDL_Color * colors, int num_colors) +{ + int i; + __dpmi_regs r; + + r.x.ax = 0x4F09; + r.h.bl = 1; /* Flag to get colors */ + r.x.cx = num_colors; + r.x.dx = 0; /* First color */ + r.x.es = __tb_segment; + r.x.di = __tb_offset; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + dosmemget(__tb, num_colors * sizeof(*colors), colors); + + /* Palette color components are stored in BGR order. */ + for (i = 0; i < num_colors; i++) { + Uint8 temp = colors[i].r; + colors[i].r = colors[i].b; + colors[i].b = temp; + colors[i].a = SDL_ALPHA_OPAQUE; + } + + return 0; +} + SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info) { diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 513c230d229d0..ad73fa036d960 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -66,6 +66,12 @@ typedef struct VBEInfo SDL_COMPILE_TIME_ASSERT(VBEInfo, sizeof(VBEInfo) == 512); +#define VBE_CAP_DAC_WIDTH_SWITCH 0x01 +#define VBE_CAP_NO_VGA_COMPAT 0x02 +#define VBE_CAP_RAMDAC_BLANK_BIT 0x04 +#define VBE_CAP_HW_STEREO_SIGNAL 0x08 +#define VBE_CAP_STEREO_VIA_EVC 0x10 + typedef struct VBEModeInfo { Uint16 mode_attributes; /* Mode attributes */ @@ -152,6 +158,8 @@ extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); extern int SVGA_SetVBEMode(VBEMode mode); extern SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info); extern int SVGA_SetDisplayStart(int x, int y); +extern int SVGA_SetDACPaletteFormat(int bits); +extern int SVGA_GetPaletteData(SDL_Color * colors, int num_colors); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 6c9fda7c4352c..70a53959dae42 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -188,6 +188,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) { + SDL_DeviceData *devdata = _this->driverdata; SDL_DisplayModeData *modedata = mode->driverdata; /* TODO: Use SDL_SetError. */ @@ -195,6 +196,9 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) return -1; } + /* TODO: Switch to 8 bit palette format, if possible and relevant. */ + devdata->palette_format = 6; + return 0; } diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index e47298022bd6d..65c7eb5d44ee4 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -30,6 +30,7 @@ typedef struct { VBEInfo vbe_info; + Uint8 palette_format; } SDL_DeviceData; typedef struct @@ -40,7 +41,6 @@ typedef struct typedef struct { - SDL_Surface *surface; SDL_bool framebuffer_page; int framebuffer_selector; Uint32 framebuffer_linear_addr; From 6fe697e94795e9c16f21ccbf08681be5f82536e9 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 27 Mar 2020 18:48:05 -0400 Subject: [PATCH 28/51] svga: Naively generate key press events Key release events do not seem to be visible via _bios_keybrd. This will probably change to use a keyboard interrupt handler. --- src/video/svga/SDL_svga_events.c | 102 ++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/src/video/svga/SDL_svga_events.c b/src/video/svga/SDL_svga_events.c index d3ba4e84a2d12..dc8e37152684c 100644 --- a/src/video/svga/SDL_svga_events.c +++ b/src/video/svga/SDL_svga_events.c @@ -22,15 +22,115 @@ #if SDL_VIDEO_DRIVER_SVGA +#include + #include "../../events/SDL_events_c.h" #include "SDL_svga_video.h" #include "SDL_svga_events.h" +static const SDL_Scancode bios_to_sdl_scancode[128] = { + 0, + SDL_SCANCODE_ESCAPE, + SDL_SCANCODE_1, + SDL_SCANCODE_2, + SDL_SCANCODE_3, + SDL_SCANCODE_4, + SDL_SCANCODE_5, + SDL_SCANCODE_6, + SDL_SCANCODE_7, + SDL_SCANCODE_8, + SDL_SCANCODE_9, + SDL_SCANCODE_0, + SDL_SCANCODE_MINUS, + SDL_SCANCODE_EQUALS, + SDL_SCANCODE_BACKSPACE, + SDL_SCANCODE_TAB, + SDL_SCANCODE_Q, + SDL_SCANCODE_W, + SDL_SCANCODE_E, + SDL_SCANCODE_R, + SDL_SCANCODE_T, + SDL_SCANCODE_Y, + SDL_SCANCODE_U, + SDL_SCANCODE_I, + SDL_SCANCODE_O, + SDL_SCANCODE_P, + SDL_SCANCODE_LEFTBRACKET, + SDL_SCANCODE_RIGHTBRACKET, + SDL_SCANCODE_RETURN, + SDL_SCANCODE_LCTRL, + SDL_SCANCODE_A, + SDL_SCANCODE_S, + SDL_SCANCODE_D, + SDL_SCANCODE_F, + SDL_SCANCODE_G, + SDL_SCANCODE_H, + SDL_SCANCODE_J, + SDL_SCANCODE_K, + SDL_SCANCODE_L, + SDL_SCANCODE_SEMICOLON, + SDL_SCANCODE_APOSTROPHE, + SDL_SCANCODE_GRAVE, + SDL_SCANCODE_LSHIFT, + SDL_SCANCODE_BACKSLASH, + SDL_SCANCODE_Z, + SDL_SCANCODE_X, + SDL_SCANCODE_C, + SDL_SCANCODE_V, + SDL_SCANCODE_B, + SDL_SCANCODE_N, + SDL_SCANCODE_M, + SDL_SCANCODE_COMMA, + SDL_SCANCODE_PERIOD, + SDL_SCANCODE_SLASH, + SDL_SCANCODE_RSHIFT, + SDL_SCANCODE_KP_MULTIPLY, + SDL_SCANCODE_LALT, + SDL_SCANCODE_SPACE, + SDL_SCANCODE_CAPSLOCK, + SDL_SCANCODE_F1, + SDL_SCANCODE_F2, + SDL_SCANCODE_F3, + SDL_SCANCODE_F4, + SDL_SCANCODE_F5, + SDL_SCANCODE_F6, + SDL_SCANCODE_F7, + SDL_SCANCODE_F8, + SDL_SCANCODE_F9, + SDL_SCANCODE_F10, + SDL_SCANCODE_NUMLOCKCLEAR, + SDL_SCANCODE_SCROLLLOCK, + SDL_SCANCODE_KP_7, + SDL_SCANCODE_KP_8, + SDL_SCANCODE_KP_9, + SDL_SCANCODE_KP_MINUS, + SDL_SCANCODE_KP_4, + SDL_SCANCODE_KP_5, + SDL_SCANCODE_KP_6, + SDL_SCANCODE_KP_PLUS, + SDL_SCANCODE_KP_1, + SDL_SCANCODE_KP_2, + SDL_SCANCODE_KP_3, + SDL_SCANCODE_KP_0, + SDL_SCANCODE_KP_PERIOD, + SDL_SCANCODE_SYSREQ, + 0, + SDL_SCANCODE_LGUI, + SDL_SCANCODE_F11, + SDL_SCANCODE_F12, +}; + void SVGA_PumpEvents(_THIS) { - /* do nothing. */ + /* TODO: Handle enhanced keyboard scancodes. */ + /* TODO: Detect key released events. */ + /* TODO: Send ASCII part to SDL_SendKeyboardText? */ + while (_bios_keybrd(_KEYBRD_READY)) { + Uint8 scan = _bios_keybrd(_KEYBRD_READ) >> 8; + SDL_SendKeyboardKey(SDL_PRESSED, bios_to_sdl_scancode[scan]); + } } #endif /* SDL_VIDEO_DRIVER_SVGA */ From 86898441a6012239d7a28e539f1d67586f385ff7 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Fri, 27 Mar 2020 23:20:30 -0400 Subject: [PATCH 29/51] svga: Restore original video state on quit --- src/video/svga/SDL_svga_vbe.c | 75 +++++++++++++++++++++++++++++++-- src/video/svga/SDL_svga_vbe.h | 4 +- src/video/svga/SDL_svga_video.c | 38 ++++++++++++++--- src/video/svga/SDL_svga_video.h | 4 +- 4 files changed, 109 insertions(+), 12 deletions(-) diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 964e8a614cb38..7f8687b62a0b8 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -30,10 +30,11 @@ #include /* Check the DPMI registers for an error after a VBE function call. */ -/* Returns -1 if VBE is not installed or the non-zero VBE error code. */ +/* Returns -128 if the function is not supported or the negated VBE error code. */ +/* TODO: Create named macro definitions for possible error values. */ #define RETURN_IF_VBE_CALL_FAILED(regs) \ - if ((regs).h.al != 0x4F) return -1; \ - if ((regs).h.ah != 0) return (regs).h.ah; + if ((regs).h.al != 0x4F) return SDL_MIN_SINT8; \ + if ((regs).h.ah != 0) return -(regs).h.ah; int SVGA_GetVBEInfo(VBEInfo * info) @@ -129,6 +130,74 @@ SVGA_SetVBEMode(VBEMode mode) return 0; } +int +SVGA_GetState(void **state) +{ + size_t state_size; + __dpmi_regs r; + + r.x.ax = 0x4F04; + r.h.dl = 0; /* Get state buffer size. */ + r.x.cx = 0xF; /* All states. */ + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + /* Calculate state buffer size. */ + state_size = r.x.bx * 64; + + /* Check that transfer buffer is big enough. */ + if (state_size > __tb_size) { + return SDL_OutOfMemory(); + } + + r.h.dl = 1; /* Save state. */ + r.x.es = __tb_segment; + r.x.bx = __tb_offset; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + /* Allocate state buffer. */ + *state = SDL_calloc(1, state_size); + if (!*state) { + return SDL_OutOfMemory(); + } + + /* Copy state data from DOS transfer buffer. */ + dosmemget(__tb, state_size, *state); + + return state_size; +} + +int +SVGA_SetState(const void *state, size_t size) +{ + __dpmi_regs r; + + /* Check that transfer buffer is big enough. */ + if (size > __tb_size) { + return SDL_OutOfMemory(); + } + + /* Copy state data into DOS transfer buffer. */ + dosmemput(state, size, __tb); + + r.x.ax = 0x4F04; + r.h.dl = 2; /* Restore state. */ + r.x.cx = 0xF; /* All states. */ + r.x.es = __tb_segment; + r.x.bx = __tb_offset; + + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + + return 0; +} + int SVGA_SetDisplayStart(int x, int y) { diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index ad73fa036d960..9e16cac28414f 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -156,10 +156,12 @@ extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); extern int SVGA_SetVBEMode(VBEMode mode); -extern SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info); +extern int SVGA_GetState(void **state); +extern int SVGA_SetState(const void *state, size_t size); extern int SVGA_SetDisplayStart(int x, int y); extern int SVGA_SetDACPaletteFormat(int bits); extern int SVGA_GetPaletteData(SDL_Color * colors, int num_colors); +extern SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 70a53959dae42..7baa735a0902b 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -113,13 +113,24 @@ VideoBootStrap SVGA_bootstrap = { static int SVGA_VideoInit(_THIS) { - /* TODO: Query for current mode. */ + SDL_DeviceData *devdata = _this->driverdata; + + /* Save original video mode. */ + if (SVGA_GetCurrentVBEMode(&devdata->original_mode, NULL)) { + return SDL_SetError("Couldn't query current video mode"); + } + + /* TODO: Use mode info if it exists. */ if (SDL_AddBasicVideoDisplay(NULL) < 0) { return -1; } - /* TODO: Save original video state. */ + /* Save original video state. */ + devdata->state_size = SVGA_GetState(&devdata->original_state); + if (devdata->state_size < 0) { + return -1; + } return 0; } @@ -188,16 +199,18 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) static int SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) { - SDL_DeviceData *devdata = _this->driverdata; SDL_DisplayModeData *modedata = mode->driverdata; - /* TODO: Use SDL_SetError. */ + if (!modedata) { + return SDL_SetError("Missing display mode data"); + } + if (SVGA_SetVBEMode(modedata->vbe_mode)) { - return -1; + /* TODO: Include VBE error message. */ + return SDL_SetError("Couldn't set VBE display mode"); } /* TODO: Switch to 8 bit palette format, if possible and relevant. */ - devdata->palette_format = 6; return 0; } @@ -205,7 +218,18 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) static void SVGA_VideoQuit(_THIS) { - /* TODO: Restore original video state. */ + SDL_DeviceData *devdata = _this->driverdata; + + /* Restore original video state. */ + if (devdata->original_state) { + SVGA_SetState(devdata->original_state, devdata->state_size); + SDL_free(devdata->original_state); + } + + /* Restore original video mode. */ + if (devdata->original_mode) { + SVGA_SetVBEMode(devdata->original_mode); + } } static int diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index 65c7eb5d44ee4..0aeb2ac00838e 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -30,7 +30,9 @@ typedef struct { VBEInfo vbe_info; - Uint8 palette_format; + VBEMode original_mode; + void *original_state; + size_t state_size; } SDL_DeviceData; typedef struct From dbe5c1084f386451c21e23af78282c51a6846fd3 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 11 Apr 2020 23:41:23 -0400 Subject: [PATCH 30/51] dos: Write logs to a file --- src/SDL_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SDL_log.c b/src/SDL_log.c index 47f5b7251eac8..8dc612c29e8e3 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -555,7 +555,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority SDL_NSLog(SDL_priority_prefixes[priority], message); return; } -#elif defined(__PSP__) || defined(__PS2__) +#elif defined(__PSP__) || defined(__PS2__) || defined(__MSDOS__) { FILE *pFile; pFile = fopen("SDL_Log.txt", "a"); From 88d8427f959c5501b04c1234c9bb1fdc7e3b99c0 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 12 Apr 2020 00:30:20 -0400 Subject: [PATCH 31/51] svga: Invalidate window surface after freeing it --- src/video/svga/SDL_svga_framebuffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 371efcb2bf41a..ca2271e1d67de 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -133,6 +133,7 @@ SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window) /* Destroy surface. */ SDL_FreeSurface(window->surface); window->surface = NULL; + window->surface_valid = SDL_FALSE; /* Deallocate local descriptor for framebuffer. */ if (windata->framebuffer_selector != -1) { From bd0280ead8888d575851e36016e182258429bd85 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 18 Apr 2020 23:56:35 -0400 Subject: [PATCH 32/51] dos: Move keyboard handling out of svga --- configure | 3 + configure.ac | 3 + src/core/dos/SDL_dos.c | 137 +++++++++++++++++++++++++++++++ src/core/dos/SDL_dos.h | 30 +++++++ src/video/svga/SDL_svga_events.c | 106 +----------------------- 5 files changed, 176 insertions(+), 103 deletions(-) create mode 100644 src/core/dos/SDL_dos.c create mode 100644 src/core/dos/SDL_dos.h diff --git a/configure b/configure index 055a05f8654b2..88b9e88de32db 100755 --- a/configure +++ b/configure @@ -29833,6 +29833,9 @@ $as_echo "#define SDL_TIMER_DOS 1" >>confdefs.h SOURCES="$SOURCES $srcdir/src/timer/dos/*.c" have_timers=yes fi + + # Set up files for shared DOS utilities and event handling + SOURCES="$SOURCES $srcdir/src/core/dos/*.c" ;; *) as_fn_error $? " diff --git a/configure.ac b/configure.ac index dc7e2a9c12123..3f7b64c767300 100644 --- a/configure.ac +++ b/configure.ac @@ -4722,6 +4722,9 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works. --ryan. SOURCES="$SOURCES $srcdir/src/timer/dos/*.c" have_timers=yes fi + + # Set up files for shared DOS utilities and event handling + SOURCES="$SOURCES $srcdir/src/core/dos/*.c" ;; *) AC_MSG_ERROR([ diff --git a/src/core/dos/SDL_dos.c b/src/core/dos/SDL_dos.c new file mode 100644 index 0000000000000..f5b4c5cfc9a91 --- /dev/null +++ b/src/core/dos/SDL_dos.c @@ -0,0 +1,137 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Jay Petacat + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#ifdef __MSDOS__ + +#include + +#include "../../events/SDL_events_c.h" + +static const SDL_Scancode bios_to_sdl_scancode[128] = { + 0, + SDL_SCANCODE_ESCAPE, + SDL_SCANCODE_1, + SDL_SCANCODE_2, + SDL_SCANCODE_3, + SDL_SCANCODE_4, + SDL_SCANCODE_5, + SDL_SCANCODE_6, + SDL_SCANCODE_7, + SDL_SCANCODE_8, + SDL_SCANCODE_9, + SDL_SCANCODE_0, + SDL_SCANCODE_MINUS, + SDL_SCANCODE_EQUALS, + SDL_SCANCODE_BACKSPACE, + SDL_SCANCODE_TAB, + SDL_SCANCODE_Q, + SDL_SCANCODE_W, + SDL_SCANCODE_E, + SDL_SCANCODE_R, + SDL_SCANCODE_T, + SDL_SCANCODE_Y, + SDL_SCANCODE_U, + SDL_SCANCODE_I, + SDL_SCANCODE_O, + SDL_SCANCODE_P, + SDL_SCANCODE_LEFTBRACKET, + SDL_SCANCODE_RIGHTBRACKET, + SDL_SCANCODE_RETURN, + SDL_SCANCODE_LCTRL, + SDL_SCANCODE_A, + SDL_SCANCODE_S, + SDL_SCANCODE_D, + SDL_SCANCODE_F, + SDL_SCANCODE_G, + SDL_SCANCODE_H, + SDL_SCANCODE_J, + SDL_SCANCODE_K, + SDL_SCANCODE_L, + SDL_SCANCODE_SEMICOLON, + SDL_SCANCODE_APOSTROPHE, + SDL_SCANCODE_GRAVE, + SDL_SCANCODE_LSHIFT, + SDL_SCANCODE_BACKSLASH, + SDL_SCANCODE_Z, + SDL_SCANCODE_X, + SDL_SCANCODE_C, + SDL_SCANCODE_V, + SDL_SCANCODE_B, + SDL_SCANCODE_N, + SDL_SCANCODE_M, + SDL_SCANCODE_COMMA, + SDL_SCANCODE_PERIOD, + SDL_SCANCODE_SLASH, + SDL_SCANCODE_RSHIFT, + SDL_SCANCODE_KP_MULTIPLY, + SDL_SCANCODE_LALT, + SDL_SCANCODE_SPACE, + SDL_SCANCODE_CAPSLOCK, + SDL_SCANCODE_F1, + SDL_SCANCODE_F2, + SDL_SCANCODE_F3, + SDL_SCANCODE_F4, + SDL_SCANCODE_F5, + SDL_SCANCODE_F6, + SDL_SCANCODE_F7, + SDL_SCANCODE_F8, + SDL_SCANCODE_F9, + SDL_SCANCODE_F10, + SDL_SCANCODE_NUMLOCKCLEAR, + SDL_SCANCODE_SCROLLLOCK, + SDL_SCANCODE_KP_7, + SDL_SCANCODE_KP_8, + SDL_SCANCODE_KP_9, + SDL_SCANCODE_KP_MINUS, + SDL_SCANCODE_KP_4, + SDL_SCANCODE_KP_5, + SDL_SCANCODE_KP_6, + SDL_SCANCODE_KP_PLUS, + SDL_SCANCODE_KP_1, + SDL_SCANCODE_KP_2, + SDL_SCANCODE_KP_3, + SDL_SCANCODE_KP_0, + SDL_SCANCODE_KP_PERIOD, + SDL_SCANCODE_SYSREQ, + 0, + SDL_SCANCODE_LGUI, + SDL_SCANCODE_F11, + SDL_SCANCODE_F12, +}; + +void +SDL_DOS_PumpEvents(void) +{ + /* TODO: Handle enhanced keyboard scancodes. */ + /* TODO: Detect key released events. */ + /* TODO: Send ASCII part to SDL_SendKeyboardText? */ + while (_bios_keybrd(_KEYBRD_READY)) { + Uint8 scan = _bios_keybrd(_KEYBRD_READ) >> 8; + SDL_SendKeyboardKey(SDL_PRESSED, bios_to_sdl_scancode[scan]); + } +} + +#endif /* __MSDOS__ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/core/dos/SDL_dos.h b/src/core/dos/SDL_dos.h new file mode 100644 index 0000000000000..f4519d77806dc --- /dev/null +++ b/src/core/dos/SDL_dos.h @@ -0,0 +1,30 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Jay Petacat + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_dos_h_ +#define SDL_dos_h_ + +extern void SDL_DOS_PumpEvents(void); + +#endif /* SDL_dos_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_events.c b/src/video/svga/SDL_svga_events.c index dc8e37152684c..684cf82a79c74 100644 --- a/src/video/svga/SDL_svga_events.c +++ b/src/video/svga/SDL_svga_events.c @@ -1,6 +1,7 @@ /* Simple DirectMedia Layer Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Jay Petacat This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -22,115 +23,14 @@ #if SDL_VIDEO_DRIVER_SVGA -#include +#include "../../core/dos/SDL_dos.h" -#include "../../events/SDL_events_c.h" - -#include "SDL_svga_video.h" #include "SDL_svga_events.h" -static const SDL_Scancode bios_to_sdl_scancode[128] = { - 0, - SDL_SCANCODE_ESCAPE, - SDL_SCANCODE_1, - SDL_SCANCODE_2, - SDL_SCANCODE_3, - SDL_SCANCODE_4, - SDL_SCANCODE_5, - SDL_SCANCODE_6, - SDL_SCANCODE_7, - SDL_SCANCODE_8, - SDL_SCANCODE_9, - SDL_SCANCODE_0, - SDL_SCANCODE_MINUS, - SDL_SCANCODE_EQUALS, - SDL_SCANCODE_BACKSPACE, - SDL_SCANCODE_TAB, - SDL_SCANCODE_Q, - SDL_SCANCODE_W, - SDL_SCANCODE_E, - SDL_SCANCODE_R, - SDL_SCANCODE_T, - SDL_SCANCODE_Y, - SDL_SCANCODE_U, - SDL_SCANCODE_I, - SDL_SCANCODE_O, - SDL_SCANCODE_P, - SDL_SCANCODE_LEFTBRACKET, - SDL_SCANCODE_RIGHTBRACKET, - SDL_SCANCODE_RETURN, - SDL_SCANCODE_LCTRL, - SDL_SCANCODE_A, - SDL_SCANCODE_S, - SDL_SCANCODE_D, - SDL_SCANCODE_F, - SDL_SCANCODE_G, - SDL_SCANCODE_H, - SDL_SCANCODE_J, - SDL_SCANCODE_K, - SDL_SCANCODE_L, - SDL_SCANCODE_SEMICOLON, - SDL_SCANCODE_APOSTROPHE, - SDL_SCANCODE_GRAVE, - SDL_SCANCODE_LSHIFT, - SDL_SCANCODE_BACKSLASH, - SDL_SCANCODE_Z, - SDL_SCANCODE_X, - SDL_SCANCODE_C, - SDL_SCANCODE_V, - SDL_SCANCODE_B, - SDL_SCANCODE_N, - SDL_SCANCODE_M, - SDL_SCANCODE_COMMA, - SDL_SCANCODE_PERIOD, - SDL_SCANCODE_SLASH, - SDL_SCANCODE_RSHIFT, - SDL_SCANCODE_KP_MULTIPLY, - SDL_SCANCODE_LALT, - SDL_SCANCODE_SPACE, - SDL_SCANCODE_CAPSLOCK, - SDL_SCANCODE_F1, - SDL_SCANCODE_F2, - SDL_SCANCODE_F3, - SDL_SCANCODE_F4, - SDL_SCANCODE_F5, - SDL_SCANCODE_F6, - SDL_SCANCODE_F7, - SDL_SCANCODE_F8, - SDL_SCANCODE_F9, - SDL_SCANCODE_F10, - SDL_SCANCODE_NUMLOCKCLEAR, - SDL_SCANCODE_SCROLLLOCK, - SDL_SCANCODE_KP_7, - SDL_SCANCODE_KP_8, - SDL_SCANCODE_KP_9, - SDL_SCANCODE_KP_MINUS, - SDL_SCANCODE_KP_4, - SDL_SCANCODE_KP_5, - SDL_SCANCODE_KP_6, - SDL_SCANCODE_KP_PLUS, - SDL_SCANCODE_KP_1, - SDL_SCANCODE_KP_2, - SDL_SCANCODE_KP_3, - SDL_SCANCODE_KP_0, - SDL_SCANCODE_KP_PERIOD, - SDL_SCANCODE_SYSREQ, - 0, - SDL_SCANCODE_LGUI, - SDL_SCANCODE_F11, - SDL_SCANCODE_F12, -}; - void SVGA_PumpEvents(_THIS) { - /* TODO: Handle enhanced keyboard scancodes. */ - /* TODO: Detect key released events. */ - /* TODO: Send ASCII part to SDL_SendKeyboardText? */ - while (_bios_keybrd(_KEYBRD_READY)) { - Uint8 scan = _bios_keybrd(_KEYBRD_READ) >> 8; - SDL_SendKeyboardKey(SDL_PRESSED, bios_to_sdl_scancode[scan]); - } + SDL_DOS_PumpEvents(); } #endif /* SDL_VIDEO_DRIVER_SVGA */ From 1c3335bf803986bf616de2fed215a6aa9915be3c Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sun, 19 Apr 2020 03:04:10 -0400 Subject: [PATCH 33/51] dos: Use interrupt service routine for keyboard events --- src/core/dos/SDL_dos.c | 172 ++++++++++++++++++++++++++++++-- src/core/dos/SDL_dos.h | 2 + src/video/svga/SDL_svga_video.c | 7 +- 3 files changed, 172 insertions(+), 9 deletions(-) diff --git a/src/core/dos/SDL_dos.c b/src/core/dos/SDL_dos.c index f5b4c5cfc9a91..e0306a1a48fc0 100644 --- a/src/core/dos/SDL_dos.c +++ b/src/core/dos/SDL_dos.c @@ -24,10 +24,14 @@ #ifdef __MSDOS__ -#include +#include +#include +#include #include "../../events/SDL_events_c.h" +#define KEYBOARD_INTERRUPT 0x09 + static const SDL_Scancode bios_to_sdl_scancode[128] = { 0, SDL_SCANCODE_ESCAPE, @@ -120,16 +124,168 @@ static const SDL_Scancode bios_to_sdl_scancode[128] = { SDL_SCANCODE_F12, }; +static volatile Uint8 scancode_buf[100]; +static volatile int scancode_count; + +static void +DOS_KeyboardISR(void) +{ + /* Read scancode into buffer. */ + if (scancode_count < SDL_arraysize(scancode_buf)) { + scancode_buf[scancode_count] = inportb(0x60); + } + + scancode_count++; + + /* Acknowledge interrupt. */ + outportb(0x20, 0x20); +} + +static int +DOS_LockKeyboardISR(void) +{ + size_t len = (void *)DOS_LockKeyboardISR - (void *)DOS_KeyboardISR; + + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "DOS: Keyboard ISR code size is %zd bytes", len); + + /* Lock interrupt service routine. */ + if (_go32_dpmi_lock_code(DOS_KeyboardISR, len)) { + return SDL_SetError("DOS: Failed to lock keyboard ISR code (%zd bytes)", len); + } + + /* Lock scancode buffer. */ + if (_go32_dpmi_lock_data((void *)scancode_buf, sizeof(scancode_buf))) { + return SDL_SetError("DOS: Failed to lock scancode buffer (%zu bytes)", sizeof(scancode_buf)); + } + + /* Lock scancode counter. */ + if (_go32_dpmi_lock_data((void *)&scancode_count, sizeof(scancode_count))) { + return SDL_SetError("DOS: Failed to lock scancode counter (%zu bytes)", sizeof(scancode_count)); + } + + return 0; +} + +static SDL_bool kbd_is_init; +static _go32_dpmi_seginfo kbd_isr, old_kbd_isr; + +static int +DOS_InitKeyboard(void) +{ + if (kbd_is_init) { + return 0; + } + + /* Save the original keyboard interrupt service routine. */ + if (_go32_dpmi_get_protected_mode_interrupt_vector(KEYBOARD_INTERRUPT, &old_kbd_isr)) { + return SDL_SetError("DOS: Failed to get original keyboard ISR"); + } + + /* Lock memory that is touched during an interrupt. */ + if (DOS_LockKeyboardISR()) { + return -1; + } + + /* Setup struct for input parameters. */ + kbd_isr.pm_selector = _my_cs(); + kbd_isr.pm_offset = (unsigned long)DOS_KeyboardISR; + + /* Wrap the keyboard ISR so it can be used. */ + if (_go32_dpmi_allocate_iret_wrapper(&kbd_isr)) { + return SDL_SetError("DOS: Failed to wrap keyboard ISR"); + } + + /* Use the new keyboard ISR. */ + if (_go32_dpmi_set_protected_mode_interrupt_vector(KEYBOARD_INTERRUPT, &kbd_isr)) { + _go32_dpmi_free_iret_wrapper(&kbd_isr); + return SDL_SetError("DOS: Failed to set new keyboard ISR"); + } + + kbd_is_init = SDL_TRUE; + + return 0; +} + +static void +DOS_HandleKeyboard(void) +{ + static SDL_bool extended_key = SDL_FALSE; + int i; + + /* Do nothing if no scancodes are buffered. */ + if (!scancode_count) { + return; + } + + /* Convert buffered scancodes to SDL key events. */ + for (i = 0; i < scancode_count && i < SDL_arraysize(scancode_buf); i++) { + Uint8 scan = scancode_buf[i]; + Uint8 state = scan & 0x80 ? SDL_RELEASED : SDL_PRESSED; + + /* Check if the code is an extended key prefix. */ + if (scan == 0xE0) { + extended_key = SDL_TRUE; + continue; + } + + /* Mask off state bit. */ + scan &= 0x7F; + + /* Generate SDL key event. */ + if (extended_key) { + /* TODO: Handle extended keyboard scancodes. */ + } else { + SDL_SendKeyboardKey(state, bios_to_sdl_scancode[scan]); + } + + /* Reset extended key flag. */ + extended_key = SDL_FALSE; + } + + /* Check for scancode buffer overflow. */ + if (scancode_count > SDL_arraysize(scancode_buf)) { + int diff = scancode_count - SDL_arraysize(scancode_buf); + SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "DOS: Scancode buffer overflowed by %d", diff); + + /* Reset extended key flag. */ + extended_key = SDL_FALSE; + } + + scancode_count = 0; +} + +static void +DOS_QuitKeyboard(void) +{ + if (kbd_is_init) { + return; + } + + /* Restore original keyboard interrupt service routine. */ + _go32_dpmi_set_protected_mode_interrupt_vector(KEYBOARD_INTERRUPT, &old_kbd_isr); + + /* Cleanup keyboard ISR wrapper. */ + _go32_dpmi_free_iret_wrapper(&kbd_isr); + + kbd_is_init = SDL_FALSE; +} + +int +SDL_DOS_Init(void) +{ + return DOS_InitKeyboard(); +} + void SDL_DOS_PumpEvents(void) { - /* TODO: Handle enhanced keyboard scancodes. */ - /* TODO: Detect key released events. */ - /* TODO: Send ASCII part to SDL_SendKeyboardText? */ - while (_bios_keybrd(_KEYBRD_READY)) { - Uint8 scan = _bios_keybrd(_KEYBRD_READ) >> 8; - SDL_SendKeyboardKey(SDL_PRESSED, bios_to_sdl_scancode[scan]); - } + DOS_HandleKeyboard(); +} + +void +SDL_DOS_Quit(void) +{ + DOS_QuitKeyboard(); } #endif /* __MSDOS__ */ diff --git a/src/core/dos/SDL_dos.h b/src/core/dos/SDL_dos.h index f4519d77806dc..e069815319b35 100644 --- a/src/core/dos/SDL_dos.h +++ b/src/core/dos/SDL_dos.h @@ -23,7 +23,9 @@ #ifndef SDL_dos_h_ #define SDL_dos_h_ +extern int SDL_DOS_Init(void); extern void SDL_DOS_PumpEvents(void); +extern void SDL_DOS_Quit(void); #endif /* SDL_dos_h_ */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 7baa735a0902b..6f8c5a4cf732e 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -1,6 +1,7 @@ /* Simple DirectMedia Layer Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Jay Petacat This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -28,6 +29,8 @@ #include "../SDL_pixels_c.h" #include "../../events/SDL_events_c.h" +#include "../../core/dos/SDL_dos.h" + #include "SDL_svga_video.h" #include "SDL_svga_events.h" #include "SDL_svga_framebuffer.h" @@ -132,7 +135,7 @@ SVGA_VideoInit(_THIS) return -1; } - return 0; + return SDL_DOS_Init(); } static void @@ -230,6 +233,8 @@ SVGA_VideoQuit(_THIS) if (devdata->original_mode) { SVGA_SetVBEMode(devdata->original_mode); } + + SDL_DOS_Quit(); } static int From cd0e9760125b2c114e1815d345fc3a0ebc146b19 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Mon, 20 Apr 2020 00:20:53 -0400 Subject: [PATCH 34/51] dos: Use PS/2 status register to poll keyboard --- src/core/dos/SDL_dos.c | 82 ++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/src/core/dos/SDL_dos.c b/src/core/dos/SDL_dos.c index e0306a1a48fc0..d20a71ededeee 100644 --- a/src/core/dos/SDL_dos.c +++ b/src/core/dos/SDL_dos.c @@ -32,6 +32,9 @@ #define KEYBOARD_INTERRUPT 0x09 +#define PS2_DATA 0x60 +#define PS2_STATUS 0x64 + static const SDL_Scancode bios_to_sdl_scancode[128] = { 0, SDL_SCANCODE_ESCAPE, @@ -130,13 +133,11 @@ static volatile int scancode_count; static void DOS_KeyboardISR(void) { - /* Read scancode into buffer. */ - if (scancode_count < SDL_arraysize(scancode_buf)) { - scancode_buf[scancode_count] = inportb(0x60); + /* Read scancodes from keyboard into buffer. */ + while (inportb(PS2_STATUS) & 1 && scancode_count < SDL_arraysize(scancode_buf)) { + scancode_buf[scancode_count++] = inportb(PS2_DATA); } - scancode_count++; - /* Acknowledge interrupt. */ outportb(0x20, 0x20); } @@ -207,51 +208,54 @@ DOS_InitKeyboard(void) } static void -DOS_HandleKeyboard(void) +DOS_ProcessScancode(Uint8 scancode) { static SDL_bool extended_key = SDL_FALSE; - int i; + Uint8 state = scancode & 0x80 ? SDL_RELEASED : SDL_PRESSED; - /* Do nothing if no scancodes are buffered. */ - if (!scancode_count) { + /* Check if the code is an extended key prefix. */ + if (scancode == 0xE0) { + extended_key = SDL_TRUE; return; } - /* Convert buffered scancodes to SDL key events. */ - for (i = 0; i < scancode_count && i < SDL_arraysize(scancode_buf); i++) { - Uint8 scan = scancode_buf[i]; - Uint8 state = scan & 0x80 ? SDL_RELEASED : SDL_PRESSED; - - /* Check if the code is an extended key prefix. */ - if (scan == 0xE0) { - extended_key = SDL_TRUE; - continue; - } - - /* Mask off state bit. */ - scan &= 0x7F; - - /* Generate SDL key event. */ - if (extended_key) { - /* TODO: Handle extended keyboard scancodes. */ - } else { - SDL_SendKeyboardKey(state, bios_to_sdl_scancode[scan]); - } - - /* Reset extended key flag. */ - extended_key = SDL_FALSE; + /* Mask off state bit. */ + scancode &= 0x7F; + + /* Generate SDL key event. */ + if (extended_key) { + /* TODO: Handle extended keyboard scancodes. */ + } else { + SDL_SendKeyboardKey(state, bios_to_sdl_scancode[scancode]); } - /* Check for scancode buffer overflow. */ - if (scancode_count > SDL_arraysize(scancode_buf)) { - int diff = scancode_count - SDL_arraysize(scancode_buf); - SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "DOS: Scancode buffer overflowed by %d", diff); + /* Reset extended key flag. */ + extended_key = SDL_FALSE; +} - /* Reset extended key flag. */ - extended_key = SDL_FALSE; +static void +DOS_PollKeyboard(void) +{ + int i; + + /* Convert buffered scancodes to SDL key events. */ + for (i = 0; i < scancode_count; i++) { + DOS_ProcessScancode(scancode_buf[i]); } + /* Reset scancode buffer count. */ + /* TODO: Do not write to scancode buffer while it's being drained here. */ scancode_count = 0; + + /* Read any remaining scancodes from keyboard and convert to SDL key events. */ + for (i = 0; inportb(PS2_STATUS) & 1; i++) { + DOS_ProcessScancode(inportb(PS2_DATA)); + } + + /* Warn if scancode buffer reached maximum capacity. */ + if (i) { + SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "DOS: %d keyboard scancode(s) not buffered", i); + } } static void @@ -279,7 +283,7 @@ SDL_DOS_Init(void) void SDL_DOS_PumpEvents(void) { - DOS_HandleKeyboard(); + DOS_PollKeyboard(); } void From 360dddd136be357b15e6493a904087f2ff0813f4 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Mon, 20 Apr 2020 23:24:18 -0400 Subject: [PATCH 35/51] dos: Do not set `pm_selector` It doesn't seem to be necessary. --- src/core/dos/SDL_dos.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/dos/SDL_dos.c b/src/core/dos/SDL_dos.c index d20a71ededeee..1fea8233538d2 100644 --- a/src/core/dos/SDL_dos.c +++ b/src/core/dos/SDL_dos.c @@ -25,7 +25,6 @@ #ifdef __MSDOS__ #include -#include #include #include "../../events/SDL_events_c.h" @@ -188,7 +187,6 @@ DOS_InitKeyboard(void) } /* Setup struct for input parameters. */ - kbd_isr.pm_selector = _my_cs(); kbd_isr.pm_offset = (unsigned long)DOS_KeyboardISR; /* Wrap the keyboard ISR so it can be used. */ From e8c6797b937c01dabab4bfbb9587c2ae31d9f433 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Thu, 23 Apr 2020 00:43:40 -0400 Subject: [PATCH 36/51] svga: Add some debug logs --- src/video/svga/SDL_svga_video.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 6f8c5a4cf732e..fb50000f2c5a4 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -54,8 +54,18 @@ static int SVGA_Available(void) { VBEInfo info; + int status = SVGA_GetVBEInfo(&info); - return SVGA_GetVBEInfo(&info) == 0 && info.vbe_version.major >= 2; + if (status) { + /* TODO: Differentiate between failure and missing. */ + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA_GetVBEInfo failed: %d", status); + return 0; + } + + SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "SVGA: Detected VESA BIOS Extensions v%u.%u", + info.vbe_version.major, info.vbe_version.minor); + + return info.vbe_version.major >= 2; } static void @@ -155,29 +165,35 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) ) { SDL_DisplayModeData *modedata; VBEModeInfo info; + int status = SVGA_GetVBEModeInfo(vbe_mode, &info); - if (SVGA_GetVBEModeInfo(vbe_mode, &info)) { + if (status) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "SVGA_GetVBEModeInfo failed: %d", status); return; } /* Mode must support graphics with a linear framebuffer. */ if ((info.mode_attributes & VBE_MODE_ATTRS) != VBE_MODE_ATTRS) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA: Ignoring mode 0x%X: Bad attributes", vbe_mode); continue; } /* Mode must be a known pixel format. */ mode.format = SVGA_GetPixelFormat(&info); if (mode.format == SDL_PIXELFORMAT_UNKNOWN) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA: Ignoring mode 0x%X: Bad pixel format", vbe_mode); continue; } /* Mode must be capable of double buffering. */ if (!info.number_of_image_pages) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA: Ignoring mode 0x%X: No double-buffering", vbe_mode); continue; } /* Scan lines must be 4-byte aligned to match SDL surface pitch. */ if (info.bytes_per_scan_line % 4 != 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA: Ignoring mode 0x%X: Bad pitch", vbe_mode); continue; } @@ -197,6 +213,8 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) SDL_free(modedata); } } + + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA: VBE lists %d modes", index - 1); } static int From 58863ebc17b812a2214a32e2ea81a9bd4163ab3c Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 6 Feb 2021 23:03:07 -0500 Subject: [PATCH 37/51] svga: Remove obsolete SVGA_Available --- src/video/svga/SDL_svga_video.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index fb50000f2c5a4..e664bc9fd29c7 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -50,24 +50,6 @@ static void SVGA_DestroyWindow(_THIS, SDL_Window * window); /* SVGA driver bootstrap functions */ -static int -SVGA_Available(void) -{ - VBEInfo info; - int status = SVGA_GetVBEInfo(&info); - - if (status) { - /* TODO: Differentiate between failure and missing. */ - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SVGA_GetVBEInfo failed: %d", status); - return 0; - } - - SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "SVGA: Detected VESA BIOS Extensions v%u.%u", - info.vbe_version.major, info.vbe_version.minor); - - return info.vbe_version.major >= 2; -} - static void SVGA_DeleteDevice(SDL_VideoDevice * device) { @@ -87,6 +69,8 @@ SVGA_CreateDevice(int devindex) } if (SVGA_GetVBEInfo(&devdata->vbe_info) || devdata->vbe_info.vbe_version.major < 2) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "SVGA: VESA BIOS Extensions v2.0 or greater is required"); + SDL_Unsupported(); SDL_free(devdata); return NULL; } @@ -120,7 +104,7 @@ SVGA_CreateDevice(int devindex) VideoBootStrap SVGA_bootstrap = { SVGAVID_DRIVER_NAME, "SDL SVGA video driver", - SVGA_Available, SVGA_CreateDevice + SVGA_CreateDevice }; static int From 0dca3332e31fa0736ac4e438c7035d683ebac59a Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Sat, 2 May 2020 00:45:46 -0400 Subject: [PATCH 38/51] WIP: dos: Add mouse support --- src/video/svga/SDL_svga_events.c | 2 + src/video/svga/SDL_svga_framebuffer.c | 38 ++++++- src/video/svga/SDL_svga_mouse.c | 151 ++++++++++++++++++++++++++ src/video/svga/SDL_svga_mouse.h | 33 ++++++ src/video/svga/SDL_svga_video.c | 21 ++-- 5 files changed, 234 insertions(+), 11 deletions(-) create mode 100644 src/video/svga/SDL_svga_mouse.c create mode 100644 src/video/svga/SDL_svga_mouse.h diff --git a/src/video/svga/SDL_svga_events.c b/src/video/svga/SDL_svga_events.c index 684cf82a79c74..2aba365058840 100644 --- a/src/video/svga/SDL_svga_events.c +++ b/src/video/svga/SDL_svga_events.c @@ -26,11 +26,13 @@ #include "../../core/dos/SDL_dos.h" #include "SDL_svga_events.h" +#include "SDL_svga_mouse.h" void SVGA_PumpEvents(_THIS) { SDL_DOS_PumpEvents(); + DOS_PollMouse(); } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index ca2271e1d67de..c23ad11a5c166 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -99,12 +99,38 @@ SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** return 0; } +/* TODO: Draw a real pointer. */ +static void +CopyCursorPixels(SDL_Window * window) +{ + SDL_Surface *surface = window->surface; + SDL_WindowData *windata = window->driverdata; + size_t surface_size = surface->pitch * surface->h; + size_t framebuffer_offset = windata->framebuffer_page ? surface_size : 0; + Uint32 color = SDL_MapRGB(surface->format, 0xFF, 0, 0); + int i, k, x, y; + + SDL_GetMouseState(&x, &y); + x = SDL_max(x, 0); + y = SDL_max(y, 0); + x = SDL_min(x, surface->w - 4); + y = SDL_min(y, surface->h - 4); + + for (i = 0; i < 4; i++) { + for (k = 0; k < 4; k++) { + movedata(_my_ds(), (uintptr_t)&color, windata->framebuffer_selector, + framebuffer_offset + surface->pitch * (y + i) + (x + k) * surface->format->BytesPerPixel, + surface->format->BytesPerPixel); + } + } +} + int SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) { SDL_WindowData *windata = window->driverdata; SDL_Surface *surface = window->surface; - size_t surface_size; + size_t framebuffer_offset, surface_size; if (!surface) { return SDL_SetError("Missing SVGA surface"); @@ -114,10 +140,14 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i /* Flip the active page flag. */ windata->framebuffer_page = !windata->framebuffer_page; + framebuffer_offset = windata->framebuffer_page ? surface_size : 0; + + /* Copy surface pixels to hidden framebuffer. */ + movedata(_my_ds(), (uintptr_t)surface->pixels, windata->framebuffer_selector, + framebuffer_offset, surface_size); - /* Copy pixels to hidden framebuffer page. */ - movedata(_my_ds(), (Uint32)surface->pixels, windata->framebuffer_selector, - windata->framebuffer_page ? surface_size : 0, surface_size); + /* Copy cursor pixels to hidden framebuffer. */ + CopyCursorPixels(window); /* Display fresh page to screen. */ SVGA_SetDisplayStart(0, windata->framebuffer_page ? surface->h : 0); diff --git a/src/video/svga/SDL_svga_mouse.c b/src/video/svga/SDL_svga_mouse.c new file mode 100644 index 0000000000000..9d78b8111d51d --- /dev/null +++ b/src/video/svga/SDL_svga_mouse.c @@ -0,0 +1,151 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Jay Petacat + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_SVGA + +#include "SDL_svga_mouse.h" + +#include + +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_mouse_c.h" + +#define MOUSE_INTERRUPT 0x33 + +static Uint8 DOS_MouseButtons[] = { + SDL_BUTTON_LEFT, + SDL_BUTTON_RIGHT, + SDL_BUTTON_MIDDLE, +}; + +static SDL_Cursor * +DOS_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) +{ + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); + + return cursor; +} + +static SDL_Cursor * +DOS_CreateSystemCursor(SDL_SystemCursor id) +{ + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); + + return cursor; +} + +static void +DOS_FreeCursor(SDL_Cursor * cursor) +{ + SDL_free(cursor); +} + +static int +DOS_ShowCursor(SDL_Cursor * cursor) +{ + __dpmi_regs r; + + r.x.ax = cursor ? 1 : 2; + + return __dpmi_int(MOUSE_INTERRUPT, &r); +} + +static void +DOS_WarpMouse(SDL_Window * window, int x, int y) +{ +} + +void +DOS_InitMouse(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + __dpmi_regs r; + + r.x.ax = 0; + + if (__dpmi_int(MOUSE_INTERRUPT, &r) || r.x.ax != 0xFFFF) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "DOS: No mouse installed"); + return; + } + + mouse->CreateCursor = DOS_CreateCursor; + mouse->CreateSystemCursor = DOS_CreateSystemCursor; + mouse->ShowCursor = DOS_ShowCursor; + mouse->FreeCursor = DOS_FreeCursor; + mouse->WarpMouse = DOS_WarpMouse; + + // SDL_SetDefaultCursor(DEFAULT_CURSOR); +} + +void +DOS_QuitMouse(void) +{ +} + +void DOS_PollMouse(void) +{ + static int last_button_status; + int button_status, i; + __dpmi_regs r; + + /* TODO: Determine if movement happened using interrupt callback. */ + + r.x.ax = 0xB; + + if (__dpmi_int(MOUSE_INTERRUPT, &r)) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DOS: Failed to query mouse position"); + DOS_QuitMouse(); + return; + } + + if (r.x.cx || r.x.dx) { + SDL_SendMouseMotion(NULL, 0, SDL_TRUE, (Sint16)r.x.cx, (Sint16)r.x.dx); + } + + r.x.ax = 3; + + if (__dpmi_int(MOUSE_INTERRUPT, &r)) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DOS: Failed to query mouse state"); + DOS_QuitMouse(); + return; + } + + button_status = r.x.bx; + + for (i = 0; i < SDL_arraysize(DOS_MouseButtons); i++) { + int mask = 1 << i; + int diff = button_status ^ last_button_status; + + if (diff & mask) { + Uint8 state = button_status & mask ? SDL_PRESSED : SDL_RELEASED; + SDL_SendMouseButton(NULL, 0, state, DOS_MouseButtons[i]); + } + } + + last_button_status = button_status; +} + +#endif /* SDL_VIDEO_DRIVER_SVGA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_mouse.h b/src/video/svga/SDL_svga_mouse.h new file mode 100644 index 0000000000000..344496aa74bb2 --- /dev/null +++ b/src/video/svga/SDL_svga_mouse.h @@ -0,0 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Jay Petacat + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_svga_mouse_h_ +#define SDL_svga_mouse_h_ + +extern void DOS_InitMouse(void); +extern void DOS_PollMouse(void); +extern void DOS_QuitMouse(void); + +#endif /* SDL_svga_mouse_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index e664bc9fd29c7..d70497d24d9a7 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -23,17 +23,13 @@ #if SDL_VIDEO_DRIVER_SVGA -#include "SDL_video.h" -#include "SDL_mouse.h" -#include "../SDL_sysvideo.h" -#include "../SDL_pixels_c.h" -#include "../../events/SDL_events_c.h" +#include "SDL_svga_video.h" #include "../../core/dos/SDL_dos.h" -#include "SDL_svga_video.h" #include "SDL_svga_events.h" #include "SDL_svga_framebuffer.h" +#include "SDL_svga_mouse.h" #define SVGAVID_DRIVER_NAME "svga" @@ -129,7 +125,15 @@ SVGA_VideoInit(_THIS) return -1; } - return SDL_DOS_Init(); + /* Initialize keyboard. */ + /* TODO: Just move keyboard stuff under this module and rename to DOS! */ + if (SDL_DOS_Init()) { + return -1; + } + + DOS_InitMouse(); + + return 0; } static void @@ -217,6 +221,8 @@ SVGA_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) /* TODO: Switch to 8 bit palette format, if possible and relevant. */ + DOS_InitMouse(); /* TODO: Is this necessary when video mode changes? */ + return 0; } @@ -237,6 +243,7 @@ SVGA_VideoQuit(_THIS) } SDL_DOS_Quit(); + DOS_QuitMouse(); } static int From 0a8e2bc28b307d58d5f77370db77a6fe3b0e5128 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sun, 31 Aug 2025 00:56:32 +0200 Subject: [PATCH 39/51] Add SDL_mouse.h include to SDL_svga_framebuffer.c --- src/video/svga/SDL_svga_framebuffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index c23ad11a5c166..320fa08edddc1 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -26,6 +26,7 @@ #include #include +#include "SDL_mouse.h" #include "SDL_svga_video.h" #include "SDL_svga_framebuffer.h" From 643bd9b4ac1108c42588c3f88e333d6bc9c956f6 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 31 Aug 2025 17:30:15 +0100 Subject: [PATCH 40/51] dos: fix functions for latest SDL2 --- src/timer/dos/SDL_systimer.c | 8 ++++---- src/video/svga/SDL_svga_video.c | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/timer/dos/SDL_systimer.c b/src/timer/dos/SDL_systimer.c index 90978059559a6..fd13687d6ae3d 100644 --- a/src/timer/dos/SDL_systimer.c +++ b/src/timer/dos/SDL_systimer.c @@ -46,14 +46,14 @@ SDL_TicksQuit(void) ticks_started = SDL_FALSE; } -Uint32 -SDL_GetTicks(void) +Uint64 +SDL_GetTicks64(void) { if (!ticks_started) { SDL_TicksInit(); } - return (clock() - start) * 1000 / CLOCKS_PER_SEC; + return (Uint64)((clock() - start) * 1000 / CLOCKS_PER_SEC); } Uint64 @@ -72,7 +72,7 @@ SDL_GetPerformanceFrequency(void) #ifdef HAVE_UCLOCK return UCLOCKS_PER_SEC; #else - return return 1000; + return 1000; #endif } diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index d70497d24d9a7..758ec9e2b3b98 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -53,7 +53,7 @@ SVGA_DeleteDevice(SDL_VideoDevice * device) } static SDL_VideoDevice * -SVGA_CreateDevice(int devindex) +SVGA_CreateDevice(void) { SDL_VideoDevice *device; SDL_DeviceData *devdata; @@ -100,7 +100,8 @@ SVGA_CreateDevice(int devindex) VideoBootStrap SVGA_bootstrap = { SVGAVID_DRIVER_NAME, "SDL SVGA video driver", - SVGA_CreateDevice + SVGA_CreateDevice, + NULL /* no ShowMessageBox implementation */ }; static int From 5f92a76ef925a0819545681b4c06435b0380a9d7 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 31 Aug 2025 18:20:53 +0100 Subject: [PATCH 41/51] dos: Do not bother attempting framebuffer texture --- src/video/SDL_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 717ca02298a29..5de7277050b12 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2705,7 +2705,7 @@ static SDL_bool ShouldAttemptTextureFramebuffer(void) attempt_texture_framebuffer = SDL_FALSE; } #endif -#if defined(__EMSCRIPTEN__) +#if defined(__EMSCRIPTEN__) || defined(__MSDOS__) attempt_texture_framebuffer = SDL_FALSE; #endif } From 8048fa33d5872981624a426246389b3faa6d23a5 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 31 Aug 2025 18:38:40 +0100 Subject: [PATCH 42/51] dos: #if SDL_VIDEO_DRIVER_SVGA -> #ifdef --- src/video/SDL_video.c | 2 +- src/video/svga/SDL_svga_events.c | 2 +- src/video/svga/SDL_svga_framebuffer.c | 4 ++-- src/video/svga/SDL_svga_mouse.c | 2 +- src/video/svga/SDL_svga_vbe.c | 2 +- src/video/svga/SDL_svga_video.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 5de7277050b12..445c721d61c34 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -143,7 +143,7 @@ static VideoBootStrap *bootstrap[] = { &OS2DIVE_bootstrap, &OS2VMAN_bootstrap, #endif -#if SDL_VIDEO_DRIVER_SVGA +#ifdef SDL_VIDEO_DRIVER_SVGA &SVGA_bootstrap, #endif #ifdef SDL_VIDEO_DRIVER_NGAGE diff --git a/src/video/svga/SDL_svga_events.c b/src/video/svga/SDL_svga_events.c index 2aba365058840..7e4484286a767 100644 --- a/src/video/svga/SDL_svga_events.c +++ b/src/video/svga/SDL_svga_events.c @@ -21,7 +21,7 @@ */ #include "../../SDL_internal.h" -#if SDL_VIDEO_DRIVER_SVGA +#ifdef SDL_VIDEO_DRIVER_SVGA #include "../../core/dos/SDL_dos.h" diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 320fa08edddc1..1c945bb1db589 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -20,7 +20,7 @@ */ #include "../../SDL_internal.h" -#if SDL_VIDEO_DRIVER_SVGA +#ifdef SDL_VIDEO_DRIVER_SVGA #include #include @@ -151,7 +151,7 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i CopyCursorPixels(window); /* Display fresh page to screen. */ - SVGA_SetDisplayStart(0, windata->framebuffer_page ? surface->h : 0); + SVGA_SetDisplayStart(0, windata->framebuffer_page ? surface->h : 0); return 0; } diff --git a/src/video/svga/SDL_svga_mouse.c b/src/video/svga/SDL_svga_mouse.c index 9d78b8111d51d..f84372205eb5d 100644 --- a/src/video/svga/SDL_svga_mouse.c +++ b/src/video/svga/SDL_svga_mouse.c @@ -22,7 +22,7 @@ #include "../../SDL_internal.h" -#if SDL_VIDEO_DRIVER_SVGA +#ifdef SDL_VIDEO_DRIVER_SVGA #include "SDL_svga_mouse.h" diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 7f8687b62a0b8..81b89a88a852c 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -20,7 +20,7 @@ */ #include "../../SDL_internal.h" -#if SDL_VIDEO_DRIVER_SVGA +#ifdef SDL_VIDEO_DRIVER_SVGA #include "SDL_svga_vbe.h" diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 758ec9e2b3b98..14b553ab82682 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -21,7 +21,7 @@ */ #include "../../SDL_internal.h" -#if SDL_VIDEO_DRIVER_SVGA +#ifdef SDL_VIDEO_DRIVER_SVGA #include "SDL_svga_video.h" From 6a87741b50e52b93852eb8ab59a89495ae9e607b Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 31 Aug 2025 20:35:07 +0100 Subject: [PATCH 43/51] dos: Add CMake configuration Example toolchain file: ```bash set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_VERSION 1) if($ENV{DJGPP_PREFIX}) set(DJGPP_PREFIX "$ENV{DJGPP_PREFIX}") else() set(DJGPP_PREFIX "/opt/i386-pc-msdosdjgpp-toolchain") endif() set(CMAKE_C_COMPILER "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-gcc") set(CMAKE_CXX_COMPILER "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-g++") set(CMAKE_STRIP "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-strip") set(PKG_CONFIG_EXECUTABLE "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-pkg-config" CACHE STRING "Path to pkg-config") set(CMAKE_EXE_LINKER_FLAGS_INIT "-static") set(DJGPP_ROOT "${DJGPP_PREFIX}/i386-pc-msdosdjgpp") set(CMAKE_FIND_ROOT_PATH "${DJGPP_ROOT}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) link_directories("${DJGPP_ROOT}/lib") include_directories(BEFORE SYSTEM "${DJGPP_ROOT}/sys-include" "${DJGPP_ROOT}/include") ``` Example invocation: ```bash cmake -S. -Bbuild-dos -DCMAKE_TOOLCHAIN_FILE="path/to/djcpp.toolchain.cmake" -DDOS=ON ``` --- CMakeLists.txt | 43 ++++++++++++++++++++++++++++++++++---- include/SDL_config.h.cmake | 3 +++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d609224783019..945ba02402420 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,7 +241,7 @@ if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC) endif() # Default option knobs -if(UNIX OR MINGW OR MSYS OR (USE_CLANG AND NOT WINDOWS) OR VITA OR PSP OR PS2 OR N3DS OR SDL_CPU_ARM64EC) +if(UNIX OR MINGW OR MSYS OR (USE_CLANG AND NOT WINDOWS) OR VITA OR PSP OR PS2 OR N3DS OR SDL_CPU_ARM64EC OR DOS) set(OPT_DEF_LIBC ON) endif() if(WINDOWS OR MACOS OR IOS OR TVOS OR VISIONOS OR WATCHOS) @@ -358,11 +358,20 @@ if(EMSCRIPTEN) set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF) endif() -if(VITA OR PSP OR PS2 OR N3DS) +if(VITA OR PSP OR PS2 OR N3DS OR DOS) set(SDL_SHARED_ENABLED_BY_DEFAULT OFF) set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF) endif() +if(DOS) + set(SDL_THREADS_ENABLED_BY_DEFAULT OFF) + set(SDL_SSE OFF) + set(SDL_SSE2 OFF) + set(SDL_SSE3 OFF) + set(SDL_MMX OFF) + set(SDL_3DNOW OFF) +endif() + set(SDL_X11_XRANDR_DEFAULT ON) if(SOLARIS) set(SDL_X11_XRANDR_DEFAULT OFF) @@ -412,7 +421,7 @@ set_option(SDL2_DISABLE_UNINSTALL "Disable uninstallation of SDL2" OFF) option_string(SDL_ASSERTIONS "Enable internal sanity checks (auto/disabled/release/enabled/paranoid)" "auto") #set_option(SDL_DEPENDENCY_TRACKING "Use gcc -MMD -MT dependency tracking" ON) set_option(SDL_ASSEMBLY "Enable assembly routines" ${OPT_DEF_ASM}) -dep_option(SDL_SSEMATH "Allow GCC to use SSE floating point math" ON "SDL_ASSEMBLY;SDL_CPU_X86 OR SDL_CPU_X64" OFF) +dep_option(SDL_SSEMATH "Allow GCC to use SSE floating point math" ON "SDL_ASSEMBLY;SDL_CPU_X86 OR SDL_CPU_X64;NOT DOS" OFF) dep_option(SDL_SSE "Use SSE assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_X86 OR SDL_CPU_X64" OFF) dep_option(SDL_SSE2 "Use SSE2 assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_X86 OR SDL_CPU_X64" OFF) dep_option(SDL_SSE3 "Use SSE3 assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_X86 OR SDL_CPU_X64" OFF) @@ -525,6 +534,10 @@ if(VITA) set_option(VIDEO_VITA_PVR "Build with PSVita PVR gles/gles2 support" OFF) endif() +if(DOS) + set_option(SDL_DOS_UCLOCK "Whether to use uclock() for performance counter on DOS" TRUE) +endif() + # General source files file(GLOB SOURCE_FILES ${SDL2_SOURCE_DIR}/src/*.c @@ -2873,6 +2886,28 @@ elseif(OS2) CheckHIDAPI() endif() +elseif(DOS) + file(GLOB DOS_CORE_SOURCES ${SDL2_SOURCE_DIR}/src/core/dos/*.c) + list(APPEND SOURCE_FILES ${DOS_CORE_SOURCES}) + + if(SDL_TIMERS) + if(SDL_DOS_UCLOCK) + set(HAVE_UCLOCK TRUE) + endif() + + set(SDL_TIMER_DOS 1) + file(GLOB DOS_TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/dos/*.c) + list(APPEND SOURCE_FILES ${DOS_TIMER_SOURCES}) + set(HAVE_SDL_TIMERS TRUE) + endif() + + if(SDL_VIDEO) + set(SDL_VIDEO_DRIVER_SVGA 1) + file(GLOB SVGA_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/svga/*.c) + list(APPEND SOURCE_FILES ${SVGA_VIDEO_SOURCES}) + set(HAVE_SDL_VIDEO TRUE) + endif() + elseif(N3DS) file(GLOB N3DS_MAIN_SOURCES ${SDL2_SOURCE_DIR}/src/main/n3ds/*.c) set(SDLMAIN_SOURCES ${SDLMAIN_SOURCES} ${N3DS_MAIN_SOURCES}) @@ -3028,7 +3063,7 @@ endif() # We always need to have threads and timers around if(NOT HAVE_SDL_THREADS) # The emscripten platform has been carefully vetted to work without threads - if (EMSCRIPTEN) + if (EMSCRIPTEN OR DOS) set(SDL_THREADS_DISABLED 1) file(GLOB THREADS_SOURCES ${SDL2_SOURCE_DIR}/src/thread/generic/*.c) list(APPEND SOURCE_FILES ${THREADS_SOURCES}) diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index 64b8413c8cdc7..934141280c8fa 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -229,6 +229,7 @@ #cmakedefine HAVE_INOTIFY 1 #cmakedefine HAVE_LIBUSB 1 #cmakedefine HAVE_O_CLOEXEC 1 +#cmakedefine HAVE_UCLOCK /* Apple platforms might be building universal binaries, where Intel builds can use immintrin.h but other architectures can't. */ @@ -398,6 +399,7 @@ #cmakedefine SDL_TIMER_UNIX @SDL_TIMER_UNIX@ #cmakedefine SDL_TIMER_WINDOWS @SDL_TIMER_WINDOWS@ #cmakedefine SDL_TIMER_OS2 @SDL_TIMER_OS2@ +#cmakedefine SDL_TIMER_DOS @SDL_TIMER_DOS@ #cmakedefine SDL_TIMER_VITA @SDL_TIMER_VITA@ #cmakedefine SDL_TIMER_PSP @SDL_TIMER_PSP@ #cmakedefine SDL_TIMER_PS2 @SDL_TIMER_PS2@ @@ -420,6 +422,7 @@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@ #cmakedefine SDL_VIDEO_DRIVER_OS2 @SDL_VIDEO_DRIVER_OS2@ +#cmakedefine SDL_VIDEO_DRIVER_SVGA @SDL_VIDEO_DRIVER_SVGA@ #cmakedefine SDL_VIDEO_DRIVER_QNX @SDL_VIDEO_DRIVER_QNX@ #cmakedefine SDL_VIDEO_DRIVER_RISCOS @SDL_VIDEO_DRIVER_RISCOS@ #cmakedefine SDL_VIDEO_DRIVER_PSP @SDL_VIDEO_DRIVER_PSP@ From 6529694137e7cb586ee7ec389ec4bd578ca84d0c Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 1 Sep 2025 00:31:48 +0100 Subject: [PATCH 44/51] dos: implement some extended keys Makes the arrow keys and page up/down work. --- src/core/dos/SDL_dos.c | 314 +++++++++++++++++++++++++++++------------ 1 file changed, 223 insertions(+), 91 deletions(-) diff --git a/src/core/dos/SDL_dos.c b/src/core/dos/SDL_dos.c index 1fea8233538d2..ac23994e6eda9 100644 --- a/src/core/dos/SDL_dos.c +++ b/src/core/dos/SDL_dos.c @@ -35,99 +35,231 @@ #define PS2_STATUS 0x64 static const SDL_Scancode bios_to_sdl_scancode[128] = { - 0, - SDL_SCANCODE_ESCAPE, - SDL_SCANCODE_1, - SDL_SCANCODE_2, - SDL_SCANCODE_3, - SDL_SCANCODE_4, - SDL_SCANCODE_5, - SDL_SCANCODE_6, - SDL_SCANCODE_7, - SDL_SCANCODE_8, - SDL_SCANCODE_9, - SDL_SCANCODE_0, - SDL_SCANCODE_MINUS, - SDL_SCANCODE_EQUALS, - SDL_SCANCODE_BACKSPACE, - SDL_SCANCODE_TAB, - SDL_SCANCODE_Q, - SDL_SCANCODE_W, - SDL_SCANCODE_E, - SDL_SCANCODE_R, - SDL_SCANCODE_T, - SDL_SCANCODE_Y, - SDL_SCANCODE_U, - SDL_SCANCODE_I, - SDL_SCANCODE_O, - SDL_SCANCODE_P, - SDL_SCANCODE_LEFTBRACKET, - SDL_SCANCODE_RIGHTBRACKET, - SDL_SCANCODE_RETURN, - SDL_SCANCODE_LCTRL, - SDL_SCANCODE_A, - SDL_SCANCODE_S, - SDL_SCANCODE_D, - SDL_SCANCODE_F, - SDL_SCANCODE_G, - SDL_SCANCODE_H, - SDL_SCANCODE_J, - SDL_SCANCODE_K, - SDL_SCANCODE_L, - SDL_SCANCODE_SEMICOLON, - SDL_SCANCODE_APOSTROPHE, - SDL_SCANCODE_GRAVE, - SDL_SCANCODE_LSHIFT, - SDL_SCANCODE_BACKSLASH, - SDL_SCANCODE_Z, - SDL_SCANCODE_X, - SDL_SCANCODE_C, - SDL_SCANCODE_V, - SDL_SCANCODE_B, - SDL_SCANCODE_N, - SDL_SCANCODE_M, - SDL_SCANCODE_COMMA, - SDL_SCANCODE_PERIOD, - SDL_SCANCODE_SLASH, - SDL_SCANCODE_RSHIFT, - SDL_SCANCODE_KP_MULTIPLY, - SDL_SCANCODE_LALT, - SDL_SCANCODE_SPACE, - SDL_SCANCODE_CAPSLOCK, - SDL_SCANCODE_F1, - SDL_SCANCODE_F2, - SDL_SCANCODE_F3, - SDL_SCANCODE_F4, - SDL_SCANCODE_F5, - SDL_SCANCODE_F6, - SDL_SCANCODE_F7, - SDL_SCANCODE_F8, - SDL_SCANCODE_F9, - SDL_SCANCODE_F10, - SDL_SCANCODE_NUMLOCKCLEAR, - SDL_SCANCODE_SCROLLLOCK, - SDL_SCANCODE_KP_7, - SDL_SCANCODE_KP_8, - SDL_SCANCODE_KP_9, - SDL_SCANCODE_KP_MINUS, - SDL_SCANCODE_KP_4, - SDL_SCANCODE_KP_5, - SDL_SCANCODE_KP_6, - SDL_SCANCODE_KP_PLUS, - SDL_SCANCODE_KP_1, - SDL_SCANCODE_KP_2, - SDL_SCANCODE_KP_3, - SDL_SCANCODE_KP_0, - SDL_SCANCODE_KP_PERIOD, - SDL_SCANCODE_SYSREQ, - 0, - SDL_SCANCODE_LGUI, - SDL_SCANCODE_F11, - SDL_SCANCODE_F12, + 0, /* 0 0x00 */ + SDL_SCANCODE_ESCAPE, /* 1 0x01 */ + SDL_SCANCODE_1, /* 2 0x02 */ + SDL_SCANCODE_2, /* 3 0x03 */ + SDL_SCANCODE_3, /* 4 0x04 */ + SDL_SCANCODE_4, /* 5 0x05 */ + SDL_SCANCODE_5, /* 6 0x06 */ + SDL_SCANCODE_6, /* 7 0x07 */ + SDL_SCANCODE_7, /* 8 0x08 */ + SDL_SCANCODE_8, /* 9 0x09 */ + SDL_SCANCODE_9, /* 10 0x0a */ + SDL_SCANCODE_0, /* 11 0x0b */ + SDL_SCANCODE_MINUS, /* 12 0x0c */ + SDL_SCANCODE_EQUALS, /* 13 0x0d */ + SDL_SCANCODE_BACKSPACE, /* 14 0x0e */ + SDL_SCANCODE_TAB, /* 15 0x0f */ + SDL_SCANCODE_Q, /* 16 0x10 */ + SDL_SCANCODE_W, /* 17 0x11 */ + SDL_SCANCODE_E, /* 18 0x12 */ + SDL_SCANCODE_R, /* 19 0x13 */ + SDL_SCANCODE_T, /* 20 0x14 */ + SDL_SCANCODE_Y, /* 21 0x15 */ + SDL_SCANCODE_U, /* 22 0x16 */ + SDL_SCANCODE_I, /* 23 0x17 */ + SDL_SCANCODE_O, /* 24 0x18 */ + SDL_SCANCODE_P, /* 25 0x19 */ + SDL_SCANCODE_LEFTBRACKET, /* 26 0x1a */ + SDL_SCANCODE_RIGHTBRACKET, /* 27 0x1b */ + SDL_SCANCODE_RETURN, /* 28 0x1c */ + SDL_SCANCODE_LCTRL, /* 29 0x1d */ + SDL_SCANCODE_A, /* 30 0x1e */ + SDL_SCANCODE_S, /* 31 0x1f */ + SDL_SCANCODE_D, /* 32 0x20 */ + SDL_SCANCODE_F, /* 33 0x21 */ + SDL_SCANCODE_G, /* 34 0x22 */ + SDL_SCANCODE_H, /* 35 0x23 */ + SDL_SCANCODE_J, /* 36 0x24 */ + SDL_SCANCODE_K, /* 37 0x25 */ + SDL_SCANCODE_L, /* 38 0x26 */ + SDL_SCANCODE_SEMICOLON, /* 39 0x27 */ + SDL_SCANCODE_APOSTROPHE, /* 40 0x28 */ + SDL_SCANCODE_GRAVE, /* 41 0x29 */ + SDL_SCANCODE_LSHIFT, /* 42 0x2a */ + SDL_SCANCODE_BACKSLASH, /* 43 0x2b */ + SDL_SCANCODE_Z, /* 44 0x2c */ + SDL_SCANCODE_X, /* 45 0x2d */ + SDL_SCANCODE_C, /* 46 0x2e */ + SDL_SCANCODE_V, /* 47 0x2f */ + SDL_SCANCODE_B, /* 48 0x30 */ + SDL_SCANCODE_N, /* 49 0x31 */ + SDL_SCANCODE_M, /* 50 0x32 */ + SDL_SCANCODE_COMMA, /* 51 0x33 */ + SDL_SCANCODE_PERIOD, /* 52 0x34 */ + SDL_SCANCODE_SLASH, /* 53 0x35 */ + SDL_SCANCODE_RSHIFT, /* 54 0x36 */ + SDL_SCANCODE_KP_MULTIPLY, /* 55 0x37 */ + SDL_SCANCODE_LALT, /* 56 0x38 */ + SDL_SCANCODE_SPACE, /* 57 0x39 */ + SDL_SCANCODE_CAPSLOCK, /* 58 0x3a */ + SDL_SCANCODE_F1, /* 59 0x3b */ + SDL_SCANCODE_F2, /* 60 0x3c */ + SDL_SCANCODE_F3, /* 61 0x3d */ + SDL_SCANCODE_F4, /* 62 0x3e */ + SDL_SCANCODE_F5, /* 63 0x3f */ + SDL_SCANCODE_F6, /* 64 0x40 */ + SDL_SCANCODE_F7, /* 65 0x41 */ + SDL_SCANCODE_F8, /* 66 0x42 */ + SDL_SCANCODE_F9, /* 67 0x43 */ + SDL_SCANCODE_F10, /* 68 0x44 */ + SDL_SCANCODE_NUMLOCKCLEAR, /* 69 0x45 */ + SDL_SCANCODE_SCROLLLOCK, /* 70 0x46 */ + SDL_SCANCODE_KP_7, /* 71 0x47 */ + SDL_SCANCODE_KP_8, /* 72 0x48 */ + SDL_SCANCODE_KP_9, /* 73 0x49 */ + SDL_SCANCODE_KP_MINUS, /* 74 0x4a */ + SDL_SCANCODE_KP_4, /* 75 0x4b */ + SDL_SCANCODE_KP_5, /* 76 0x4c */ + SDL_SCANCODE_KP_6, /* 77 0x4d */ + SDL_SCANCODE_KP_PLUS, /* 78 0x4e */ + SDL_SCANCODE_KP_1, /* 79 0x4f */ + SDL_SCANCODE_KP_2, /* 80 0x50 */ + SDL_SCANCODE_KP_3, /* 81 0x51 */ + SDL_SCANCODE_KP_0, /* 82 0x52 */ + SDL_SCANCODE_KP_PERIOD, /* 83 0x53 */ + SDL_SCANCODE_SYSREQ, /* 84 0x54 */ + 0, /* 85 0x55 */ + SDL_SCANCODE_LGUI, /* 86 0x56 */ + SDL_SCANCODE_F11, /* 87 0x57 */ + SDL_SCANCODE_F12, /* 88 0x58 */ +}; + +/* Keys that are first indicated by 0xE0 */ +static const SDL_Scancode extended_key_to_sdl_scancode[128] = { + 0, /* 0 0x00 */ + 0, /* 1 0x01 */ + 0, /* 2 0x02 */ + 0, /* 3 0x03 */ + 0, /* 4 0x04 */ + 0, /* 5 0x05 */ + 0, /* 6 0x06 */ + 0, /* 7 0x07 */ + 0, /* 8 0x08 */ + 0, /* 9 0x09 */ + 0, /* 10 0x0a */ + 0, /* 11 0x0b */ + 0, /* 12 0x0c */ + 0, /* 13 0x0d */ + 0, /* 14 0x0e */ + 0, /* 15 0x0f */ + 0, /* 16 0x10 */ + 0, /* 17 0x11 */ + 0, /* 18 0x12 */ + 0, /* 19 0x13 */ + 0, /* 20 0x14 */ + 0, /* 21 0x15 */ + 0, /* 22 0x16 */ + 0, /* 23 0x17 */ + 0, /* 24 0x18 */ + 0, /* 25 0x19 */ + 0, /* 26 0x1a */ + 0, /* 27 0x1b */ + SDL_SCANCODE_KP_ENTER, /* 28 0x1c */ + SDL_SCANCODE_RALT, /* 29 0x1d */ + 0, /* 30 0x1e */ + 0, /* 31 0x1f */ + 0, /* 32 0x20 */ + 0, /* 33 0x21 */ + 0, /* 34 0x22 */ + 0, /* 35 0x23 */ + 0, /* 36 0x24 */ + 0, /* 37 0x25 */ + 0, /* 38 0x26 */ + 0, /* 39 0x27 */ + 0, /* 40 0x28 */ + 0, /* 41 0x29 */ + SDL_SCANCODE_LSHIFT, /* 42 0x2a */ + 0, /* 43 0x2b */ + 0, /* 44 0x2c */ + 0, /* 45 0x2d */ + 0, /* 46 0x2e */ + 0, /* 47 0x2f */ + 0, /* 48 0x30 */ + 0, /* 49 0x31 */ + 0, /* 50 0x32 */ + 0, /* 51 0x33 */ + 0, /* 52 0x34 */ + SDL_SCANCODE_KP_DIVIDE, /* 53 0x35 */ + SDL_SCANCODE_RSHIFT, /* 54 0x36 */ + SDL_SCANCODE_PRINTSCREEN, /* 55 0x37 */ + SDL_SCANCODE_RALT, /* 56 0x38 */ + 0, /* 57 0x39 */ + 0, /* 58 0x3a */ + 0, /* 59 0x3b */ + 0, /* 60 0x3c */ + 0, /* 61 0x3d */ + 0, /* 62 0x3e */ + 0, /* 63 0x3f */ + 0, /* 64 0x40 */ + 0, /* 65 0x41 */ + 0, /* 66 0x42 */ + 0, /* 67 0x43 */ + 0, /* 68 0x44 */ + 0, /* 69 0x45 */ + SDL_SCANCODE_PAUSE, /* 70 0x46 */ + SDL_SCANCODE_HOME, /* 71 0x47 */ + SDL_SCANCODE_UP, /* 72 0x48 */ + SDL_SCANCODE_PAGEUP, /* 73 0x49 */ + 0, /* 74 0x4a */ + SDL_SCANCODE_LEFT, /* 75 0x4b */ + 0, /* 76 0x4c */ + SDL_SCANCODE_RIGHT, /* 77 0x4d */ + 0, /* 78 0x4e */ + SDL_SCANCODE_END, /* 79 0x4f */ + SDL_SCANCODE_DOWN, /* 80 0x50 */ + SDL_SCANCODE_PAGEDOWN, /* 81 0x51 */ + SDL_SCANCODE_INSERT, /* 82 0x52 */ + SDL_SCANCODE_DELETE, /* 83 0x53 */ + 0, /* 84 0x54 */ + 0, /* 85 0x55 */ + 0, /* 86 0x56 */ + 0, /* 87 0x57 */ + 0, /* 88 0x58 */ + 0, /* 89 0x59 */ + 0, /* 90 0x5a */ + 0, /* 91 0x5b */ + 0, /* 92 0x5c */ + 0, /* 93 0x5d */ + 0, /* 94 0x5e */ + 0, /* 95 0x5f */ + 0, /* 96 0x60 */ + 0, /* 97 0x61 */ + 0, /* 98 0x62 */ + 0, /* 99 0x63 */ + 0, /* 100 0x64 */ + 0, /* 101 0x65 */ + 0, /* 102 0x66 */ + 0, /* 103 0x67 */ + 0, /* 104 0x68 */ + 0, /* 105 0x69 */ + 0, /* 106 0x6a */ + 0, /* 107 0x6b */ + 0, /* 108 0x6c */ + 0, /* 109 0x6d */ + 0, /* 110 0x6e */ + 0, /* 111 0x6f */ + 0, /* 112 0x70 */ + 0, /* 113 0x71 */ + 0, /* 114 0x72 */ + 0, /* 115 0x73 */ + 0, /* 116 0x74 */ + 0, /* 117 0x75 */ + 0, /* 118 0x76 */ + 0, /* 119 0x77 */ + 0, /* 120 0x78 */ + 0, /* 121 0x79 */ + 0, /* 122 0x7a */ + 0, /* 123 0x7b */ + 0, /* 124 0x7c */ + 0, /* 125 0x7d */ + 0, /* 126 0x7e */ + 0, /* 127 0x7f */ }; static volatile Uint8 scancode_buf[100]; -static volatile int scancode_count; +static volatile int scancode_count; static void DOS_KeyboardISR(void) @@ -222,7 +354,7 @@ DOS_ProcessScancode(Uint8 scancode) /* Generate SDL key event. */ if (extended_key) { - /* TODO: Handle extended keyboard scancodes. */ + SDL_SendKeyboardKey(state, extended_key_to_sdl_scancode[scancode]); } else { SDL_SendKeyboardKey(state, bios_to_sdl_scancode[scancode]); } From d9cf9066d9cb796b56d1d70c9c560c055a32149b Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 1 Sep 2025 01:53:34 +0100 Subject: [PATCH 45/51] dos: handle text input events Basic TEXTINPUT event firing that assumes US keyboard layout. --- src/core/dos/SDL_dos.c | 52 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/core/dos/SDL_dos.c b/src/core/dos/SDL_dos.c index ac23994e6eda9..52c685b7acc27 100644 --- a/src/core/dos/SDL_dos.c +++ b/src/core/dos/SDL_dos.c @@ -258,6 +258,19 @@ static const SDL_Scancode extended_key_to_sdl_scancode[128] = { 0, /* 127 0x7f */ }; +static const char shift_digits[16] = { + ')', /* 0 */ + '!', /* 1 */ + '@', /* 2 */ + '#', /* 3 */ + '$', /* 4 */ + '%', /* 5 */ + '^', /* 6 */ + '&', /* 7 */ + '*', /* 8 */ + '(', /* 9 */ +}; + static volatile Uint8 scancode_buf[100]; static volatile int scancode_count; @@ -338,29 +351,54 @@ DOS_InitKeyboard(void) } static void -DOS_ProcessScancode(Uint8 scancode) +DOS_ProcessScancode(Uint8 raw) { static SDL_bool extended_key = SDL_FALSE; - Uint8 state = scancode & 0x80 ? SDL_RELEASED : SDL_PRESSED; + Uint8 state = raw & 0x80 ? SDL_RELEASED : SDL_PRESSED; + SDL_Scancode scancode; /* Check if the code is an extended key prefix. */ - if (scancode == 0xE0) { + if (raw == 0xE0) { extended_key = SDL_TRUE; return; } /* Mask off state bit. */ - scancode &= 0x7F; + raw &= 0x7F; - /* Generate SDL key event. */ + /* Convert to SDL scancode. */ if (extended_key) { - SDL_SendKeyboardKey(state, extended_key_to_sdl_scancode[scancode]); + scancode = extended_key_to_sdl_scancode[raw]; } else { - SDL_SendKeyboardKey(state, bios_to_sdl_scancode[scancode]); + scancode = bios_to_sdl_scancode[raw]; } /* Reset extended key flag. */ extended_key = SDL_FALSE; + + /* Send a key event. Return if it wasn't posted. */ + if (SDL_SendKeyboardKey(state, scancode) == 0) return; + + /* If text input events are enabled, send one with basic US layout conversion. */ + if (state == SDL_PRESSED && SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) { + const SDL_Keymod modstate = SDL_GetModState(); + const SDL_Keycode keycode = SDL_GetKeyFromScancode(scancode); + if (((modstate & (KMOD_CTRL | KMOD_ALT)) == 0) && + keycode >= SDLK_SPACE && keycode <= SDLK_z) { + char buf[2]; + if ((modstate & KMOD_SHIFT)) { + if (keycode >= SDLK_0 && keycode <= SDLK_9) { + buf[0] = shift_digits[keycode - '0']; + } else if (keycode >= SDLK_a && keycode <= SDLK_z) { + buf[0] = keycode - ('a' - 'A'); + } + } else { + buf[0] = (char)keycode; + } + buf[1] = '\0'; + SDL_SendKeyboardText(buf); + } + } } static void From 027fb049acd6784d3044cd62a48653b494e3f9d8 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 1 Sep 2025 13:57:47 +0100 Subject: [PATCH 46/51] dos: modernize fullscreen-only handling --- src/video/svga/SDL_svga_video.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 14b553ab82682..4c5d90f05018c 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -80,6 +80,7 @@ SVGA_CreateDevice(void) } device->driverdata = devdata; + device->quirk_flags = VIDEO_DEVICE_QUIRK_FULLSCREEN_ONLY; /* Set the function pointers */ device->VideoInit = SVGA_VideoInit; @@ -264,10 +265,6 @@ SVGA_CreateWindow(_THIS, SDL_Window * window) /* Set framebuffer selector to sentinel value. */ windata->framebuffer_selector = -1; - /* Window is always fullscreen. */ - /* QUESTION: Is this appropriate, or should an error be returned instead? */ - window->flags |= SDL_WINDOW_FULLSCREEN; - return 0; } From b55cac0c06aa191dcc7a3e63ae6fe6656593026e Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 1 Sep 2025 17:10:10 +0100 Subject: [PATCH 47/51] dos: Implement palette support --- src/video/svga/SDL_svga_framebuffer.c | 19 +++++++- src/video/svga/SDL_svga_vbe.c | 66 ++++++++++++++++++++++++++- src/video/svga/SDL_svga_vbe.h | 3 +- src/video/svga/SDL_svga_video.h | 7 ++- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 1c945bb1db589..debaf86d8133d 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -85,10 +85,18 @@ SDL_SVGA_CreateFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** /* Populate color palette for indexed pixel formats. */ if (surface->format->palette) { SDL_Palette *palette = surface->format->palette; - if (SVGA_GetPaletteData(palette->colors, palette->ncolors)) { + if (SVGA_SetDACPaletteFormat(8)) { + /* Failed to set to 8-bit, assume 6-bit channel */ + windata->palette_dac_bits = 6; + } else { + windata->palette_dac_bits = 8; + } + if (SVGA_GetPaletteData(palette->colors, palette->ncolors, windata->palette_dac_bits)) { SDL_SVGA_DestroyFramebuffer(_this, window); return -1; } + windata->last_palette = palette; + windata->last_palette_version = palette->version; } /* Save data and set output parameters. */ @@ -143,6 +151,15 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i windata->framebuffer_page = !windata->framebuffer_page; framebuffer_offset = windata->framebuffer_page ? surface_size : 0; + if (surface->format->BitsPerPixel == 8 && + (surface->format->palette != windata->last_palette || + surface->format->palette->version != windata->last_palette_version)) { + /* Update the palette */ + SVGA_SetPaletteData(surface->format->palette->colors, surface->format->palette->ncolors, windata->palette_dac_bits); + windata->last_palette = surface->format->palette; + windata->last_palette_version = surface->format->palette->version; + } + /* Copy surface pixels to hidden framebuffer. */ movedata(_my_ds(), (uintptr_t)surface->pixels, windata->framebuffer_selector, framebuffer_offset, surface_size); diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 81b89a88a852c..5ee6c1517fe14 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -226,13 +226,18 @@ SVGA_SetDACPaletteFormat(int bits) __dpmi_int(0x10, &r); + if (r.h.al != 0x4F) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "VBE: Failed to set DAC palette format to %d bits, got al=%02x ah=%02x bh=%d; will assume 6-bit color channels", + (int)bits, (int)r.h.al, (int)r.h.ah, (int)r.h.bh); + } + RETURN_IF_VBE_CALL_FAILED(r); return r.h.bh; } int -SVGA_GetPaletteData(SDL_Color * colors, int num_colors) +SVGA_GetPaletteData(SDL_Color * colors, int num_colors, Uint8 palette_dac_bits) { int i; __dpmi_regs r; @@ -250,14 +255,71 @@ SVGA_GetPaletteData(SDL_Color * colors, int num_colors) dosmemget(__tb, num_colors * sizeof(*colors), colors); - /* Palette color components are stored in BGR order. */ + /* + Palette color components are stored in BGRA order, where + A is the alignment byte. + */ for (i = 0; i < num_colors; i++) { Uint8 temp = colors[i].r; colors[i].r = colors[i].b; colors[i].b = temp; colors[i].a = SDL_ALPHA_OPAQUE; + if (palette_dac_bits == 6) { + colors[i].r <<= 2; + colors[i].g <<= 2; + colors[i].b <<= 2; + } + } + + return 0; +} + +int SVGA_SetPaletteData(SDL_Color *colors, int num_colors, Uint8 palette_dac_bits) +{ + int i; + __dpmi_regs r; + Uint8 bgr_colors[256 * 4]; + + if (num_colors > 256) { + SDL_SetError("Too many palette colors"); + return -1; } + if (palette_dac_bits == 8) { + for (i = 0; i < num_colors; i++) { + bgr_colors[i * 4] = colors[i].b; + bgr_colors[i * 4 + 1] = colors[i].g; + bgr_colors[i * 4 + 2] = colors[i].r; + bgr_colors[i * 4 + 3] = 0; + } + } else { + for (i = 0; i < num_colors; i++) { + bgr_colors[i * 4] = colors[i].b >> 2; + bgr_colors[i * 4 + 1] = colors[i].g >> 2; + bgr_colors[i * 4 + 2] = colors[i].r >> 2; + bgr_colors[i * 4 + 3] = 0; + } + } + + r.x.ax = 0x4F09; + /* + Flag to set colors. + + Note that according to https://www.phatcode.net/res/221/files/vbe20.pdf 4.12 (page 37), + on some systems this flag should be 0x80 and that can be determined using the Capabilities + field, which we do not yet do. + */ + r.h.bl = 0x0; + r.x.cx = num_colors; + r.x.dx = 0; /* First color */ + r.x.es = __tb_segment; + r.x.di = __tb_offset; + + dosmemput(bgr_colors, num_colors * 4, __tb); + __dpmi_int(0x10, &r); + + RETURN_IF_VBE_CALL_FAILED(r); + return 0; } diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 9e16cac28414f..7e1199cda1fb3 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -160,7 +160,8 @@ extern int SVGA_GetState(void **state); extern int SVGA_SetState(const void *state, size_t size); extern int SVGA_SetDisplayStart(int x, int y); extern int SVGA_SetDACPaletteFormat(int bits); -extern int SVGA_GetPaletteData(SDL_Color * colors, int num_colors); +extern int SVGA_GetPaletteData(SDL_Color * colors, int num_colors, Uint8 palette_dac_bits); +extern int SVGA_SetPaletteData(SDL_Color *colors, int num_colors, Uint8 palette_dac_bits); extern SDL_PixelFormatEnum SVGA_GetPixelFormat(const VBEModeInfo * info); #endif /* SDL_svga_vbe_h_ */ diff --git a/src/video/svga/SDL_svga_video.h b/src/video/svga/SDL_svga_video.h index 0aeb2ac00838e..f326027e3f2ba 100644 --- a/src/video/svga/SDL_svga_video.h +++ b/src/video/svga/SDL_svga_video.h @@ -43,9 +43,12 @@ typedef struct typedef struct { - SDL_bool framebuffer_page; - int framebuffer_selector; + SDL_Palette *last_palette; + Uint32 last_palette_version; Uint32 framebuffer_linear_addr; + int framebuffer_selector; + SDL_bool framebuffer_page; + Uint8 palette_dac_bits; } SDL_WindowData; #endif /* SDL_svga_video_h_ */ From 6e5751fc0bc5572290a9c9714340177f39461a56 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 1 Sep 2025 18:23:35 +0100 Subject: [PATCH 48/51] dos: Only draw the cursor if it is enabled --- src/video/svga/SDL_svga_framebuffer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index debaf86d8133d..54803df2197dc 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -26,6 +26,7 @@ #include #include +#include "SDL_events.h" #include "SDL_mouse.h" #include "SDL_svga_video.h" #include "SDL_svga_framebuffer.h" @@ -165,7 +166,9 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i framebuffer_offset, surface_size); /* Copy cursor pixels to hidden framebuffer. */ - CopyCursorPixels(window); + if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) { + CopyCursorPixels(window); + } /* Display fresh page to screen. */ SVGA_SetDisplayStart(0, windata->framebuffer_page ? surface->h : 0); From 48628257fb3631d1347d6fa3f3c45ab94ae34a7b Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Mon, 1 Sep 2025 23:28:03 +0200 Subject: [PATCH 49/51] Change return to continue on SVGA mode info error This allows S3 trio video cards to work --- src/video/svga/SDL_svga_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index 4c5d90f05018c..d4fb46b4cdd61 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -159,7 +159,7 @@ SVGA_GetDisplayModes(_THIS, SDL_VideoDisplay * display) if (status) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "SVGA_GetVBEModeInfo failed: %d", status); - return; + continue; } /* Mode must support graphics with a linear framebuffer. */ From 476458815a5d01cfafccb1ed90a87d1765595550 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Tue, 2 Sep 2025 09:44:03 +0100 Subject: [PATCH 50/51] dos: Use protected-mode interface to set palette Calling out via real-mode bridge would kill performance when color cycling. Luckily, VBE 2.0 provides protected mode interface for some of the functions, and setting the palette is one of them. The asm code is based on Allegro 4.2 `vesa_set_palette_range`. Luckily, Allegro license is extremely permissive. --- src/video/svga/SDL_svga_framebuffer.c | 2 + src/video/svga/SDL_svga_vbe.c | 103 +++++++++++++++++++++----- src/video/svga/SDL_svga_vbe.h | 1 + src/video/svga/SDL_svga_video.c | 5 ++ 4 files changed, 92 insertions(+), 19 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 54803df2197dc..7e498ca889933 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -200,6 +200,8 @@ SDL_SVGA_DestroyFramebuffer(_THIS, SDL_Window * window) __dpmi_free_physical_address_mapping(&meminfo); windata->framebuffer_linear_addr = 0; } + + windata->last_palette = NULL; } #endif /* SDL_VIDEO_DRIVER_SVGA */ diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index 5ee6c1517fe14..cd378263a7597 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -18,6 +18,13 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + +/* + Some of the asm routines here are based on Allegro 4.2. + Huge thanks to Allegro 4 authors for publishing their code under + a permissive license! +*/ + #include "../../SDL_internal.h" #ifdef SDL_VIDEO_DRIVER_SVGA @@ -36,6 +43,56 @@ if ((regs).h.al != 0x4F) return SDL_MIN_SINT8; \ if ((regs).h.ah != 0) return -(regs).h.ah; +typedef struct VbeProtectedModeInterface +{ + unsigned short setWindow __attribute__((packed)); + unsigned short setDisplayStart __attribute__((packed)); + unsigned short setPalette __attribute__((packed)); + unsigned short IOPrivInfo __attribute__((packed)); +} VbeProtectedModeInterface; +VbeProtectedModeInterface *PM_Interface; + +/* Protected mode interface functions: */ +void *PM_SetWindow_Ptr; +void *PM_SetDisplayStart_Ptr; +void *PM_SetPalette_Ptr; + +int SVGA_InitProtectedModeInterface() +{ + __dpmi_regs r; + + if (PM_Interface != NULL) { + return 0; + } + + /* call the VESA function */ + r.x.ax = 0x4F0A; + r.x.bx = 0; + __dpmi_int(0x10, &r); + if (r.h.ah) + return -1; + + PM_Interface = SDL_malloc(r.x.cx); + dosmemget(r.x.es * 16 + r.x.di, r.x.cx, PM_Interface); + PM_SetWindow_Ptr = (void *)((char *)PM_Interface + PM_Interface->setWindow); + PM_SetDisplayStart_Ptr = (void *)((char *)PM_Interface + PM_Interface->setDisplayStart); + PM_SetPalette_Ptr = (void *)((char *)PM_Interface + PM_Interface->setPalette); + return 0; +} + +/* Returns a copy of the current %ds selector. */ +static int default_ds(void) +{ + short result; + + __asm__( + " movw %%ds, %0 " + + : "=r"(result)); + + return result; +} + int SVGA_GetVBEInfo(VBEInfo * info) { @@ -276,8 +333,14 @@ SVGA_GetPaletteData(SDL_Color * colors, int num_colors, Uint8 palette_dac_bits) int SVGA_SetPaletteData(SDL_Color *colors, int num_colors, Uint8 palette_dac_bits) { + /* + Flag to set colors. + + Set to 0x80 to wait for vblank before setting palette (e.g. for vsync). + */ + int mode = 0x80; + int seg; int i; - __dpmi_regs r; Uint8 bgr_colors[256 * 4]; if (num_colors > 256) { @@ -301,24 +364,26 @@ int SVGA_SetPaletteData(SDL_Color *colors, int num_colors, Uint8 palette_dac_bit } } - r.x.ax = 0x4F09; - /* - Flag to set colors. - - Note that according to https://www.phatcode.net/res/221/files/vbe20.pdf 4.12 (page 37), - on some systems this flag should be 0x80 and that can be determined using the Capabilities - field, which we do not yet do. - */ - r.h.bl = 0x0; - r.x.cx = num_colors; - r.x.dx = 0; /* First color */ - r.x.es = __tb_segment; - r.x.di = __tb_offset; - - dosmemput(bgr_colors, num_colors * 4, __tb); - __dpmi_int(0x10, &r); - - RETURN_IF_VBE_CALL_FAILED(r); + seg = default_ds(); + asm( + " pushl %%ebp ; " + " pushw %%ds ; " + " movw %w1, %%ds ; " /* set the IO segment */ + " call *%0 ; " /* call the VESA function */ + " popw %%ds ; " + " popl %%ebp ; " + + : /* no outputs */ + + : "S"(PM_SetPalette_Ptr), /* function pointer in esi */ + "a"(seg), /* IO segment in eax */ + "b"(mode), /* mode in ebx */ + "c"(num_colors), /* how many colors in ecx */ + "d"(0), /* first color in edx */ + "D"(bgr_colors) /* palette data pointer in edi */ + + : "memory", "%cc" /* clobbers flags */ + ); return 0; } diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 7e1199cda1fb3..5abd2e0af25d1 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -151,6 +151,7 @@ SDL_COMPILE_TIME_ASSERT(VBEModeInfo, sizeof(VBEModeInfo) == 256); #define VBE_MEM_MODEL_DIRECT 6 #define VBE_MEM_MODEL_YUV 7 +extern int SVGA_InitProtectedModeInterface(); extern int SVGA_GetVBEInfo(VBEInfo * info); extern VBEMode SVGA_GetVBEModeAtIndex(const VBEInfo * info, int index); extern int SVGA_GetVBEModeInfo(VBEMode mode, VBEModeInfo * info); diff --git a/src/video/svga/SDL_svga_video.c b/src/video/svga/SDL_svga_video.c index d4fb46b4cdd61..1c64b0d1fa34e 100644 --- a/src/video/svga/SDL_svga_video.c +++ b/src/video/svga/SDL_svga_video.c @@ -58,6 +58,11 @@ SVGA_CreateDevice(void) SDL_VideoDevice *device; SDL_DeviceData *devdata; + if (SVGA_InitProtectedModeInterface()) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "SVGA: Failed to get protected mode interface"); + return NULL; + } + devdata = (SDL_DeviceData *) SDL_calloc(1, sizeof(*devdata)); if (!devdata) { SDL_OutOfMemory(); From 20b47a62a12f0c7be4052fb5b32eb21d709d6f06 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Tue, 2 Sep 2025 10:18:48 +0100 Subject: [PATCH 51/51] dos: Use protected-mode interface to request flip --- src/video/svga/SDL_svga_framebuffer.c | 5 ++++- src/video/svga/SDL_svga_vbe.c | 31 +++++++++++++++++++-------- src/video/svga/SDL_svga_vbe.h | 2 +- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/video/svga/SDL_svga_framebuffer.c b/src/video/svga/SDL_svga_framebuffer.c index 7e498ca889933..62d2c84c33c32 100644 --- a/src/video/svga/SDL_svga_framebuffer.c +++ b/src/video/svga/SDL_svga_framebuffer.c @@ -171,7 +171,10 @@ SDL_SVGA_UpdateFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, i } /* Display fresh page to screen. */ - SVGA_SetDisplayStart(0, windata->framebuffer_page ? surface->h : 0); + SVGA_SetDisplayStart( + /*x=*/0, /*y=*/windata->framebuffer_page ? surface->h : 0, + /*bytes_per_pixel=*/surface->format->BytesPerPixel, + /*bytes_per_line=*/surface->pitch * surface->format->BytesPerPixel); return 0; } diff --git a/src/video/svga/SDL_svga_vbe.c b/src/video/svga/SDL_svga_vbe.c index cd378263a7597..b57e07c13968c 100644 --- a/src/video/svga/SDL_svga_vbe.c +++ b/src/video/svga/SDL_svga_vbe.c @@ -255,19 +255,32 @@ SVGA_SetState(const void *state, size_t size) return 0; } -int -SVGA_SetDisplayStart(int x, int y) +int SVGA_SetDisplayStart(int x, int y, int bytes_per_pixel, int bytes_per_line) { - __dpmi_regs r; + int seg; + long a; + seg = default_ds(); - r.x.ax = 0x4F07; - r.x.bx = 0x80; /* Set start and wait for vertical retrace. */ - r.x.cx = x; - r.x.dx = y; + a = ((x * bytes_per_pixel) + (y * bytes_per_line)) / 4; - __dpmi_int(0x10, &r); + asm( + " pushl %%ebp ; " + " pushw %%es ; " + " movw %w1, %%es ; " /* set the IO segment */ + " call *%0 ; " /* call the VESA function */ + " popw %%es ; " + " popl %%ebp ; " - RETURN_IF_VBE_CALL_FAILED(r); + : /* no outputs */ + + : "S"(PM_SetDisplayStart_Ptr), /* function pointer in esi */ + "a"(seg), /* IO segment in eax */ + "b"(0x80), /* mode in ebx (0x80 = wait for vertical retrace) */ + "c"(a & 0xFFFF), /* low word of address in ecx */ + "d"(a >> 16) /* high word of address in edx */ + + : "memory", "%edi", "%cc" /* clobbers edi and flags */ + ); return 0; } diff --git a/src/video/svga/SDL_svga_vbe.h b/src/video/svga/SDL_svga_vbe.h index 5abd2e0af25d1..c5daef29d059d 100644 --- a/src/video/svga/SDL_svga_vbe.h +++ b/src/video/svga/SDL_svga_vbe.h @@ -159,7 +159,7 @@ extern int SVGA_GetCurrentVBEMode(VBEMode * mode, VBEModeInfo * info); extern int SVGA_SetVBEMode(VBEMode mode); extern int SVGA_GetState(void **state); extern int SVGA_SetState(const void *state, size_t size); -extern int SVGA_SetDisplayStart(int x, int y); +extern int SVGA_SetDisplayStart(int x, int y, int bytes_per_pixel, int bytes_per_line); extern int SVGA_SetDACPaletteFormat(int bits); extern int SVGA_GetPaletteData(SDL_Color * colors, int num_colors, Uint8 palette_dac_bits); extern int SVGA_SetPaletteData(SDL_Color *colors, int num_colors, Uint8 palette_dac_bits);