OS/2 port!
This was mostly, if not entirely, written by "Doodle" and "Caetano":
doodle@scenergy.dfmk.hu
daniel@caetano.eng.br
--ryan.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README.OS2 Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,133 @@
+
+===========
+SDL on OS/2
+===========
+
+Last updated on Oct 02, 2005.
+
+
+1. How to compile?
+------------------
+
+To compile this, you'll need the followings installed:
+- The OS/2 Developer's Toolkit
+- The OpenWatcom compiler
+ (http://www.openwatcom.org)
+- The FSLib library
+ (ftp://ftp.netlabs.org/pub/SDL)
+
+Please edit the second, fourth and fifth lines of setvars.cmd file
+to set the folders where the toolkit, the OW compiler and the FSLib are.
+You won't need NASM yet (The Netwide Assembler), you can leave that line.
+Run setvars.cmd, and you should get a shell in which you can
+compile SDL.
+
+Check the "Watcom.mif" file. This is the file which is included by all the
+Watcom makefiles, so changes here will affect the whole build process.
+There is a line in there which determines if the resulting SDL.DLL will be
+a 'debug' or a 'release' build. The 'debug' version is full of printf()'s,
+so if something goes wrong, its output can help a lot for debugging.
+
+Then go to the 'src' folder, and run "wmake -f makefile.wat".
+This should create the SDL.DLL and the corresponding SDL.LIB file there.
+
+To test applications, it's a good idea to use the 'debug' build of SDL, and
+redirect the standard output and standard error output to files, to see what
+happens internally in SDL.
+(like: testsprite >stdout.txt 2>stderr.txt)
+
+To rebuild SDL, use the following commands in 'src' folder:
+wmake -f makefile.wat clean
+wmake -f makefile.wat
+
+
+
+2. How to compile the testapps?
+-------------------------------
+
+Once you have SDL.DLL compiled, navigate into the 'test' folder, copy in there
+the newly built SDL.DLL, and copy in there FSLib.DLL.
+
+Then run "wmake -f makefile.wat" in there to compile some of the testapps.
+
+
+
+3. What is missing?
+-------------------
+
+The following things are missing from this SDL implementation:
+- MMX, SSE and 3DNOW! optimized video blitters?
+- HW Video surfaces
+- OpenGL support
+
+
+
+4. Special Keys / Full-Screen support
+-------------------------------------
+
+There are two special hot-keys implemented:
+- Alt+Home switches between fullscreen and windowed mode
+- Alt+End simulates closing the window (can be used as a Panic key)
+Only the LEFT Alt key will work.
+
+
+
+5. Joysticks on SDL/2
+---------------------
+
+The Joystick detection only works for standard joysticks (2 buttons, 2 axes
+and the like). Therefore, if you use a non-standard joystick, you should
+specify its features in the SDL_OS2_JOYSTICK environment variable in a batch
+file or CONFIG.SYS, so SDL applications can provide full capability to your
+device. The syntax is:
+
+SET SDL_OS2_JOYSTICK=[JOYSTICK_NAME] [AXES] [BUTTONS] [HATS] [BALLS]
+
+So, it you have a Gravis GamePad with 4 axes, 2 buttons, 2 hats and 0 balls,
+the line should be:
+
+SET SDL_OS2_JOYSTICK=Gravis_GamePad 4 2 2 0
+
+If you want to add spaces in your joystick name, just surround it with
+quotes or double-quotes:
+
+SET SDL_OS2_JOYSTICK='Gravis GamePad' 4 2 2 0
+
+or
+
+SET SDL_OS2_JOYSTICK="Gravis GamePad" 4 2 2 0
+
+ Notive However that Balls and Hats are not supported under OS/2, and the
+value will be ignored... but it is wise to define these correctly because
+in the future those can be supported.
+ Also the number of buttons is limited to 2 when using two joysticks,
+4 when using one joystick with 4 axes, 6 when using a joystick with 3 axes
+and 8 when using a joystick with 2 axes. Notice however these are limitations
+of the Joystick Port hardware, not OS/2.
+
+
+
+6. Next steps...
+----------------
+
+Things to do:
+- Implement missing stuffs (look for 'TODO' string in source code!)
+- Finish video driver (the 'wincommon' can be a good example for missing
+ things like application icon and so on...)
+- Enable MMX/SSE/SSE2 acceleration functions
+- Rewrite CDROM support using DOS Ioctl for better support.
+
+
+
+7. Contacts
+-----------
+
+ You can contact the developers for bugs:
+
+ Area Developer email
+ General (Audio/Video/System) Doodle doodle@scenergy.dfmk.hu
+ CDROM and Joystick Caetano daniel@caetano.eng.br
+
+ Notice however that SDL/2 is 'in development' stage so ... if you want to help,
+please, be our guest and contact us!
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Watcom.mif Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,33 @@
+#=============================================================================
+# This file contains the common includes for the
+# Watcom makefiles to build SDL.DLL for OS/2
+#
+#
+#=============================================================================
+
+# Create debug build or not?
+#debug_build=defined
+
+# Special flags for building SDL
+SDLCFlags = -dBUILD_SDL -dCHECK_LEAKS
+
+#
+#==============================================================================
+#
+
+!ifdef debug_build
+debugflags = -d2 -dDEBUG_BUILD
+!else
+debugflags =
+!endif
+
+cflags = -zq $(debugflags) -bd -bm -bt=OS2 -5s -fpi -sg -otexan -wx -ei $(SDLCFlags) $(ExtraCFlags)
+
+.extensions:
+.extensions: .lib .dll .obj .c .asm
+
+.c.obj : .AUTODEPEND
+ wcc386 $[* $(cflags)
+
+.asm.obj : .AUTODEPEND
+ nasm -t -O2 -f obj -I$(%include) $[*.asm
--- a/include/SDL_byteorder.h Wed Nov 23 07:23:48 2005 +0000
+++ b/include/SDL_byteorder.h Wed Nov 23 07:29:56 2005 +0000
@@ -55,9 +55,8 @@
(defined(__arm__) || defined(__thumb__)) || \
(defined(__sh__) || defined(__sh64__)) || \
(defined(__mips__) && defined(__MIPSEL__)) || \
- defined(__SYMBIAN32__) || \
- defined(__x86_64__) || \
- defined(__LITTLE_ENDIAN__)
+ defined(__SYMBIAN32__) || defined(__x86_64__) || \
+ defined(__OS2__) || defined(__LITTLE_ENDIAN__)
#define SDL_BYTEORDER SDL_LIL_ENDIAN
#else
#define SDL_BYTEORDER SDL_BIG_ENDIAN
--- a/include/SDL_thread.h Wed Nov 23 07:23:48 2005 +0000
+++ b/include/SDL_thread.h Wed Nov 23 07:29:56 2005 +0000
@@ -50,7 +50,50 @@
typedef struct SDL_Thread SDL_Thread;
/* Create a thread */
+#ifdef __OS2__
+/*
+ We compile SDL into a DLL on OS/2. This means, that it's the DLL which
+ creates a new thread for the calling process with the SDL_CreateThread()
+ API. There is a problem with this, that only the RTL of the SDL.DLL will
+ be initialized for those threads, and not the RTL of the calling application!
+ To solve this, we make a little hack here.
+ We'll always use the caller's _beginthread() and _endthread() APIs to
+ start a new thread. This way, it it's the SDL.DLL which uses this API,
+ then the RTL of SDL.DLL will be used to create the new thread, and if it's
+ the application, then the RTL of the application will be used.
+ So, in short:
+ Always use the _beginthread() and _endthread() of the calling runtime library!
+*/
+
+#ifdef __WATCOMC__
+#include <process.h> // This has _beginthread() and _endthread() defined!
+#endif
+#ifdef __EMX__
+#include <stdlib.h> // This has _beginthread() and _endthread() defined, if -Zmt flag is used!
+#endif
+
+typedef Uint32 SDLCALL (*pfnSDL_CurrentBeginThread)(void (*pfnThreadFn)(void *), Uint32 uiStackSize, void *pParam);
+typedef void SDLCALL (*pfnSDL_CurrentEndThread)(void);
+
+extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread_Core(int (*fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
+
+// Disable warnings about unreferenced symbol!
+#pragma disable_message (202)
+static Uint32 SDLCALL SDL_CurrentBeginThread(void (*pfnThreadFn)(void *), Uint32 uiStackSize, void *pParam)
+{
+ return _beginthread(pfnThreadFn, NULL, uiStackSize, pParam);
+}
+
+static void SDLCALL SDL_CurrentEndThread(void)
+{
+ _endthread();
+}
+
+#define SDL_CreateThread(fn, data) SDL_CreateThread_Core(fn, data, SDL_CurrentBeginThread, SDL_CurrentEndThread)
+
+#else
extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data);
+#endif
/* Get the 32-bit thread identifier for the current thread */
extern DECLSPEC Uint32 SDLCALL SDL_ThreadID(void);
--- a/include/SDL_types.h Wed Nov 23 07:23:48 2005 +0000
+++ b/include/SDL_types.h Wed Nov 23 07:29:56 2005 +0000
@@ -57,7 +57,7 @@
#if !defined(__STRICT_ANSI__)
#ifdef __osf__ /* Tru64 */
#define SDL_HAS_64BIT_TYPE long
-#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DECC)
+#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DECC) || defined(__WATCOMC__)
#define SDL_HAS_64BIT_TYPE long long
#elif defined(_MSC_VER) /* VC++ */
#define SDL_HAS_64BIT_TYPE __int64
--- a/include/begin_code.h Wed Nov 23 07:23:48 2005 +0000
+++ b/include/begin_code.h Wed Nov 23 07:29:56 2005 +0000
@@ -56,8 +56,20 @@
# define DECLSPEC __declspec(dllexport)
# endif
# else
+# ifdef __OS2__
+# ifdef __WATCOMC__
+# ifdef BUILD_SDL
+# define DECLSPEC __declspec(dllexport)
+# else
# define DECLSPEC
# endif
+# else
+# define DECLSPEC
+# endif
+# else
+# define DECLSPEC
+# endif
+# endif
# endif
#endif
@@ -66,8 +78,14 @@
#if defined(WIN32) && !defined(__GNUC__)
#define SDLCALL __cdecl
#else
+#ifdef __OS2__
+/* But on OS/2, we use the _System calling convention */
+/* to be compatible with every compiler */
+#define SDLCALL _System
+#else
#define SDLCALL
#endif
+#endif
#endif /* SDLCALL */
/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/setvars.cmd Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,16 @@
+@ECHO OFF
+SET WATCOM=d:\watcom
+SET NASM=d:\nasm
+SET OS2TK=d:\os2tk45
+SET FSLIB=d:\watcom\projects\FSLib
+
+SET PATH=%WATCOM%\BINP;%WATCOM%\BINW;%os2tk%\bin;%NASM%;%PATH%
+SET INCLUDE=%WATCOM%\H;%WATCOM%\H\OS2
+SET FINCLUDE=%WATCOM%\SRC\FORTRAN
+SET EDPATH=%WATCOM%\EDDAT
+SET HELP=%WATCOM%\BINP\HELP;%HELP%
+SET BOOKSHELF=%WATCOM%\BINP\HELP;%BOOKSHELF%
+SET BEGINLIBPATH=%WATCOM%\BINP\DLL
+
+cmd
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,132 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+#
+#=============================================================================
+
+dllname=SDL
+
+audioobjs = audio\SDL_audio.obj audio\SDL_audiocvt.obj audio\SDL_audiomem.obj &
+ audio\SDL_mixer.obj audio\SDL_mixer_MMX_VC.obj audio\SDL_wave.obj &
+ audio\SDL_dart.obj
+cdromobjs = cdrom\SDL_cdrom.obj cdrom\SDL_syscdrom.obj
+cpuinfoobjs = cpuinfo\SDL_cpuinfo.obj
+endianobjs = endian\SDL_endian.obj
+eventsobjs = events\SDL_active.obj events\SDL_events.obj events\SDL_expose.obj &
+ events\SDL_keyboard.obj events\SDL_mouse.obj events\SDL_quit.obj &
+ events\SDL_resize.obj
+fileobjs = file\SDL_rwops.obj
+hermesobjs = hermes\mmx_main.obj hermes\mmxp2_32.obj hermes\x86_main.obj &
+ hermes\x86p_16.obj hermes\x86p_32.obj
+joystickobjs = joystick\SDL_joystick.obj joystick\SDL_sysjoystick.obj
+threadobjs = thread\SDL_thread.obj thread\SDL_sysmutex.obj &
+ thread\SDL_syssem.obj thread\SDL_systhread.obj &
+ thread\SDL_syscond.obj
+timerobjs = timer\SDL_timer.obj timer\SDL_systimer.obj
+videoobjs = video\SDL_blit.obj video\SDL_blit_0.obj video\SDL_blit_1.obj &
+ video\SDL_blit_A.obj video\SDL_blit_N.obj video\SDL_bmp.obj &
+ video\SDL_cursor.obj video\SDL_gamma.obj video\SDL_pixels.obj &
+ video\SDL_RLEaccel.obj video\SDL_stretch.obj video\SDL_surface.obj &
+ video\SDL_video.obj video\SDL_yuv.obj video\SDL_yuv_mmx.obj &
+ video\SDL_yuv_sw.obj video\SDL_os2fslib.obj
+
+object_files= SDL.obj SDL_error.obj SDL_fatal.obj SDL_getenv.obj &
+ SDL_loadso.obj $(audioobjs) $(cpuinfoobjs) $(endianobjs) &
+ $(eventsobjs) $(fileobjs) $(joystickobjs) &
+ $(threadobjs) $(timerobjs) $(videoobjs) $(cdromobjs)
+
+
+# Extra stuffs to pass to C compiler:
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\Watcom.mif
+
+.before
+ @set include=$(%os2tk)\h;$(%include);../include;./thread;./thread/os2;./video;./cdrom;./cdrom/os2;./joystick;./joystick/os2;
+
+all : check_subdir_objects $(dllname).dll $(dllname).lib
+
+$(dllname).dll : $(dllname).lnk $(object_files)
+ wlink @$(dllname)
+
+check_subdir_objects: .always .symbolic
+ @cd audio
+ @wmake -h -f Makefile.wat
+ @cd ..\cdrom
+ @wmake -h -f Makefile.wat
+ @cd ..\cpuinfo
+ @wmake -h -f Makefile.wat
+ @cd ..\endian
+ @wmake -h -f Makefile.wat
+ @cd ..\events
+ @wmake -h -f Makefile.wat
+ @cd ..\file
+ @wmake -h -f Makefile.wat
+ @cd ..\joystick
+ @wmake -h -f Makefile.wat
+ @cd ..\thread
+ @wmake -h -f Makefile.wat
+ @cd ..\timer
+ @wmake -h -f Makefile.wat
+ @cd ..\video
+ @wmake -h -f Makefile.wat
+ @cd ..
+
+$(dllname).lnk :
+ @echo Creating linker file ($(dllname).lnk)...
+ @echo $#============================================================================= >$^@
+ @echo $# This is a linker file to build SDL.DLL for OS/2 >>$^@
+ @echo $# >>$^@
+ @echo $# Generated automatically by Makefile.wat >>$^@
+ @echo $#============================================================================= >>$^@
+ @echo SYSTEM 386 LX DLL INITINSTANCE TERMINSTANCE >>$^@
+ @echo NAME $^& >>$^@
+ @for %i in ($(object_files)) do @echo FILE %i >>$^@
+ @echo LIBPATH %os2tk%\lib >>$^@
+ @echo LIBPATH %fslib% >>$^@
+ @echo LIB mmpm2.lib >>$^@
+ @echo LIB fslib.lib >>$^@
+ @echo OPTION QUIET >>$^@
+ @echo OPTION MAP=$^&.map >>$^@
+ @echo OPTION DESCRIPTION 'Simple DirectMedia Layer v1.2.7' >>$^@
+ @echo OPTION ELIMINATE >>$^@
+ @echo OPTION MANYAUTODATA >>$^@
+ @echo OPTION OSNAME='OS/2 and eComStation' >>$^@
+ @echo OPTION SHOWDEAD >>$^@
+ @echo Linker file created!
+
+$(dllname).lib : $(dllname).dll
+ implib $(dllname).lib $(dllname).dll
+
+clean : .SYMBOLIC
+ @if exist *.dll del *.dll
+ @if exist *.lib del *.lib
+ @if exist *.obj del *.obj
+ @if exist *.lnk del *.lnk
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
+ @cd audio
+ @wmake -h -f Makefile.wat clean
+ @cd ..\cdrom
+ @wmake -h -f Makefile.wat clean
+ @cd ..\cpuinfo
+ @wmake -h -f Makefile.wat clean
+ @cd ..\endian
+ @wmake -h -f Makefile.wat clean
+ @cd ..\events
+ @wmake -h -f Makefile.wat clean
+ @cd ..\file
+ @wmake -h -f Makefile.wat clean
+ @cd ..\joystick
+ @wmake -h -f Makefile.wat clean
+ @cd ..\thread
+ @wmake -h -f Makefile.wat clean
+ @cd ..\timer
+ @wmake -h -f Makefile.wat clean
+ @cd ..\video
+ @wmake -h -f Makefile.wat clean
+ @cd ..
--- a/src/SDL.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/SDL.c Wed Nov 23 07:29:56 2005 +0000
@@ -220,15 +220,25 @@
void SDL_Quit(void)
{
/* Quit all subsystems */
+#ifdef DEBUG_BUILD
+ printf("[SDL_Quit] : Enter! Calling QuitSubSystem()\n"); fflush(stdout);
+#endif
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
#ifdef CHECK_LEAKS
+#ifdef DEBUG_BUILD
+ printf("[SDL_Quit] : CHECK_LEAKS\n"); fflush(stdout);
+#endif
+
/* Print the number of surfaces not freed */
if ( surfaces_allocated != 0 ) {
fprintf(stderr, "SDL Warning: %d SDL surfaces extant\n",
surfaces_allocated);
}
#endif
+#ifdef DEBUG_BUILD
+ printf("[SDL_Quit] : SDL_UninstallParachute()\n"); fflush(stdout);
+#endif
/* Uninstall any parachute signal handlers */
SDL_UninstallParachute();
@@ -236,6 +246,10 @@
#if !defined(DISABLE_THREADS) && defined(ENABLE_PTH)
pth_kill();
#endif
+#ifdef DEBUG_BUILD
+ printf("[SDL_Quit] : Returning!\n"); fflush(stdout);
+#endif
+
}
/* Return the library version number */
@@ -244,6 +258,7 @@
return(&version);
}
+#ifndef __OS2__
#if defined(_WIN32_WCE) || (defined(__WATCOMC__) && defined(BUILD_DLL))
/* Need to include DllMain() on Windows CE and Watcom C for some reason.. */
#include <windows.h>
@@ -262,3 +277,75 @@
return TRUE;
}
#endif /* _WIN32_WCE and building DLL with Watcom C */
+#else
+// Building for OS/2
+#ifdef __WATCOMC__
+
+#define INCL_DOSERRORS
+#define INCL_DOSEXCEPTIONS
+#include <os2.h>
+
+// Exception handler to prevent the Audio thread hanging, making a zombie process!
+ULONG _System SDL_Main_ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
+ PEXCEPTIONREGISTRATIONRECORD pERegRec,
+ PCONTEXTRECORD pCtxRec,
+ PVOID p)
+{
+ if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
+ return XCPT_CONTINUE_SEARCH;
+ if (pERepRec->fHandlerFlags & EH_UNWINDING)
+ return XCPT_CONTINUE_SEARCH;
+ if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
+ return XCPT_CONTINUE_SEARCH;
+
+ // Do cleanup at every fatal exception!
+ if (((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION) &&
+ (pERepRec->ExceptionNum != XCPT_BREAKPOINT) &&
+ (pERepRec->ExceptionNum != XCPT_SINGLE_STEP)
+ )
+ {
+ if (SDL_initialized & SDL_INIT_AUDIO)
+ {
+ // This removes the zombie audio thread in case of emergency.
+#ifdef DEBUG_BUILD
+ printf("[SDL_Main_ExceptionHandler] : Calling SDL_CloseAudio()!\n");
+#endif
+ SDL_CloseAudio();
+ }
+ }
+ return (XCPT_CONTINUE_SEARCH);
+}
+
+
+EXCEPTIONREGISTRATIONRECORD SDL_Main_xcpthand = {0, SDL_Main_ExceptionHandler};
+
+// The main DLL entry for DLL Initialization and Uninitialization:
+unsigned _System LibMain(unsigned hmod, unsigned termination)
+{
+ if (termination)
+ {
+#ifdef DEBUG_BUILD
+// printf("[SDL DLL Unintialization] : Removing exception handler\n");
+#endif
+ DosUnsetExceptionHandler(&SDL_Main_xcpthand);
+ return 1;
+ } else
+ {
+#ifdef DEBUG_BUILD
+ // Make stdout and stderr unbuffered!
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+#endif
+ // Fire up exception handler
+#ifdef DEBUG_BUILD
+// printf("[SDL DLL Initialization] : Setting exception handler\n");
+#endif
+ // Set exception handler
+ DosSetExceptionHandler(&SDL_Main_xcpthand);
+
+ return 1;
+ }
+}
+
+#endif
+#endif
--- a/src/SDL_loadso.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/SDL_loadso.c Wed Nov 23 07:29:56 2005 +0000
@@ -44,6 +44,8 @@
# include "loadso/beos/SDL_loadso.c"
#elif defined(__MINT__) && defined(ENABLE_LDG)
# include "loadso/mint/SDL_loadso.c"
+#elif defined(__OS2__)
+# include "loadso/os2/SDL_loadso.c"
#else
# include "loadso/dummy/SDL_loadso.c"
#endif /* system type */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for DART (audio support)
+#=============================================================================
+
+object_files= SDL_audio.obj SDL_audiocvt.obj SDL_audiomem.obj SDL_mixer.obj SDL_mixer_MMX_VC.obj SDL_wave.obj SDL_dart.obj
+ExtraCFlags=-dUSE_ASM_MIXER_VC -dUSE_DOSSETPRIORITY
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;./dart
+
+all : $(object_files)
+
+SDL_dart.obj: .AUTODEPEND
+ wcc386 dart\SDL_dart.c $(cflags)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- a/src/audio/SDL_audio.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/audio/SDL_audio.c Wed Nov 23 07:29:56 2005 +0000
@@ -38,6 +38,12 @@
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
+#ifdef __OS2__
+// We'll need the DosSetPriority() API!
+#define INCL_DOSPROCESS
+#include <os2.h>
+#endif
+
/* Available audio drivers */
static AudioBootStrap *bootstrap[] = {
#ifdef OPENBSD_AUDIO_SUPPORT
@@ -108,6 +114,9 @@
#ifdef DRENDERER_SUPPORT
&DRENDERER_bootstrap,
#endif
+#ifdef __OS2__
+ &DART_bootstrap,
+#endif
NULL
};
SDL_AudioDevice *current_audio = NULL;
@@ -181,6 +190,16 @@
D(bug("Entering audio loop...\n"));
#endif
+#ifdef __OS2__
+ // Increase the priority of this thread to make sure that
+ // the audio will be continuous all the time!
+#ifdef USE_DOSSETPRIORITY
+#ifdef DEBUG_BUILD
+ printf("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID());
+#endif
+ DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
+#endif
+#endif
/* Loop, filling the audio buffers */
while ( audio->enabled ) {
@@ -249,6 +268,11 @@
D(bug("CloseAudio..Done, subtask exiting...\n"));
audio_configured = 0;
#endif
+#ifdef __OS2__
+#ifdef DEBUG_BUILD
+ printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
+#endif
+#endif
return(0);
}
--- a/src/audio/SDL_mixer_MMX_VC.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/audio/SDL_mixer_MMX_VC.c Wed Nov 23 07:29:56 2005 +0000
@@ -12,8 +12,10 @@
// Mixing for 16 bit signed buffers
////////////////////////////////////////////////
+#ifndef __WATCOMC__
#include <windows.h>
#include <stdio.h>
+#endif
void SDL_MixAudio_MMX_S16_VC(char* dst,char* src,unsigned int nSize,int volume)
{
@@ -41,7 +43,9 @@
psllq mm0, 16 //$16,%%mm0
por mm0, mm1 //%%mm1,%%mm0 // mm0 = vol|vol|vol|vol
+ #ifndef __WATCOMC__
align 16
+ #endif
mixloopS16:
movq mm1, [esi] //(%%esi),%%mm1\n" // mm1 = a|b|c|d
movq mm2, mm1 //%%mm1,%%mm2\n" // mm2 = a|b|c|d
@@ -121,7 +125,9 @@
cmp ebx, 0 //$0,%%ebx
je endS8
+ #ifndef __WATCOMC__
align 16
+ #endif
mixloopS8:
pxor mm2, mm2 //%%mm2,%%mm2 // mm2 = 0
movq mm1, [esi] //(%%esi),%%mm1 // mm1 = a|b|c|d|e|f|g|h
--- a/src/audio/SDL_sysaudio.h Wed Nov 23 07:23:48 2005 +0000
+++ b/src/audio/SDL_sysaudio.h Wed Nov 23 07:29:56 2005 +0000
@@ -172,6 +172,9 @@
#ifdef MMEAUDIO_SUPPORT
extern AudioBootStrap MMEAUDIO_bootstrap;
#endif
+#ifdef __OS2__
+extern AudioBootStrap DART_bootstrap;
+#endif
/* This is the current audio device */
extern SDL_AudioDevice *current_audio;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/dart/SDL_dart.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,436 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Allow access to a raw mixing buffer */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "SDL_types.h"
+#include "SDL_error.h"
+#include "SDL_timer.h"
+#include "SDL_audio.h"
+#include "SDL_audio_c.h"
+#include "SDL_dart.h"
+
+// Buffer states:
+#define BUFFER_EMPTY 0
+#define BUFFER_USED 1
+
+typedef struct _tMixBufferDesc {
+ int iBufferUsage; // BUFFER_EMPTY or BUFFER_USED
+ SDL_AudioDevice *pSDLAudioDevice;
+} tMixBufferDesc, *pMixBufferDesc;
+
+
+//---------------------------------------------------------------------
+// DARTEventFunc
+//
+// This function is called by DART, when an event occures, like end of
+// playback of a buffer, etc...
+//---------------------------------------------------------------------
+LONG APIENTRY DARTEventFunc(ULONG ulStatus,
+ PMCI_MIX_BUFFER pBuffer,
+ ULONG ulFlags)
+{
+ if (ulFlags && MIX_WRITE_COMPLETE)
+ { // Playback of buffer completed!
+
+ // Get pointer to buffer description
+ pMixBufferDesc pBufDesc;
+
+ if (pBuffer)
+ {
+ pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm;
+
+ if (pBufDesc)
+ {
+ SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice;
+ // Set the buffer to be empty
+ pBufDesc->iBufferUsage = BUFFER_EMPTY;
+ // And notify DART feeder thread that it will have to work a bit.
+ if (pSDLAudioDevice)
+ DosPostEventSem(pSDLAudioDevice->hidden->hevAudioBufferPlayed);
+ }
+ }
+ }
+ return TRUE;
+}
+
+
+int DART_OpenAudio(_THIS, SDL_AudioSpec *spec)
+{
+ MCI_AMP_OPEN_PARMS AmpOpenParms;
+ MCI_GENERIC_PARMS GenericParms;
+ int iDeviceOrd = 0; // Default device to be used
+ int bOpenShared = 1; // Try opening it shared
+ int iBits = 16; // Default is 16 bits signed
+ int iFreq = 44100; // Default is 44KHz
+ int iChannels = 2; // Default is 2 channels (Stereo)
+ int iNumBufs = 2; // Number of audio buffers: 2
+ int iBufSize;
+ int iOpenMode;
+ int iSilence;
+ int rc;
+
+ // First thing is to try to open a given DART device!
+ memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
+ // pszDeviceType should contain the device type in low word, and device ordinal in high word!
+ AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16));
+
+ iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID;
+ if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE;
+
+ rc = mciSendCommand( 0, MCI_OPEN,
+ iOpenMode,
+ (PVOID) &AmpOpenParms, 0);
+ if (rc!=MCIERR_SUCCESS) // No audio available??
+ return (-1);
+ // Save the device ID we got from DART!
+ // We will use this in the next calls!
+ iDeviceOrd = AmpOpenParms.usDeviceID;
+
+ // Determine the audio parameters from the AudioSpec
+ switch ( spec->format & 0xFF )
+ {
+ case 8:
+ /* Unsigned 8 bit audio data */
+ spec->format = AUDIO_U8;
+ iSilence = 0x80;
+ iBits = 8;
+ break;
+ case 16:
+ /* Signed 16 bit audio data */
+ spec->format = AUDIO_S16;
+ iSilence = 0x00;
+ iBits = 16;
+ break;
+ default:
+ // Close DART, and exit with error code!
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("Unsupported audio format");
+ return(-1);
+ }
+ iFreq = spec->freq;
+ iChannels = spec->channels;
+ /* Update the fragment size as size in bytes */
+ SDL_CalculateAudioSpec(spec);
+ iBufSize = spec->size;
+
+ // Now query this device if it supports the given freq/bits/channels!
+ memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS));
+ _this->hidden->MixSetupParms.ulBitsPerSample = iBits;
+ _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
+ _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq;
+ _this->hidden->MixSetupParms.ulChannels = iChannels;
+ _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY;
+ _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
+ _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc;
+ rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP,
+ MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
+ &(_this->hidden->MixSetupParms), 0);
+ if (rc!=MCIERR_SUCCESS)
+ { // The device cannot handle this format!
+ // Close DART, and exit with error code!
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("Audio device doesn't support requested audio format");
+ return(-1);
+ }
+ // The device can handle this format, so initialize!
+ rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
+ MCI_WAIT | MCI_MIXSETUP_INIT,
+ &(_this->hidden->MixSetupParms), 0);
+ if (rc!=MCIERR_SUCCESS)
+ { // The device could not be opened!
+ // Close DART, and exit with error code!
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("Audio device could not be set up");
+ return(-1);
+ }
+ // Ok, the device is initialized.
+ // Now we should allocate buffers. For this, we need a place where
+ // the buffer descriptors will be:
+ _this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs);
+ if (!(_this->hidden->pMixBuffers))
+ { // Not enough memory!
+ // Close DART, and exit with error code!
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("Not enough memory for audio buffer descriptors");
+ return(-1);
+ }
+ // Now that we have the place for buffer list, we can ask DART for the
+ // buffers!
+ _this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers
+ _this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size
+ _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list
+ // Allocate buffers!
+ rc = mciSendCommand(iDeviceOrd, MCI_BUFFER,
+ MCI_WAIT | MCI_ALLOCATE_MEMORY,
+ &(_this->hidden->BufferParms), 0);
+ if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0))
+ { // Could not allocate memory!
+ // Close DART, and exit with error code!
+ free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("DART could not allocate buffers");
+ return(-1);
+ }
+ // Ok, we have all the buffers allocated, let's mark them!
+ {
+ int i;
+ for (i=0; i<iNumBufs; i++)
+ {
+ pMixBufferDesc pBufferDesc = (pMixBufferDesc) malloc(sizeof(tMixBufferDesc));;
+ // Check if this buffer was really allocated by DART
+ if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc))
+ { // Wrong buffer!
+ // Close DART, and exit with error code!
+ // Free buffer descriptions
+ { int j;
+ for (j=0; j<i; j++) free((void *)(_this->hidden->pMixBuffers[j].ulUserParm));
+ }
+ // and cleanup
+ mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
+ free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("Error at internal buffer check");
+ return(-1);
+ }
+ pBufferDesc->iBufferUsage = BUFFER_EMPTY;
+ pBufferDesc->pSDLAudioDevice = _this;
+
+ _this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize;
+ _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer
+ _this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of
+ // audio data, but as we will continously send
+ // audio data, there will be no end.:)
+ memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize);
+ }
+ }
+ _this->hidden->iNextFreeBuffer = 0;
+ _this->hidden->iLastPlayedBuf = -1;
+ // Create event semaphore
+ if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR)
+ {
+ // Could not create event semaphore!
+ {
+ int i;
+ for (i=0; i<iNumBufs; i++) free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
+ }
+ mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
+ free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
+ mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+ SDL_SetError("Could not create event semaphore");
+ return(-1);
+ }
+
+ // Store the new settings in global variables
+ _this->hidden->iCurrDeviceOrd = iDeviceOrd;
+ _this->hidden->iCurrFreq = iFreq;
+ _this->hidden->iCurrBits = iBits;
+ _this->hidden->iCurrChannels = iChannels;
+ _this->hidden->iCurrNumBufs = iNumBufs;
+ _this->hidden->iCurrBufSize = iBufSize;
+
+ return (0);
+}
+
+
+
+void DART_ThreadInit(_THIS)
+{
+ return;
+}
+
+/* This function waits until it is possible to write a full sound buffer */
+void DART_WaitAudio(_THIS)
+{
+ int i;
+ pMixBufferDesc pBufDesc;
+ ULONG ulPostCount;
+
+ DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
+ // If there is already an empty buffer, then return now!
+ for (i=0; i<_this->hidden->iCurrNumBufs; i++)
+ {
+ pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm;
+ if (pBufDesc->iBufferUsage == BUFFER_EMPTY)
+ return;
+ }
+ // If there is no empty buffer, wait for one to be empty!
+ DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important!
+ return;
+}
+
+void DART_PlayAudio(_THIS)
+{
+ int iFreeBuf = _this->hidden->iNextFreeBuffer;
+ pMixBufferDesc pBufDesc;
+
+ pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm;
+ pBufDesc->iBufferUsage = BUFFER_USED;
+ // Send it to DART to be queued
+ _this->hidden->MixSetupParms.pmixWrite(_this->hidden->MixSetupParms.ulMixHandle,
+ &(_this->hidden->pMixBuffers[iFreeBuf]), 1);
+
+ _this->hidden->iLastPlayedBuf = iFreeBuf;
+ iFreeBuf = (iFreeBuf+1) % _this->hidden->iCurrNumBufs;
+ _this->hidden->iNextFreeBuffer = iFreeBuf;
+}
+
+Uint8 *DART_GetAudioBuf(_THIS)
+{
+ int iFreeBuf;
+ Uint8 *pResult;
+ pMixBufferDesc pBufDesc;
+
+ if (_this)
+ {
+ if (_this->hidden)
+ {
+ iFreeBuf = _this->hidden->iNextFreeBuffer;
+ pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm;
+
+ if (pBufDesc)
+ {
+ if (pBufDesc->iBufferUsage == BUFFER_EMPTY)
+ {
+ pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer;
+ return pResult;
+ }
+ } else
+ printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", pBufDesc);
+ } else
+ printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", _this->hidden);
+ } else
+ printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this);
+ return NULL;
+}
+
+void DART_WaitDone(_THIS)
+{
+ pMixBufferDesc pBufDesc;
+ ULONG ulPostCount;
+ APIRET rc;
+
+ pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm;
+ rc = NO_ERROR;
+ while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc==NO_ERROR))
+ {
+ DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
+ rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important!
+ }
+}
+
+void DART_CloseAudio(_THIS)
+{
+ MCI_GENERIC_PARMS GenericParms;
+ int rc;
+
+ // Stop DART playback
+ rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, &GenericParms, 0);
+ if (rc!=MCIERR_SUCCESS)
+ {
+#ifdef SFX_DEBUG_BUILD
+ printf("Could not stop DART playback!\n");
+ fflush(stdout);
+#endif
+ }
+
+ // Close event semaphore
+ DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
+
+ // Free memory of buffer descriptions
+ {
+ int i;
+ for (i=0; i<_this->hidden->iCurrNumBufs; i++) free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
+ }
+
+ // Deallocate buffers
+ rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
+
+ // Free bufferlist
+ free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
+
+ // Close dart
+ rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, &(GenericParms), 0);
+}
+
+/* Audio driver bootstrap functions */
+
+int Audio_Available(void)
+{
+ return(1);
+}
+
+void Audio_DeleteDevice(SDL_AudioDevice *device)
+{
+ free(device->hidden);
+ free(device);
+}
+
+SDL_AudioDevice *Audio_CreateDevice(int devindex)
+{
+ SDL_AudioDevice *this;
+
+ /* Initialize all variables that we clean on shutdown */
+ this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
+ if ( this )
+ {
+ memset(this, 0, (sizeof *this));
+ this->hidden = (struct SDL_PrivateAudioData *)
+ malloc((sizeof *this->hidden));
+ }
+ if ( (this == NULL) || (this->hidden == NULL) )
+ {
+ SDL_OutOfMemory();
+ if ( this )
+ free(this);
+ return(0);
+ }
+ memset(this->hidden, 0, (sizeof *this->hidden));
+
+ /* Set the function pointers */
+ this->OpenAudio = DART_OpenAudio;
+ this->ThreadInit = DART_ThreadInit;
+ this->WaitAudio = DART_WaitAudio;
+ this->PlayAudio = DART_PlayAudio;
+ this->GetAudioBuf = DART_GetAudioBuf;
+ this->WaitDone = DART_WaitDone;
+ this->CloseAudio = DART_CloseAudio;
+
+ this->free = Audio_DeleteDevice;
+
+ return this;
+}
+
+AudioBootStrap DART_bootstrap = {
+ "dart", "OS/2 Direct Audio RouTines (DART)",
+ Audio_Available, Audio_CreateDevice
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/dart/SDL_dart.h Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,67 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#ifndef _SDL_lowaudio_h
+#define _SDL_lowaudio_h
+
+#include "SDL_sysaudio.h"
+
+#define INCL_TYPES
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSRESOURCES
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+
+#define INCL_OS2MM
+#define INCL_MMIOOS2
+#define INCL_MCIOS2
+#include <os2.h>
+#include <os2me.h> // DART stuff and MMIO stuff
+
+/* Hidden "this" pointer for the audio functions */
+#define _THIS SDL_AudioDevice *_this
+
+/* The DirectSound objects */
+struct SDL_PrivateAudioData
+{
+ int iCurrDeviceOrd;
+ int iCurrFreq;
+ int iCurrBits;
+ int iCurrChannels;
+ int iCurrNumBufs;
+ int iCurrBufSize;
+
+ int iLastPlayedBuf;
+ int iNextFreeBuffer;
+
+ MCI_BUFFER_PARMS BufferParms; // Sound buffer parameters
+ MCI_MIX_BUFFER *pMixBuffers; // Sound buffers
+ MCI_MIXSETUP_PARMS MixSetupParms; // Mixer setup parameters
+ HEV hevAudioBufferPlayed; // Event semaphore to indicate that an audio buffer has been played by DART
+};
+
+#endif /* _SDL_lowaudio_h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,30 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for OS/2 System CDROM support
+#=============================================================================
+
+object_files=SDL_syscdrom.obj SDL_cdrom.obj
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
+
+all : $(object_files)
+
+SDL_syscdrom.obj : .AUTODEPEND
+ wcc386 os2\SDL_syscdrom.c $(cflags)
+
+SDL_cdrom.obj : .AUTODEPEND
+ wcc386 SDL_cdrom.c $(cflags)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/os2/SDL_syscdrom.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,399 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2004 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Functions for system-level CD-ROM audio control */
+
+#define INCL_MCIOS2
+#include <os2.h>
+#include <os2me.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "SDL_error.h"
+#include "SDL_cdrom.h"
+#include "SDL_syscdrom.h"
+
+/* Size of MCI result buffer (in bytes) */
+#define MCI_CMDRETBUFSIZE 128
+
+/* The maximum number of CD-ROM drives we'll detect */
+#define MAX_DRIVES 16
+
+/* A list of available CD-ROM drives */
+static char *SDL_cdlist[MAX_DRIVES];
+//static dev_t SDL_cdmode[MAX_DRIVES];
+
+/* The system-dependent CD control functions */
+static const char *SDL_SYS_CDName(int drive);
+static int SDL_SYS_CDOpen(int drive);
+static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
+static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
+static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
+static int SDL_SYS_CDPause(SDL_CD *cdrom);
+static int SDL_SYS_CDResume(SDL_CD *cdrom);
+static int SDL_SYS_CDStop(SDL_CD *cdrom);
+static int SDL_SYS_CDEject(SDL_CD *cdrom);
+static void SDL_SYS_CDClose(SDL_CD *cdrom);
+
+/* MCI Timing Functions */
+#define MCI_MMTIMEPERSECOND 3000
+#define FRAMESFROMMM(mmtime) (((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND)
+
+
+/* Ready for MCI CDAudio Devices */
+int SDL_SYS_CDInit(void)
+{
+int i; /* generig counter */
+MCI_SYSINFO_PARMS msp; /* Structure to MCI SysInfo parameters */
+CHAR SysInfoRet[MCI_CMDRETBUFSIZE]; /* Buffer for MCI Command result */
+
+/* Fill in our driver capabilities */
+SDL_CDcaps.Name = SDL_SYS_CDName;
+SDL_CDcaps.Open = SDL_SYS_CDOpen;
+SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
+SDL_CDcaps.Status = SDL_SYS_CDStatus;
+SDL_CDcaps.Play = SDL_SYS_CDPlay;
+SDL_CDcaps.Pause = SDL_SYS_CDPause;
+SDL_CDcaps.Resume = SDL_SYS_CDResume;
+SDL_CDcaps.Stop = SDL_SYS_CDStop;
+SDL_CDcaps.Eject = SDL_SYS_CDEject;
+SDL_CDcaps.Close = SDL_SYS_CDClose;
+
+/* Get the number of CD ROMs in the System */
+/* Clean SysInfo structure */
+memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));
+/* Prepare structure to Ask Numer of Audio CDs */
+msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
+msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
+msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
+if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
+SDL_numcds = atoi(SysInfoRet);
+if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */
+
+/* Get and Add their system name to the SDL_cdlist */
+msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
+msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
+msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
+for (i=0; i<SDL_numcds; i++)
+ {
+ msp.ulNumber = i+1;
+ mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0);
+ SDL_cdlist[i] = (char *)malloc(strlen(SysInfoRet)+1);
+ if ( SDL_cdlist[i] == NULL )
+ {
+ SDL_OutOfMemory();
+ return(-1);
+ }
+ strcpy(SDL_cdlist[i], SysInfoRet);
+ }
+return(0);
+}
+
+/* Return CDAudio System Dependent Device Name - Ready for MCI*/
+static const char *SDL_SYS_CDName(int drive)
+{
+return(SDL_cdlist[drive]);
+}
+
+/* Open CDAudio Device - Ready for MCI */
+static int SDL_SYS_CDOpen(int drive)
+{
+MCI_OPEN_PARMS mop;
+MCI_SET_PARMS msp;
+MCI_GENERIC_PARMS mgp;
+
+/* Open the device */
+mop.hwndCallback = (HWND)NULL; // None
+mop.usDeviceID = (USHORT)NULL; // Will be returned.
+mop.pszDeviceType = (PSZ)SDL_cdlist[drive]; // CDAudio Device
+if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
+/* Set time format */
+msp.hwndCallback = (HWND)NULL; // None
+msp.ulTimeFormat = MCI_FORMAT_MSF; // Minute : Second : Frame structure
+msp.ulSpeedFormat = (ULONG)NULL; // No change
+msp.ulAudio = (ULONG)NULL; // No Channel
+msp.ulLevel = (ULONG)NULL; // No Volume
+msp.ulOver = (ULONG)NULL; // No Delay
+msp.ulItem = (ULONG)NULL; // No item
+msp.ulValue = (ULONG)NULL; // No value for item flag
+if (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID);
+/* Error setting time format? - Close opened device */
+mgp.hwndCallback = (HWND)NULL; // None
+mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);
+return(CD_ERROR);
+}
+
+/* Get CD Table Of Contents - Ready for MCI */
+static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
+{
+MCI_TOC_PARMS mtp;
+MCI_STATUS_PARMS msp;
+MCI_TOC_REC * mtr;
+INT i;
+
+/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */
+if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;
+
+/* Get Number of Tracks */
+msp.hwndCallback = (HWND)NULL; /* None */
+msp.ulReturn = (ULONG)NULL; /* We want this information */
+msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;
+msp.ulValue = (ULONG)NULL; /* No additional information */
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
+cdrom->numtracks = msp.ulReturn;
+if ( cdrom->numtracks > SDL_MAX_TRACKS )
+ {
+ cdrom->numtracks = SDL_MAX_TRACKS;
+ }
+/* Alocate space for TOC data */
+mtr = (MCI_TOC_REC *)malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));
+if ( mtr == NULL )
+ {
+ SDL_OutOfMemory();
+ return(-1);
+ }
+/* Get TOC from CD */
+mtp.pBuf = mtr;
+mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS)
+ {
+ SDL_OutOfMemory();
+ free(mtr);
+ return(CD_ERROR);
+ }
+/* Fill SDL Tracks Structure */
+for (i=0; i<cdrom->numtracks; i++)
+ {
+ /* Set Track ID */
+ cdrom->track[i].id = (mtr+i)->TrackNum;
+ /* Set Track Type */
+ msp.hwndCallback = (HWND)NULL; /* None */
+ msp.ulReturn = (ULONG)NULL; /* We want this information */
+ msp.ulItem = MCI_CD_STATUS_TRACK_TYPE;
+ msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */
+ if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS)
+ {
+ free(mtr);
+ return (CD_ERROR);
+ }
+ if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK;
+ else cdrom->track[i].type = SDL_DATA_TRACK;
+ /* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */
+ cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr);
+ /* Set Track Offset */
+ cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr);
+ }
+free(mtr);
+return(0);
+}
+
+
+/* Get CD-ROM status - Ready for MCI */
+static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
+{
+CDstatus status;
+MCI_STATUS_PARMS msp;
+
+/* Get Status from MCI */
+msp.hwndCallback = (HWND)NULL; /* None */
+msp.ulReturn = (ULONG)NULL; /* We want this information */
+msp.ulItem = MCI_STATUS_MODE;
+msp.ulValue = (ULONG)NULL; /* No additional information */
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;
+else
+ {
+ switch(msp.ulReturn)
+ {
+ case MCI_MODE_NOT_READY:
+ status = CD_TRAYEMPTY;
+ break;
+ case MCI_MODE_PAUSE:
+ status = CD_PAUSED;
+ break;
+ case MCI_MODE_PLAY:
+ status = CD_PLAYING;
+ break;
+ case MCI_MODE_STOP:
+ status = CD_STOPPED;
+ break;
+ /* These cases should not occour */
+ case MCI_MODE_RECORD:
+ case MCI_MODE_SEEK:
+ default:
+ status = CD_ERROR;
+ break;
+ }
+ }
+
+/* Determine position */
+if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */
+ {
+ if ((status == CD_PLAYING) || (status == CD_PAUSED))
+ {
+ /* Get Position */
+ msp.hwndCallback = (HWND)NULL; /* None */
+ msp.ulReturn = (ULONG)NULL; /* We want this information */
+ msp.ulItem = MCI_STATUS_POSITION;
+ msp.ulValue = (ULONG)NULL; /* No additiona info */
+ if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR);
+ /* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */
+ *position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn));
+ }
+ else *position = 0;
+ }
+return(status);
+}
+
+/* Start play - Ready for MCI */
+static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
+{
+MCI_GENERIC_PARMS mgp;
+MCI_STATUS_PARMS msp;
+MCI_PLAY_PARMS mpp;
+ULONG min,sec,frm;
+
+/* Start MSF */
+FRAMES_TO_MSF(start, &min, &sec, &frm);
+MSF_MINUTE(mpp.ulFrom) = min;
+MSF_SECOND(mpp.ulFrom) = sec;
+MSF_FRAME(mpp.ulFrom) = frm;
+/* End MSF */
+FRAMES_TO_MSF(start+length, &min, &sec, &frm);
+MSF_MINUTE(mpp.ulTo) = min;
+MSF_SECOND(mpp.ulTo) = sec;
+MSF_FRAME(mpp.ulTo) = frm;
+#ifdef DEBUG_CDROM
+ fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
+ playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
+ playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
+#endif
+/* Verifies if it is paused first... and if it is, unpause before stopping it. */
+msp.hwndCallback = (HWND)NULL; /* None */
+msp.ulReturn = (ULONG)NULL; /* We want this information */
+msp.ulItem = MCI_STATUS_MODE;
+msp.ulValue = (ULONG)NULL; /* No additional information */
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
+ {
+ if (msp.ulReturn == MCI_MODE_PAUSE)
+ {
+ mgp.hwndCallback = (HWND)NULL; // None
+ mciSendCommand(cdrom->id,MCI_RESUME,NULL,&mgp, 0);
+ }
+ }
+/* Now play it. */
+mpp.hwndCallback = (HWND)NULL; // We do not want the info. temp
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;
+return (CD_ERROR);
+}
+
+/* Pause play - Ready for MCI */
+static int SDL_SYS_CDPause(SDL_CD *cdrom)
+{
+MCI_GENERIC_PARMS mgp;
+
+mgp.hwndCallback = (HWND)NULL; // None
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
+return(CD_ERROR);
+}
+
+/* Resume play - Ready for MCI */
+static int SDL_SYS_CDResume(SDL_CD *cdrom)
+{
+MCI_GENERIC_PARMS mgp;
+
+mgp.hwndCallback = (HWND)NULL; // None
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
+return(CD_ERROR);
+}
+
+/* Stop play - Ready for MCI */
+static int SDL_SYS_CDStop(SDL_CD *cdrom)
+{
+MCI_GENERIC_PARMS mgp;
+MCI_STATUS_PARMS msp;
+
+/* Verifies if it is paused first... and if it is, unpause before stopping it. */
+msp.hwndCallback = (HWND)NULL; /* None */
+msp.ulReturn = (ULONG)NULL; /* We want this information */
+msp.ulItem = MCI_STATUS_MODE;
+msp.ulValue = (ULONG)NULL; /* No additional information */
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
+ {
+ if (msp.ulReturn == MCI_MODE_PAUSE)
+ {
+ mgp.hwndCallback = (HWND)NULL; // None
+ mciSendCommand(cdrom->id,MCI_RESUME,NULL,&mgp, 0);
+ }
+ }
+/* Now stops the media */
+mgp.hwndCallback = (HWND)NULL; // None
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
+return(CD_ERROR);
+}
+
+/* Eject the CD-ROM - Ready for MCI */
+static int SDL_SYS_CDEject(SDL_CD *cdrom)
+{
+MCI_SET_PARMS msp;
+
+msp.hwndCallback = (HWND)NULL; // None
+msp.ulTimeFormat = (ULONG)NULL; // No change
+msp.ulSpeedFormat = (ULONG)NULL; // No change
+msp.ulAudio = (ULONG)NULL; // No Channel
+msp.ulLevel = (ULONG)NULL; // No Volume
+msp.ulOver = (ULONG)NULL; // No Delay
+msp.ulItem = (ULONG)NULL; // No item
+msp.ulValue = (ULONG)NULL; // No value for item flag
+if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;
+return(CD_ERROR);
+}
+
+/* Close the CD-ROM handle - Ready for MCI */
+static void SDL_SYS_CDClose(SDL_CD *cdrom)
+{
+MCI_GENERIC_PARMS mgp;
+
+mgp.hwndCallback = (HWND)NULL; // None
+mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);
+}
+
+/* Finalize CDROM Subsystem - Ready for MCI */
+void SDL_SYS_CDQuit(void)
+{
+int i;
+
+if ( SDL_numcds > 0 )
+ {
+ for ( i=0; i<SDL_numcds; ++i )
+ {
+ free(SDL_cdlist[i]);
+ }
+ SDL_numcds = 0;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for cpuinfo
+#=============================================================================
+
+object_files=SDL_cpuinfo.obj
+
+# We have to define the following so the assembly parts can be
+# compiled by Watcom, too!
+ExtraCFlags=-d_MSC_VER
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include
+
+all : $(object_files)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/endian/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,24 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for endianness
+#=============================================================================
+
+object_files=SDL_endian.obj
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include
+
+all : $(object_files)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/events/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,24 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for events
+#=============================================================================
+
+object_files=SDL_active.obj SDL_events.obj SDL_expose.obj SDL_keyboard.obj SDL_mouse.obj SDL_quit.obj SDL_resize.obj
+ExtraCFlags=-dUSE_DOSSETPRIORITY
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;../timer;../joystick;../video;
+
+all : $(object_files)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- a/src/events/SDL_events.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/events/SDL_events.c Wed Nov 23 07:29:56 2005 +0000
@@ -89,9 +89,28 @@
}
}
+#ifdef __OS2__
+/*
+ * We'll increase the priority of GobbleEvents thread, so it will process
+ * events in time for sure! For this, we need the DosSetPriority() API
+ * from the os2.h include file.
+ */
+#define INCL_DOSPROCESS
+#include <os2.h>
+#include <time.h>
+#endif
+
static int SDL_GobbleEvents(void *unused)
{
event_thread = SDL_ThreadID();
+
+#ifdef __OS2__
+#ifdef USE_DOSSETPRIORITY
+ /* Increase thread priority, so it will process events in time for sure! */
+ DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +16, 0);
+#endif
+#endif
+
while ( SDL_EventQ.active ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
--- a/src/events/SDL_resize.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/events/SDL_resize.c Wed Nov 23 07:29:56 2005 +0000
@@ -45,8 +45,11 @@
SDL_Event events[32];
/* See if this event would change the video surface */
- if ( !w || !h ||
- ((last_resize.w == w) && (last_resize.h == h)) ) {
+ if ( !w || !h
+#ifndef __OS2__
+ || ((last_resize.w == w) && (last_resize.h == h))
+#endif
+ ) {
return(0);
}
last_resize.w = w;
--- a/src/events/SDL_sysevents.h Wed Nov 23 07:23:48 2005 +0000
+++ b/src/events/SDL_sysevents.h Wed Nov 23 07:29:56 2005 +0000
@@ -44,3 +44,7 @@
#ifdef macintosh /* MacOS 7/8 don't support preemptive multi-tasking */
#define CANT_THREAD_EVENTS
#endif
+
+#ifdef __OS2__ /* The OS/2 event loop runs in a separate thread */
+#define MUST_THREAD_EVENTS
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/file/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,24 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for file
+#=============================================================================
+
+object_files=SDL_rwops.obj
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include
+
+all : $(object_files)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for joystick (using the dummy joystick driver)
+#=============================================================================
+
+object_files=SDL_joystick.obj SDL_sysjoystick.obj
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;./os2;../;../events;
+
+all : $(object_files)
+
+SDL_sysjoystick.obj: .AUTODEPEND
+ wcc386 os2\SDL_sysjoystick.c $(cflags)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/os2/SDL_sysjoystick.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,669 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2004 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* OS/2 Joystick driver, contributed by Daniel Caetano */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mem.h>
+
+#define INCL_DOSDEVICES
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSMEMMGR
+#include <os2.h>
+#include "joyos2.h"
+
+#include "SDL_error.h"
+#include "SDL_joystick.h"
+#include "SDL_sysjoystick.h"
+#include "SDL_joystick_c.h"
+
+HFILE hJoyPort = NULL; /* Joystick GAME$ Port Address */
+#define MAX_JOYSTICKS 2 /* Maximum of two joysticks */
+#define MAX_AXES 4 /* each joystick can have up to 4 axes */
+#define MAX_BUTTONS 8 /* 8 buttons */
+#define MAX_HATS 0 /* 0 hats - OS/2 doesn't support it */
+#define MAX_BALLS 0 /* and 0 balls - OS/2 doesn't support it */
+#define AXIS_MIN -32768 /* minimum value for axes coordinate */
+#define AXIS_MAX 32767 /* maximum value for axes coordinate */
+#define MAX_JOYNAME 128 /* Joystick name may have 128 characters */
+/* limit axes to 256 possible positions to filter out noise */
+#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256)
+/* Calc Button Flag for buttons A to D */
+#define JOY_BUTTON_FLAG(n) (1<<n)
+
+/* Joystick data... hold information about detected devices */
+struct _SYS_JoyData
+{
+Sint8 id; // Device ID
+char szDeviceName[MAX_JOYNAME]; // Device Name
+char axes; // Number of axes
+char buttons; // Number of buttons
+char hats; // Number of buttons
+char balls; // Number of buttons
+int axes_min[MAX_AXES]; // minimum callibration value for axes
+int axes_med[MAX_AXES]; // medium callibration value for axes
+int axes_max[MAX_AXES]; // maximum callibration value for axes
+int buttoncalc[4]; // Used for buttons 5, 6, 7 and 8.
+} SYS_JoyData[MAX_JOYSTICKS];
+
+
+/* Structure used to convert data from OS/2 driver format to SDL format */
+struct joystick_hwdata
+{
+Sint8 id;
+struct _transaxes
+ {
+ int offset; /* Center Offset */
+ float scale1; /* Center to left/up Scale */
+ float scale2; /* Center to right/down Scale */
+ } transaxes[MAX_AXES];
+};
+
+/* Structure used to get values from Joystick Environment Variable */
+struct _joycfg
+{
+char name[MAX_JOYNAME];
+unsigned int axes;
+unsigned int buttons;
+unsigned int hats;
+unsigned int balls;
+};
+
+/* OS/2 Implementation Function Prototypes */
+APIRET joyPortOpen(HFILE * hGame);
+void joyPortClose(HFILE * hGame);
+int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars);
+int joyGetEnv(struct _joycfg * joydata);
+
+
+
+/************************************************************************/
+/* Function to scan the system for joysticks. */
+/* This function should set SDL_numjoysticks to the number of available */
+/* joysticks. Joystick 0 should be the system default joystick. */
+/* It should return 0, or -1 on an unrecoverable fatal error. */
+/************************************************************************/
+int SDL_SYS_JoystickInit(void)
+{
+APIRET rc; /* Generic OS/2 return code */
+GAME_PORT_STRUCT stJoyStatus; /* Joystick Status Structure */
+GAME_PARM_STRUCT stGameParms; /* Joystick Parameter Structure */
+GAME_CALIB_STRUCT stGameCalib; /* Calibration Struct */
+ULONG ulDataLen; /* Size of data */
+ULONG ulLastTick; /* Tick Counter for timing operations */
+Uint8 maxdevs; /* Maximum number of devices */
+Uint8 numdevs; /* Number of present devices */
+Uint8 maxbut; /* Maximum number of buttons... */
+Uint8 i; /* Temporary Count Vars */
+Uint8 ucNewJoystickMask; /* Mask for Joystick Detection */
+struct _joycfg joycfg; /* Joy Configuration from envvar */
+
+
+/* Get Max Number of Devices */
+rc = joyPortOpen(&hJoyPort); /* Open GAME$ port */
+if (rc != 0) return 0; /* Cannot open... report no joystick */
+ulDataLen = sizeof(stGameParms);
+rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_PARMS,
+ NULL, 0, NULL, &stGameParms, ulDataLen, &ulDataLen); /* Ask device info */
+if (rc != 0)
+ {
+ joyPortClose(&hJoyPort);
+ SDL_SetError("Could not read joystick port.");
+ return -1;
+ }
+if (stGameParms.useA != 0) maxdevs++;
+if (stGameParms.useB != 0) maxdevs++;
+if ( maxdevs > MAX_JOYSTICKS ) maxdevs = MAX_JOYSTICKS;
+
+/* Defines min/max axes values (callibration) */
+ulDataLen = sizeof(stGameCalib);
+rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_CALIB,
+ NULL, 0, NULL, &stGameCalib, ulDataLen, &ulDataLen);
+if (rc != 0)
+ {
+ joyPortClose(&hJoyPort);
+ SDL_SetError("Could not read callibration data.");
+ return -1;
+ }
+
+/* Determine how many joysticks are active */
+numdevs = 0; /* Points no device */
+ucNewJoystickMask = 0x0F; /* read all 4 joystick axis */
+ulDataLen = sizeof(ucNewJoystickMask);
+rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_RESET,
+ &ucNewJoystickMask, ulDataLen, &ulDataLen, NULL, 0, NULL);
+if (rc == 0)
+ {
+ ulDataLen = sizeof(stJoyStatus);
+ rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
+ NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
+ if (rc != 0)
+ {
+ joyPortClose(&hJoyPort);
+ SDL_SetError("Could not call joystick port.");
+ return -1;
+ }
+ ulLastTick = stJoyStatus.ulJs_Ticks;
+ while (stJoyStatus.ulJs_Ticks == ulLastTick)
+ {
+ rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
+ NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
+ }
+ if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) numdevs++;
+ if (((stJoyStatus.ucJs_JoyStickMask >> 2) & 0x03) > 0) numdevs++;
+ }
+
+if (numdevs>maxdevs) numdevs=maxdevs;
+
+/* If *any* joystick was detected... Let's configure SDL for them */
+if (numdevs > 0)
+ {
+ /* Verify if it is a "user defined" joystick */
+ if (joyGetEnv(&joycfg))
+ {
+ GAME_3POS_STRUCT * axis[4];
+ axis[0] = &stGameCalib.Ax;
+ axis[1] = &stGameCalib.Ay;
+ axis[2] = &stGameCalib.Bx;
+ axis[3] = &stGameCalib.By;
+ /* Say it has one device only (user defined is always one device only) */
+ numdevs = 1;
+ /* Define Device 0 as... */
+ SYS_JoyData[0].id=0;
+ /* Define Number of Axes... up to 4 */
+ if (joycfg.axes>MAX_AXES) joycfg.axes = MAX_AXES;
+ SYS_JoyData[0].axes = joycfg.axes;
+ /* Define number of buttons... 8 if 2 axes, 6 if 3 axes and 4 if 4 axes */
+ maxbut = MAX_BUTTONS;
+ if (joycfg.axes>2) maxbut-=((joycfg.axes-2)<<1); /* MAX_BUTTONS - 2*(axes-2) */
+ if (joycfg.buttons > maxbut) joycfg.buttons = maxbut;
+ SYS_JoyData[0].buttons = joycfg.buttons;
+ /* Define number of hats */
+ if (joycfg.hats > MAX_HATS) joycfg.hats = MAX_HATS;
+ SYS_JoyData[0].hats = joycfg.hats;
+ /* Define number of balls */
+ if (joycfg.balls > MAX_BALLS) joycfg.balls = MAX_BALLS;
+ SYS_JoyData[0].balls = joycfg.balls;
+ /* Initialize Axes Callibration Values */
+ for (i=0; i<joycfg.axes; i++)
+ {
+ SYS_JoyData[0].axes_min[i] = axis[i]->lower;
+ SYS_JoyData[0].axes_med[i] = axis[i]->centre;
+ SYS_JoyData[0].axes_max[i] = axis[i]->upper;
+ }
+ /* Initialize Buttons 5 to 8 structures */
+ if (joycfg.buttons>=5) SYS_JoyData[0].buttoncalc[0]=((axis[2]->lower+axis[3]->centre)>>1);
+ if (joycfg.buttons>=6) SYS_JoyData[0].buttoncalc[1]=((axis[3]->lower+axis[3]->centre)>>1);
+ if (joycfg.buttons>=7) SYS_JoyData[0].buttoncalc[2]=((axis[2]->upper+axis[3]->centre)>>1);
+ if (joycfg.buttons>=8) SYS_JoyData[0].buttoncalc[3]=((axis[3]->upper+axis[3]->centre)>>1);
+ /* Intialize Joystick Name */
+ strcpy (SYS_JoyData[0].szDeviceName,joycfg.name);
+ }
+ /* Default Init ... autoconfig */
+ else
+ {
+ /* if two devices were detected... configure as Joy1 4 axis and Joy2 2 axis */
+ if (numdevs==2)
+ {
+ /* Define Device 0 as 4 axes, 4 buttons */
+ SYS_JoyData[0].id=0;
+ SYS_JoyData[0].axes = 4;
+ SYS_JoyData[0].buttons = 4;
+ SYS_JoyData[0].hats = 0;
+ SYS_JoyData[0].balls = 0;
+ SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
+ SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
+ SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
+ SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
+ SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
+ SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
+ SYS_JoyData[0].axes_min[2] = stGameCalib.Bx.lower;
+ SYS_JoyData[0].axes_med[2] = stGameCalib.Bx.centre;
+ SYS_JoyData[0].axes_max[2] = stGameCalib.Bx.upper;
+ SYS_JoyData[0].axes_min[3] = stGameCalib.By.lower;
+ SYS_JoyData[0].axes_med[3] = stGameCalib.By.centre;
+ SYS_JoyData[0].axes_max[3] = stGameCalib.By.upper;
+ /* Define Device 1 as 2 axes, 2 buttons */
+ SYS_JoyData[1].id=1;
+ SYS_JoyData[1].axes = 2;
+ SYS_JoyData[1].buttons = 2;
+ SYS_JoyData[1].hats = 0;
+ SYS_JoyData[1].balls = 0;
+ SYS_JoyData[1].axes_min[0] = stGameCalib.Bx.lower;
+ SYS_JoyData[1].axes_med[0] = stGameCalib.Bx.centre;
+ SYS_JoyData[1].axes_max[0] = stGameCalib.Bx.upper;
+ SYS_JoyData[1].axes_min[1] = stGameCalib.By.lower;
+ SYS_JoyData[1].axes_med[1] = stGameCalib.By.centre;
+ SYS_JoyData[1].axes_max[1] = stGameCalib.By.upper;
+ }
+ /* One joystick only? */
+ else
+ {
+ /* If it is joystick A... */
+ if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0)
+ {
+ /* Define Device 0 as 2 axes, 4 buttons */
+ SYS_JoyData[0].id=0;
+ SYS_JoyData[0].axes = 2;
+ SYS_JoyData[0].buttons = 4;
+ SYS_JoyData[0].hats = 0;
+ SYS_JoyData[0].balls = 0;
+ SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
+ SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
+ SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
+ SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
+ SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
+ SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
+ }
+ /* If not, it is joystick B */
+ else
+ {
+ /* Define Device 1 as 2 axes, 2 buttons */
+ SYS_JoyData[0].id=1;
+ SYS_JoyData[0].axes = 2;
+ SYS_JoyData[0].buttons = 2;
+ SYS_JoyData[0].hats = 0;
+ SYS_JoyData[0].balls = 0;
+ SYS_JoyData[0].axes_min[0] = stGameCalib.Bx.lower;
+ SYS_JoyData[0].axes_med[0] = stGameCalib.Bx.centre;
+ SYS_JoyData[0].axes_max[0] = stGameCalib.Bx.upper;
+ SYS_JoyData[0].axes_min[1] = stGameCalib.By.lower;
+ SYS_JoyData[0].axes_med[1] = stGameCalib.By.centre;
+ SYS_JoyData[0].axes_max[1] = stGameCalib.By.upper;
+ }
+ }
+ /* Hack to define Joystick Port Names */
+ if ( numdevs > maxdevs ) numdevs = maxdevs;
+ for (i=0; i<numdevs; i++) sprintf (SYS_JoyData[i].szDeviceName,"Default Joystick %c",'A'+SYS_JoyData[i].id);
+ }
+ }
+/* Return the number of devices found */
+return(numdevs);
+}
+
+
+
+/***********************************************************/
+/* Function to get the device-dependent name of a joystick */
+/***********************************************************/
+const char *SDL_SYS_JoystickName(int index)
+{
+/* No need to verify if device exists, already done in upper layer */
+return(SYS_JoyData[index].szDeviceName);
+}
+
+
+
+/******************************************************************************/
+/* Function to open a joystick for use. */
+/* The joystick to open is specified by the index field of the joystick. */
+/* This should fill the nbuttons and naxes fields of the joystick structure. */
+/* It returns 0, or -1 if there is an error. */
+/******************************************************************************/
+int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
+{
+int index; /* Index shortcut for index in joystick structure */
+int i; /* Generic Counter */
+
+/* allocate memory for system specific hardware data */
+joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
+if (joystick->hwdata == NULL)
+ {
+ SDL_OutOfMemory();
+ return(-1);
+ }
+/* Reset Hardware Data */
+memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
+
+/* ShortCut Pointer */
+index = joystick->index;
+/* Define offsets and scales for all axes */
+joystick->hwdata->id = SYS_JoyData[index].id;
+for ( i = 0; i < MAX_AXES; ++i )
+ {
+ if ( (i<2) || i < SYS_JoyData[index].axes )
+ {
+ joystick->hwdata->transaxes[i].offset = ((AXIS_MAX + AXIS_MIN)>>1) - SYS_JoyData[index].axes_med[i];
+ //joystick->hwdata->transaxes[i].scale = (float)((AXIS_MAX - AXIS_MIN)/(SYS_JoyData[index].axes_max[i]-SYS_JoyData[index].axes_min[i]));
+ joystick->hwdata->transaxes[i].scale1 = (float)abs((AXIS_MIN/SYS_JoyData[index].axes_min[i]));
+ joystick->hwdata->transaxes[i].scale2 = (float)abs((AXIS_MAX/SYS_JoyData[index].axes_max[i]));
+ }
+ else
+ {
+ joystick->hwdata->transaxes[i].offset = 0;
+ //joystick->hwdata->transaxes[i].scale = 1.0; /* Just in case */
+ joystick->hwdata->transaxes[i].scale1 = 1.0; /* Just in case */
+ joystick->hwdata->transaxes[i].scale2 = 1.0; /* Just in case */
+ }
+ }
+
+/* fill nbuttons, naxes, and nhats fields */
+joystick->nbuttons = SYS_JoyData[index].buttons;
+joystick->naxes = SYS_JoyData[index].axes;
+/* joystick->nhats = SYS_JoyData[index].hats; */
+joystick->nhats = 0; /* No support for hats at this time */
+/* joystick->nballs = SYS_JoyData[index].balls; */
+joystick->nballs = 0; /* No support for balls at this time */
+return 0;
+}
+
+
+
+/***************************************************************************/
+/* Function to update the state of a joystick - called as a device poll. */
+/* This function shouldn't update the joystick structure directly, */
+/* but instead should call SDL_PrivateJoystick*() to deliver events */
+/* and update joystick device state. */
+/***************************************************************************/
+void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
+{
+APIRET rc; /* Generic OS/2 return code */
+int index; /* index shortcurt to joystick index */
+int i; /* Generic counter */
+int normbut; /* Number of buttons reported by joystick */
+int corr; /* Correction for button names */
+Sint16 value, change; /* Values used to update axis values */
+struct _transaxes *transaxes; /* Shortcut for Correction structure */
+Uint32 pos[MAX_AXES]; /* Vector to inform the Axis status */
+ULONG ulDataLen; /* Size of data */
+GAME_STATUS_STRUCT stGameStatus; /* Joystick Status Structure */
+
+ulDataLen = sizeof(stGameStatus);
+rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_STATUS,
+ NULL, 0, NULL, &stGameStatus, ulDataLen, &ulDataLen);
+if (rc != 0)
+ {
+ SDL_SetError("Could not read joystick status.");
+ return; /* Could not read data */
+ }
+
+/* Shortcut pointer */
+index = joystick->index;
+/* joystick motion events */
+
+if (SYS_JoyData[index].id == 0)
+ {
+ pos[0] = stGameStatus.curdata.A.x;
+ pos[1] = stGameStatus.curdata.A.y;
+ if (SYS_JoyData[index].axes >= 3) pos[2] = stGameStatus.curdata.B.x;
+ else pos[2]=0;
+ if (SYS_JoyData[index].axes >= 4) pos[3] = stGameStatus.curdata.B.y;
+ else pos[3]=0;
+ pos[4]=0; /* OS/2 basic drivers do not support more than 4 axes joysticks */
+ pos[5]=0;
+ }
+else if (SYS_JoyData[index].id == 1)
+ {
+ pos[0] = stGameStatus.curdata.B.x;
+ pos[1] = stGameStatus.curdata.B.y;
+ pos[2]=0;
+ pos[3]=0;
+ pos[4]=0;
+ pos[5]=0;
+ }
+
+/* Corrects the movements using the callibration */
+transaxes = joystick->hwdata->transaxes;
+for (i = 0; i < joystick->naxes; i++)
+ {
+ value = pos[i] + transaxes[i].offset;
+ if (value<0)
+ {
+ value*=transaxes[i].scale1;
+ if (value>0) value = AXIS_MIN;
+ }
+ else
+ {
+ value*=transaxes[i].scale2;
+ if (value<0) value = AXIS_MAX;
+ }
+ change = (value - joystick->axes[i]);
+ if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) )
+ {
+ SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value);
+ }
+ }
+
+/* joystick button A to D events */
+if (SYS_JoyData[index].id == 1) corr = 2;
+else corr = 0;
+normbut=4; /* Number of normal buttons */
+if (joystick->nbuttons<normbut) normbut = joystick->nbuttons;
+for ( i = corr; (i-corr) < normbut; ++i )
+ {
+ /*
+ Button A: 1110 0000
+ Button B: 1101 0000
+ Button C: 1011 0000
+ Button D: 0111 0000
+ */
+ if ( (~stGameStatus.curdata.butMask)>>4 & JOY_BUTTON_FLAG(i) )
+ {
+ if ( ! joystick->buttons[i-corr] )
+ {
+ SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_PRESSED);
+ }
+ }
+ else
+ {
+ if ( joystick->buttons[i-corr] )
+ {
+ SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_RELEASED);
+ }
+ }
+ }
+
+/* Joystick button E to H buttons */
+ /*
+ Button E: Axis 2 X Left
+ Button F: Axis 2 Y Up
+ Button G: Axis 2 X Right
+ Button H: Axis 2 Y Down
+ */
+if (joystick->nbuttons>=5)
+ {
+ if (stGameStatus.curdata.B.x < SYS_JoyData[index].buttoncalc[0]) SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_PRESSED);
+ else SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_RELEASED);
+ }
+if (joystick->nbuttons>=6)
+ {
+ if (stGameStatus.curdata.B.y < SYS_JoyData[index].buttoncalc[1]) SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_PRESSED);
+ else SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_RELEASED);
+ }
+if (joystick->nbuttons>=7)
+ {
+ if (stGameStatus.curdata.B.x > SYS_JoyData[index].buttoncalc[2]) SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_PRESSED);
+ else SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_RELEASED);
+ }
+if (joystick->nbuttons>=8)
+ {
+ if (stGameStatus.curdata.B.y > SYS_JoyData[index].buttoncalc[3]) SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_PRESSED);
+ else SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_RELEASED);
+ }
+
+/* joystick hat events */
+/* Not Supported under OS/2 */
+/* joystick ball events */
+/* Not Supported under OS/2 */
+}
+
+
+
+/******************************************/
+/* Function to close a joystick after use */
+/******************************************/
+void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
+{
+if (joystick->hwdata != NULL)
+ {
+ /* free system specific hardware data */
+ free(joystick->hwdata);
+ }
+}
+
+
+
+/********************************************************************/
+/* Function to perform any system-specific joystick related cleanup */
+/********************************************************************/
+void SDL_SYS_JoystickQuit(void)
+{
+joyPortClose(&hJoyPort);
+}
+
+
+
+/************************/
+/************************/
+/* OS/2 Implementations */
+/************************/
+/************************/
+
+
+/*****************************************/
+/* Open Joystick Port, if not opened yet */
+/*****************************************/
+APIRET joyPortOpen(HFILE * hGame)
+{
+APIRET rc; /* Generic Return Code */
+ULONG ulAction; /* ? */
+ULONG ulVersion; /* Version of joystick driver */
+ULONG ulDataLen; /* Size of version data */
+
+/* Verifies if joyport is not already open... */
+if (*hGame != NULL) return 0;
+/* Open GAME$ for read */
+rc = DosOpen((PSZ)GAMEPDDNAME, hGame, &ulAction, 0, FILE_READONLY,
+ FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL);
+if (rc != 0)
+ {
+ SDL_SetError("Could not open Joystick Port.");
+ return -1;
+ }
+
+/* Get Joystick Driver Version... must be 2.0 or higher */
+ulVersion = 0;
+ulDataLen = sizeof(ulVersion);
+rc = DosDevIOCtl( *hGame, IOCTL_CAT_USER, GAME_GET_VERSION,
+ NULL, 0, NULL, &ulVersion, ulDataLen, &ulDataLen);
+if (rc != 0)
+ {
+ joyPortClose(hGame);
+ SDL_SetError("Could not get Joystick Driver version.");
+ return -1;
+ }
+if (ulVersion < GAME_VERSION)
+ {
+ joyPortClose(hGame);
+ SDL_SetError("Driver too old. At least IBM driver version 2.0 required.");
+ return -1;
+ }
+return 0;
+}
+
+
+
+/****************************/
+/* Close JoyPort, if opened */
+/****************************/
+void joyPortClose(HFILE * hGame)
+{
+if (*hGame != NULL) DosClose(*hGame);
+*hGame = NULL;
+}
+
+
+
+/***************************/
+/* Get SDL Joystick EnvVar */
+/***************************/
+int joyGetEnv(struct _joycfg * joydata)
+{
+char *joyenv; /* Pointer to tested character */
+char tempnumber[5]; /* Temporary place to put numeric texts */
+
+joyenv = getenv("SDL_OS2_JOYSTICK");
+if (joyenv == NULL) return 0;
+/* Joystick Environment is defined! */
+while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
+/* If the string name starts with '... get if fully */
+if (*joyenv=='\'') joyenv+=joyGetData(++joyenv,joydata->name,'\'',sizeof(joydata->name));
+/* If not, get it until the next space */
+else if (*joyenv=='\"') joyenv+=joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name));
+else joyenv+=joyGetData(joyenv,joydata->name,' ',sizeof(joydata->name));
+/* Now get the number of axes */
+while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
+joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
+joydata->axes = atoi(tempnumber);
+/* Now get the number of buttons */
+while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
+joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
+joydata->buttons = atoi(tempnumber);
+/* Now get the number of hats */
+while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
+joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
+joydata->hats = atoi(tempnumber);
+/* Now get the number of balls */
+while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
+joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
+joydata->balls = atoi(tempnumber);
+return 1;
+}
+
+
+
+/************************************************************************/
+/* Get a text from in the string starting in joyenv until it finds */
+/* the stopchar or maxchars is reached. The result is placed in name. */
+/************************************************************************/
+int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars)
+{
+char *nameptr; /* Pointer to the selected character */
+int chcnt=0; /* Count how many characters where copied */
+
+nameptr=name;
+while (*joyenv!=stopchar && *joyenv!=0)
+ {
+ if (nameptr<(name+(maxchars-1)))
+ {
+ *nameptr = *joyenv; /* Only copy if smaller than maximum */
+ nameptr++;
+ }
+ chcnt++;
+ joyenv++;
+ }
+if (*joyenv==stopchar)
+ {
+ joyenv++; /* Jump stopchar */
+ chcnt++;
+ }
+*nameptr = 0; /* Mark last byte */
+return chcnt;
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/os2/joyos2.h Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,177 @@
+/*****************************************************************************/
+/* */
+/* COPYRIGHT Copyright (C) 1995 IBM Corporation */
+/* */
+/* The following IBM OS/2 source code is provided to you solely for */
+/* the purpose of assisting you in your development of OS/2 device */
+/* drivers. You may use this code in accordance with the IBM License */
+/* Agreement provided in the IBM Device Driver Source Kit for OS/2. This */
+/* Copyright statement may not be removed. */
+/* */
+/*****************************************************************************/
+#ifndef JOYOS2_H
+#define JOYOS2_H
+
+/****** GAMEPORT.SYS joystick definitions, start *****************************/
+#define GAME_VERSION 0x20 /* 2.0 First IBM version */
+#define GAMEPDDNAME "GAME$ "
+#define IOCTL_CAT_USER 0x80
+#define GAME_PORT_GET 0x20 /* read GAMEPORT.SYS values */
+#define GAME_PORT_RESET 0x60 /* reset joystick mask with given value */
+
+#pragma pack(1) /* pack structure size is 1 byte */
+typedef struct { /* GAMEPORT.SYS structure */
+ USHORT usJs_AxCnt; /* Joystick_A X position */
+ USHORT usJs_AyCnt; /* Joystick_A Y position */
+ USHORT usJs_BxCnt; /* Joystick_B X position */
+ USHORT usJs_ByCnt; /* Joystick_B Y position */
+ USHORT usJs_ButtonA1Cnt; /* button A1 press count */
+ USHORT usJs_ButtonA2Cnt; /* button A2 press count */
+ USHORT usJs_ButtonB1Cnt; /* button B1 press count */
+ USHORT usJs_ButtonB2Cnt; /* button B2 press count */
+ UCHAR ucJs_JoyStickMask; /* mask of connected joystick pots */
+ UCHAR ucJs_ButtonStatus; /* bits of switches down */
+ ULONG ulJs_Ticks; /* joystick clock ticks */
+} GAME_PORT_STRUCT;
+#pragma pack() /*reset to normal pack size */
+/****** GAMEPORT.SYS joystick definitions, end *******************************/
+
+
+/****************************************************************************/
+#define GAME_GET_VERSION 0x01
+#define GAME_GET_PARMS 0x02
+#define GAME_SET_PARMS 0x03
+#define GAME_GET_CALIB 0x04
+#define GAME_SET_CALIB 0x05
+#define GAME_GET_DIGSET 0x06
+#define GAME_SET_DIGSET 0x07
+#define GAME_GET_STATUS 0x10
+#define GAME_GET_STATUS_BUTWAIT 0x11
+#define GAME_GET_STATUS_SAMPWAIT 0x12
+/****************************************************************************/
+
+/****************************************************************************/
+// bit masks for each axis
+#define JOY_AX_BIT 0x01
+#define JOY_AY_BIT 0x02
+#define JOY_A_BITS (JOY_AX_BIT|JOY_AY_BIT)
+#define JOY_BX_BIT 0x04
+#define JOY_BY_BIT 0x08
+#define JOY_B_BITS (JOY_BX_BIT|JOY_BY_BIT)
+#define JOY_ALLPOS_BITS (JOY_A_BITS|JOY_B_BITS)
+
+// bit masks for each button
+#define JOY_BUT1_BIT 0x10
+#define JOY_BUT2_BIT 0x20
+#define JOY_BUT3_BIT 0x40
+#define JOY_BUT4_BIT 0x80
+#define JOY_ALL_BUTS (JOY_BUT1_BIT|JOY_BUT2_BIT|JOY_BUT3_BIT|JOY_BUT4_BIT)
+/****************************************************************************/
+
+/****************************************************************************/
+// 1-D position struct used for each axis
+typedef SHORT GAME_POS; /* some data formats require signed values */
+
+// simple 2-D position for each joystick
+typedef struct
+{
+ GAME_POS x;
+ GAME_POS y;
+}
+GAME_2DPOS_STRUCT;
+
+// struct defining the instantaneous state of both sticks and all buttons
+typedef struct
+{
+ GAME_2DPOS_STRUCT A;
+ GAME_2DPOS_STRUCT B;
+ USHORT butMask;
+}
+GAME_DATA_STRUCT;
+
+// struct to be used for calibration and digital response on each axis
+typedef struct
+{
+ GAME_POS lower;
+ GAME_POS centre;
+ GAME_POS upper;
+}
+GAME_3POS_STRUCT;
+/****************************************************************************/
+
+/****************************************************************************/
+// status struct returned to OS/2 applications:
+// current data for all sticks as well as button counts since last read
+typedef struct
+{
+ GAME_DATA_STRUCT curdata;
+ USHORT b1cnt;
+ USHORT b2cnt;
+ USHORT b3cnt;
+ USHORT b4cnt;
+}
+GAME_STATUS_STRUCT;
+/****************************************************************************/
+
+/****************************************************************************/
+/* in use bitmasks originating in 0.2b */
+#define GAME_USE_BOTH_OLDMASK 0x01 /* for backward compat with bool */
+#define GAME_USE_X_NEWMASK 0x02
+#define GAME_USE_Y_NEWMASK 0x04
+#define GAME_USE_X_EITHERMASK (GAME_USE_X_NEWMASK|GAME_USE_BOTH_OLDMASK)
+#define GAME_USE_Y_EITHERMASK (GAME_USE_Y_NEWMASK|GAME_USE_BOTH_OLDMASK)
+#define GAME_USE_BOTH_NEWMASK (GAME_USE_X_NEWMASK|GAME_USE_Y_NEWMASK)
+
+/* only timed sampling implemented in version 1.0 */
+#define GAME_MODE_TIMED 1 /* timed sampling */
+#define GAME_MODE_REQUEST 2 /* request driven sampling */
+
+/* only raw implemented in version 1.0 */
+#define GAME_DATA_FORMAT_RAW 1 /* [l,c,r] */
+#define GAME_DATA_FORMAT_SIGNED 2 /* [-l,0,+r] */
+#define GAME_DATA_FORMAT_BINARY 3 /* {-1,0,+1} */
+#define GAME_DATA_FORMAT_SCALED 4 /* [-10,+10] */
+
+// parameters defining the operation of the driver
+typedef struct
+{
+ USHORT useA; /* new bitmasks: see above */
+ USHORT useB;
+ USHORT mode; /* see consts above */
+ USHORT format; /* see consts above */
+ USHORT sampDiv; /* samp freq = 32 / n */
+ USHORT scale; /* scaling factor */
+ USHORT res1; /* must be 0 */
+ USHORT res2; /* must be 0 */
+}
+GAME_PARM_STRUCT;
+/****************************************************************************/
+
+/****************************************************************************/
+// calibration values for each axis:
+// - upper limit on value to be considered in lower range
+// - centre value
+// - lower limit on value to be considered in upper range
+typedef struct
+{
+ GAME_3POS_STRUCT Ax;
+ GAME_3POS_STRUCT Ay;
+ GAME_3POS_STRUCT Bx;
+ GAME_3POS_STRUCT By;
+}
+GAME_CALIB_STRUCT;
+/****************************************************************************/
+
+/****************************************************************************/
+// struct defining the digital response values for all axes
+typedef struct
+{
+ GAME_3POS_STRUCT Ax;
+ GAME_3POS_STRUCT Ay;
+ GAME_3POS_STRUCT Bx;
+ GAME_3POS_STRUCT By;
+}
+GAME_DIGSET_STRUCT;
+/****************************************************************************/
+
+#endif
--- a/src/loadso/macosx/SDL_loadso.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/loadso/macosx/SDL_loadso.c Wed Nov 23 07:29:56 2005 +0000
@@ -781,6 +781,7 @@
const char *errstr;
const char *file;
void (*init) (void);
+
ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
switch (ofirc)
{
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/loadso/os2/SDL_loadso.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,82 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2004 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* System dependent library loading routines */
+
+#if !SDL_INTERNAL_BUILDING_LOADSO
+#error Do not compile directly...compile src/SDL_loadso.c instead!
+#endif
+
+#if !defined(__OS2__)
+#error Compiling for the wrong platform?
+#endif
+
+#include <stdio.h>
+#define INCL_DOSERRORS
+#define INCL_DOSMODULEMGR
+#include <os2.h>
+
+#include "SDL_types.h"
+#include "SDL_error.h"
+#include "SDL_loadso.h"
+
+void *SDL_LoadObject(const char *sofile)
+{
+ HMODULE handle = NULL;
+ char buf[512];
+ APIRET ulrc = DosLoadModule(buf, sizeof (buf), (char *) sofile, &handle);
+
+ /* Generate an error message if all loads failed */
+ if ((ulrc != NO_ERROR) || (handle == NULL))
+ SDL_SetError("Failed loading %s: %s", sofile, buf);
+
+ return((void *) handle);
+}
+
+void *SDL_LoadFunction(void *handle, const char *name)
+{
+ const char *loaderror = "Unknown error";
+ void *symbol = NULL;
+ APIRET ulrc = DosQueryProcAddr((HMODULE)handle, 0, (char *)name, &symbol);
+ if (ulrc == ERROR_INVALID_HANDLE)
+ loaderror = "Invalid module handle";
+ else if (ulrc == ERROR_INVALID_NAME)
+ loaderror = "Symbol not found";
+
+ if (symbol == NULL)
+ SDL_SetError("Failed loading %s: %s", name, loaderror);
+
+ return(symbol);
+}
+
+void SDL_UnloadObject(void *handle)
+{
+ if ( handle != NULL )
+ DosFreeModule((HMODULE) handle);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,36 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for threading
+#=============================================================================
+
+object_files=SDL_thread.obj SDL_sysmutex.obj SDL_syssem.obj SDL_systhread.obj SDL_syscond.obj
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
+
+all : $(object_files)
+
+SDL_sysmutex.obj: .AUTODEPEND
+ wcc386 os2\SDL_sysmutex.c $(cflags)
+
+SDL_syssem.obj: .AUTODEPEND
+ wcc386 os2\SDL_syssem.c $(cflags)
+
+SDL_systhread.obj: .AUTODEPEND
+ wcc386 os2\SDL_systhread.c $(cflags)
+
+SDL_syscond.obj: .AUTODEPEND
+ wcc386 os2\SDL_syscond.c $(cflags)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- a/src/thread/SDL_systhread.h Wed Nov 23 07:23:48 2005 +0000
+++ b/src/thread/SDL_systhread.h Wed Nov 23 07:29:56 2005 +0000
@@ -33,7 +33,11 @@
saves a system-dependent thread id in thread->id, and returns 0
on success.
*/
+#ifdef __OS2__
+extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
+#else
extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args);
+#endif
/* This function does any necessary setup in the child thread */
extern void SDL_SYS_SetupThread(void);
--- a/src/thread/SDL_thread.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/thread/SDL_thread.c Wed Nov 23 07:29:56 2005 +0000
@@ -218,7 +218,11 @@
*statusloc = userfunc(userdata);
}
-SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
+#ifdef __OS2__
+DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread_Core(int (*fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
+#else
+DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (*fn)(void *), void *data)
+#endif
{
SDL_Thread *thread;
thread_args *args;
@@ -254,7 +258,11 @@
SDL_AddThread(thread);
/* Create the thread and go! */
+#ifdef __OS2__
+ ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
+#else
ret = SDL_SYS_CreateThread(thread, args);
+#endif
if ( ret >= 0 ) {
/* Wait for the thread function to use arguments */
SDL_SemWait(args->wait);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/os2/SDL_syscond.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,223 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* An implementation of condition variables using semaphores and mutexes */
+/*
+ This implementation borrows heavily from the BeOS condition variable
+ implementation, written by Christopher Tate and Owen Smith. Thanks!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+
+struct SDL_cond
+{
+ SDL_mutex *lock;
+ int waiting;
+ int signals;
+ SDL_sem *wait_sem;
+ SDL_sem *wait_done;
+};
+
+/* Create a condition variable */
+DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void)
+{
+ SDL_cond *cond;
+
+ cond = (SDL_cond *) malloc(sizeof(SDL_cond));
+ if ( cond ) {
+ cond->lock = SDL_CreateMutex();
+ cond->wait_sem = SDL_CreateSemaphore(0);
+ cond->wait_done = SDL_CreateSemaphore(0);
+ cond->waiting = cond->signals = 0;
+ if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) {
+ SDL_DestroyCond(cond);
+ cond = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return(cond);
+}
+
+/* Destroy a condition variable */
+DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond)
+{
+ if ( cond ) {
+ if ( cond->wait_sem ) {
+ SDL_DestroySemaphore(cond->wait_sem);
+ }
+ if ( cond->wait_done ) {
+ SDL_DestroySemaphore(cond->wait_done);
+ }
+ if ( cond->lock ) {
+ SDL_DestroyMutex(cond->lock);
+ }
+ free(cond);
+ }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond)
+{
+ if ( ! cond ) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if ( cond->waiting > cond->signals ) {
+ ++cond->signals;
+ SDL_SemPost(cond->wait_sem);
+ SDL_UnlockMutex(cond->lock);
+ SDL_SemWait(cond->wait_done);
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond)
+{
+ if ( ! cond ) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if ( cond->waiting > cond->signals ) {
+ int i, num_waiting;
+
+ num_waiting = (cond->waiting - cond->signals);
+ cond->signals = cond->waiting;
+ for ( i=0; i<num_waiting; ++i ) {
+ SDL_SemPost(cond->wait_sem);
+ }
+ /* Now all released threads are blocked here, waiting for us.
+ Collect them all (and win fabulous prizes!) :-)
+ */
+ SDL_UnlockMutex(cond->lock);
+ for ( i=0; i<num_waiting; ++i ) {
+ SDL_SemWait(cond->wait_done);
+ }
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Wait on the condition variable for at most 'ms' milliseconds.
+ The mutex must be locked before entering this function!
+ The mutex is unlocked during the wait, and locked again after the wait.
+
+Typical use:
+
+Thread A:
+ SDL_LockMutex(lock);
+ while ( ! condition ) {
+ SDL_CondWait(cond);
+ }
+ SDL_UnlockMutex(lock);
+
+Thread B:
+ SDL_LockMutex(lock);
+ ...
+ condition = true;
+ ...
+ SDL_UnlockMutex(lock);
+ */
+DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
+{
+ int retval;
+
+ if ( ! cond ) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ /* Obtain the protection mutex, and increment the number of waiters.
+ This allows the signal mechanism to only perform a signal if there
+ are waiting threads.
+ */
+ SDL_LockMutex(cond->lock);
+ ++cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Unlock the mutex, as is required by condition variable semantics */
+ SDL_UnlockMutex(mutex);
+
+ /* Wait for a signal */
+ if ( ms == SDL_MUTEX_MAXWAIT ) {
+ retval = SDL_SemWait(cond->wait_sem);
+ } else {
+ retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
+ }
+
+ /* Let the signaler know we have completed the wait, otherwise
+ the signaler can race ahead and get the condition semaphore
+ if we are stopped between the mutex unlock and semaphore wait,
+ giving a deadlock. See the following URL for details:
+ http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
+ */
+ SDL_LockMutex(cond->lock);
+ if ( cond->signals > 0 ) {
+ /* If we timed out, we need to eat a condition signal */
+ if ( retval > 0 ) {
+ SDL_SemWait(cond->wait_sem);
+ }
+ /* We always notify the signal thread that we are done */
+ SDL_SemPost(cond->wait_done);
+
+ /* Signal handshake complete */
+ --cond->signals;
+ }
+ --cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Lock the mutex, as is required by condition variable semantics */
+ SDL_LockMutex(mutex);
+
+ return retval;
+}
+
+/* Wait on the condition variable forever */
+DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
+{
+ return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/os2/SDL_syscond_c.h Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/os2/SDL_sysmutex.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,115 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Mutex functions using the OS/2 API */
+
+#include <stdio.h>
+#include <stdlib.h>
+#define INCL_DOSERRORS
+#define INCL_DOSSEMAPHORES
+#include <os2.h>
+
+#include "SDL_error.h"
+#include "SDL_mutex.h"
+
+
+struct SDL_mutex {
+ HMTX hmtxID;
+};
+
+/* Create a mutex */
+DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void)
+{
+ SDL_mutex *mutex;
+ APIRET ulrc;
+
+ /* Allocate mutex memory */
+ mutex = (SDL_mutex *)malloc(sizeof(*mutex));
+ if (mutex)
+ {
+ /* Create the mutex, with initial value signaled */
+ ulrc = DosCreateMutexSem(NULL, // Create unnamed semaphore
+ &(mutex->hmtxID), // Pointer to handle
+ 0L, // Flags: create it private (not shared)
+ FALSE); // Initial value: unowned
+ if (ulrc!=NO_ERROR)
+ {
+ SDL_SetError("Couldn't create mutex");
+ free(mutex);
+ mutex = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return(mutex);
+}
+
+/* Free the mutex */
+DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
+{
+ if ( mutex )
+ {
+ if ( mutex->hmtxID )
+ {
+ DosCloseMutexSem(mutex->hmtxID);
+ mutex->hmtxID = 0;
+ }
+ free(mutex);
+ }
+}
+
+/* Lock the mutex */
+DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex)
+{
+ if ( mutex == NULL )
+ {
+ SDL_SetError("Passed a NULL mutex");
+ return -1;
+ }
+ if ( DosRequestMutexSem(mutex->hmtxID, SEM_INDEFINITE_WAIT) != NO_ERROR )
+ {
+ SDL_SetError("Couldn't wait on mutex");
+ return -1;
+ }
+ return(0);
+}
+
+/* Unlock the mutex */
+DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex)
+{
+ if ( mutex == NULL )
+ {
+ SDL_SetError("Passed a NULL mutex");
+ return -1;
+ }
+ if ( DosReleaseMutexSem(mutex->hmtxID) != NO_ERROR )
+ {
+ SDL_SetError("Couldn't release mutex");
+ return -1;
+ }
+ return(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/os2/SDL_syssem.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,199 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Semaphore functions using the OS/2 API */
+
+#include <stdio.h>
+#include <stdlib.h>
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_DOSSEMAPHORES
+#include <os2.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+
+
+struct SDL_semaphore {
+ HMTX id;
+ HEV changed;
+ Uint32 value;
+};
+
+
+/* Create a semaphore */
+DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
+{
+ SDL_sem *sem;
+ ULONG ulrc;
+
+ /* Allocate sem memory */
+ sem = (SDL_sem *)malloc(sizeof(*sem));
+ if ( sem ) {
+ /* Create the mutex semaphore */
+ ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE);
+ if ( ulrc ) {
+ SDL_SetError("Couldn't create semaphore");
+ free(sem);
+ sem = NULL;
+ } else
+ {
+ DosCreateEventSem(NULL, &(sem->changed), 0, FALSE);
+ sem->value = initial_value;
+ DosReleaseMutexSem(sem->id);
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return(sem);
+}
+
+/* Free the semaphore */
+DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
+{
+ if ( sem ) {
+ if ( sem->id ) {
+ DosCloseEventSem(sem->changed);
+ DosCloseMutexSem(sem->id);
+ sem->id = 0;
+ }
+ free(sem);
+ }
+}
+
+DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
+{
+ ULONG ulrc;
+
+ if ( ! sem ) {
+ SDL_SetError("Passed a NULL sem");
+ return -1;
+ }
+
+ if ( timeout == SDL_MUTEX_MAXWAIT ) {
+ while (1) {
+ ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
+ if (ulrc) {
+ /* if error waiting mutex */
+ SDL_SetError("DosRequestMutexSem() failed");
+ return -1;
+ } else if (sem->value) {
+ sem->value--;
+ DosReleaseMutexSem(sem->id);
+ return 0;
+ } else {
+ ULONG ulPostCount;
+ DosResetEventSem(sem->changed, &ulPostCount);
+ DosReleaseMutexSem(sem->id);
+ /* continue waiting until somebody posts the semaphore */
+ DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT);
+ }
+ }
+ } else
+ if ( timeout == 0 )
+ {
+ ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
+ if (ulrc==NO_ERROR)
+ {
+ if (sem->value)
+ {
+ sem->value--;
+ DosReleaseMutexSem(sem->id);
+ return 0;
+ } else
+ {
+ DosReleaseMutexSem(sem->id);
+ return SDL_MUTEX_TIMEDOUT;
+ }
+ } else
+ {
+ SDL_SetError("DosRequestMutexSem() failed");
+ return -1;
+ }
+ } else {
+ ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
+ if (ulrc) {
+ /* if error waiting mutex */
+ SDL_SetError("DosRequestMutexSem() failed");
+ return -1;
+ } else
+ if (sem->value) {
+ sem->value--;
+ DosReleaseMutexSem(sem->id);
+ return 0;
+ } else {
+ ULONG ulPostCount;
+ DosResetEventSem(sem->changed, &ulPostCount);
+ DosReleaseMutexSem(sem->id);
+ /* continue waiting until somebody posts the semaphore */
+ ulrc = DosWaitEventSem(sem->changed, timeout);
+ if (ulrc==NO_ERROR)
+ return 0;
+ else
+ return SDL_MUTEX_TIMEDOUT;
+ }
+ }
+ /* never reached */
+ return -1;
+}
+
+DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem)
+{
+ return SDL_SemWaitTimeout(sem, 0);
+}
+
+DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem)
+{
+ return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
+}
+
+/* Returns the current count of the semaphore */
+DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
+{
+ if ( ! sem ) {
+ SDL_SetError("Passed a NULL sem");
+ return 0;
+ }
+ return sem->value;
+}
+
+DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
+{
+ if ( ! sem ) {
+ SDL_SetError("Passed a NULL sem");
+ return -1;
+ }
+ if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) {
+ SDL_SetError("DosRequestMutexSem() failed");
+ return -1;
+ }
+ sem->value++;
+ DosPostEventSem(sem->changed);
+ DosReleaseMutexSem(sem->id);
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/os2/SDL_systhread.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,114 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* OS/2 thread management routines for SDL */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <process.h>
+#define INCL_DOSERRORS
+#define INCL_DOSPROCESS
+#include <os2.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+#include "SDL_systhread.h"
+
+typedef struct ThreadStartParms
+{
+ void *args;
+ pfnSDL_CurrentEndThread pfnCurrentEndThread;
+} tThreadStartParms, *pThreadStartParms;
+
+static void threadfunc(void *pparm)
+{
+ pThreadStartParms pThreadParms = pparm;
+ pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
+
+ // Call the thread function!
+ SDL_RunThread(pThreadParms->args);
+
+ // Get the current endthread we have to use!
+ if (pThreadParms)
+ {
+ pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
+ free(pThreadParms);
+ }
+ // Call endthread!
+ if (pfnCurrentEndThread)
+ (*pfnCurrentEndThread)();
+}
+
+int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
+{
+ pThreadStartParms pThreadParms = malloc(sizeof(tThreadStartParms));
+ if (!pThreadParms)
+ {
+ SDL_SetError("Not enough memory to create thread");
+ return(-1);
+ }
+
+ // Save the function which we will have to call to clear the RTL of calling app!
+ pThreadParms->pfnCurrentEndThread = pfnEndThread;
+ // Also save the real parameters we have to pass to thread function
+ pThreadParms->args = args;
+ // Start the thread using the runtime library of calling app!
+ thread->threadid = thread->handle = (*pfnBeginThread)(threadfunc, 512*1024, pThreadParms);
+ if (thread->threadid<=0)
+ {
+ SDL_SetError("Not enough resources to create thread");
+ return(-1);
+ }
+ return(0);
+}
+
+void SDL_SYS_SetupThread(void)
+{
+ return;
+}
+
+DECLSPEC Uint32 SDLCALL SDL_ThreadID(void)
+{
+ PTIB tib;
+ DosGetInfoBlocks(&tib, NULL);
+ return((Uint32) (tib->tib_ptib2->tib2_ultid));
+}
+
+void SDL_SYS_WaitThread(SDL_Thread *thread)
+{
+ TID tid = thread->handle;
+ DosWaitThread(&tid, DCWW_WAIT);
+}
+
+/* WARNING: This function is really a last resort.
+ * Threads should be signaled and then exit by themselves.
+ * TerminateThread() doesn't perform stack and DLL cleanup.
+ */
+void SDL_SYS_KillThread(SDL_Thread *thread)
+{
+ DosKillThread(thread->handle);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/os2/SDL_systhread_c.h Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#define INCL_DOSPROCESS
+#include <os2.h>
+
+typedef TID SYS_ThreadHandle;
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/timer/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for timers
+#=============================================================================
+
+object_files=SDL_timer.obj SDL_systimer.obj
+ExtraCFlags=
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
+
+all : $(object_files)
+
+SDL_systimer.obj: .AUTODEPEND
+ wcc386 os2\SDL_systimer.c $(cflags)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- a/src/timer/SDL_timer.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/timer/SDL_timer.c Wed Nov 23 07:29:56 2005 +0000
@@ -242,7 +242,7 @@
}
/* Old style callback functions are wrapped through this */
-static Uint32 callback_wrapper(Uint32 ms, void *param)
+static Uint32 SDLCALL callback_wrapper(Uint32 ms, void *param)
{
SDL_TimerCallback func = (SDL_TimerCallback) param;
return (*func)(ms);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/timer/os2/SDL_systimer.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,230 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSDATETIME
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSEXCEPTIONS
+#include <os2.h>
+
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_timer_c.h"
+#include "SDL_error.h"
+
+
+#define TIME_WRAP_VALUE (~(DWORD)0)
+
+/* The first high-resolution ticks value of the application */
+static long long hires_start_ticks;
+/* The number of ticks per second of the high-resolution performance counter */
+static ULONG hires_ticks_per_second;
+
+void SDL_StartTicks(void)
+{
+ DosTmrQueryFreq(&hires_ticks_per_second);
+ DosTmrQueryTime((PQWORD)&hires_start_ticks);
+}
+
+DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
+{
+ long long hires_now;
+ ULONG ticks = ticks;
+
+ DosTmrQueryTime((PQWORD)&hires_now);
+/*
+ hires_now -= hires_start_ticks;
+ hires_now *= 1000;
+ hires_now /= hires_ticks_per_second;
+*/
+ /* inline asm to avoid runtime inclusion */
+ _asm {
+ push edx
+ push eax
+ mov eax, dword ptr hires_now
+ mov edx, dword ptr hires_now+4
+ sub eax, dword ptr hires_start_ticks
+ sbb edx, dword ptr hires_start_ticks+4
+ mov ebx,1000
+ mov ecx,edx
+ mul ebx
+ push eax
+ push edx
+ mov eax,ecx
+ mul ebx
+ pop eax
+ add edx,eax
+ pop eax
+ mov ebx, dword ptr hires_ticks_per_second
+ div ebx
+ mov dword ptr ticks, eax
+ pop edx
+ pop eax
+ }
+
+ return ticks;
+
+}
+
+/* High resolution sleep, originally made by Ilya Zakharevich */
+DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
+{
+ /* This is similar to DosSleep(), but has 8ms granularity in time-critical
+ threads even on Warp3. */
+ HEV hevEvent1 = 0; /* Event semaphore handle */
+ HTIMER htimerEvent1 = 0; /* Timer handle */
+ APIRET rc = NO_ERROR; /* Return code */
+ int ret = 1;
+ ULONG priority = 0, nesting; /* Shut down the warnings */
+ PPIB pib;
+ PTIB tib;
+ char *e = NULL;
+ APIRET badrc;
+ int switch_priority = 50;
+
+ DosCreateEventSem(NULL, /* Unnamed */
+ &hevEvent1, /* Handle of semaphore returned */
+ DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */
+ FALSE); /* Semaphore is in RESET state */
+
+ if (ms >= switch_priority)
+ switch_priority = 0;
+ if (switch_priority)
+ {
+ if (DosGetInfoBlocks(&tib, &pib)!=NO_ERROR)
+ switch_priority = 0;
+ else
+ {
+ /* In Warp3, to switch scheduling to 8ms step, one needs to do
+ DosAsyncTimer() in time-critical thread. On laters versions,
+ more and more cases of wait-for-something are covered.
+
+ It turns out that on Warp3fp42 it is the priority at the time
+ of DosAsyncTimer() which matters. Let's hope that this works
+ with later versions too... XXXX
+ */
+ priority = (tib->tib_ptib2->tib2_ulpri);
+ if ((priority & 0xFF00) == 0x0300) /* already time-critical */
+ switch_priority = 0;
+ /* Make us time-critical. Just modifying TIB is not enough... */
+ /* tib->tib_ptib2->tib2_ulpri = 0x0300;*/
+ /* We do not want to run at high priority if a signal causes us
+ to longjmp() out of this section... */
+ if (DosEnterMustComplete(&nesting))
+ switch_priority = 0;
+ else
+ DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
+ }
+ }
+
+ if ((badrc = DosAsyncTimer(ms,
+ (HSEM) hevEvent1, /* Semaphore to post */
+ &htimerEvent1))) /* Timer handler (returned) */
+ e = "DosAsyncTimer";
+
+ if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300)
+ {
+ /* Nobody switched priority while we slept... Ignore errors... */
+ /* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */
+ if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0)))
+ rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0);
+ }
+ if (switch_priority)
+ rc = DosExitMustComplete(&nesting); /* Ignore errors */
+
+ /* The actual blocking call is made with "normal" priority. This way we
+ should not bother with DosSleep(0) etc. to compensate for us interrupting
+ higher-priority threads. The goal is to prohibit the system spending too
+ much time halt()ing, not to run us "no matter what". */
+ if (!e) /* Wait for AsyncTimer event */
+ badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT);
+
+ if (e) ; /* Do nothing */
+ else if (badrc == ERROR_INTERRUPT)
+ ret = 0;
+ else if (badrc)
+ e = "DosWaitEventSem";
+ if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */
+ e = "DosCloseEventSem";
+ badrc = rc;
+ }
+ if (e)
+ {
+ SDL_SetError("[SDL_Delay] : Had error in %s(), rc is 0x%x\n", e, badrc);
+ }
+}
+
+/* Data to handle a single periodic alarm */
+static int timer_alive = 0;
+static SDL_Thread *timer = NULL;
+
+static int RunTimer(void *unused)
+{
+ DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
+ while ( timer_alive ) {
+ if ( SDL_timer_running ) {
+ SDL_ThreadedTimerCheck();
+ }
+ SDL_Delay(10);
+ }
+ return(0);
+}
+
+/* This is only called if the event thread is not running */
+int SDL_SYS_TimerInit(void)
+{
+ timer_alive = 1;
+ timer = SDL_CreateThread(RunTimer, NULL);
+ if ( timer == NULL )
+ return(-1);
+ return(SDL_SetTimerThreaded(1));
+}
+
+void SDL_SYS_TimerQuit(void)
+{
+ timer_alive = 0;
+ if ( timer ) {
+ SDL_WaitThread(timer, NULL);
+ timer = NULL;
+ }
+}
+
+int SDL_SYS_StartTimer(void)
+{
+ SDL_SetError("Internal logic error: OS/2 uses threaded timer");
+ return(-1);
+}
+
+void SDL_SYS_StopTimer(void)
+{
+ return;
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,27 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for threading
+#=============================================================================
+
+object_files=SDL_blit.obj SDL_blit_0.obj SDL_blit_1.obj SDL_blit_A.obj SDL_blit_N.obj SDL_bmp.obj SDL_cursor.obj SDL_gamma.obj SDL_pixels.obj SDL_RLEaccel.obj SDL_stretch.obj SDL_surface.obj SDL_video.obj SDL_yuv.obj SDL_yuv_mmx.obj SDL_yuv_sw.obj SDL_os2fslib.obj
+ExtraCFlags=-dUSE_DOSSETPRIORITY
+
+#
+#==============================================================================
+#
+!include ..\..\Watcom.mif
+
+.before
+ set include=$(%os2tk)\h;$(%include);../../include;../;./os2;../events;../hermes;$(%FSLIB);
+
+all : $(object_files)
+
+SDL_os2fslib.obj : .AUTODEPEND
+ wcc386 os2fslib\SDL_os2fslib.c $(cflags)
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst
--- a/src/video/SDL_sysvideo.h Wed Nov 23 07:23:48 2005 +0000
+++ b/src/video/SDL_sysvideo.h Wed Nov 23 07:29:56 2005 +0000
@@ -423,6 +423,9 @@
#ifdef ENABLE_RISCOS
extern VideoBootStrap RISCOS_bootstrap;
#endif
+#ifdef __OS2__
+extern VideoBootStrap OS2FSLib_bootstrap;
+#endif
/* This is the current video device */
extern SDL_VideoDevice *current_video;
--- a/src/video/SDL_video.c Wed Nov 23 07:23:48 2005 +0000
+++ b/src/video/SDL_video.c Wed Nov 23 07:29:56 2005 +0000
@@ -126,6 +126,9 @@
#ifdef ENABLE_RISCOS
&RISCOS_bootstrap,
#endif
+#ifdef __OS2__
+ &OS2FSLib_bootstrap,
+#endif
#ifdef ENABLE_DUMMYVIDEO
&DUMMY_bootstrap,
#endif
@@ -664,7 +667,10 @@
SDL_VideoSurface = NULL; /* In case it's freed by driver */
mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
if ( mode ) { /* Prevent resize events from mode change */
+ /* But not on OS/2 */
+#ifndef __OS2__
SDL_PrivateResize(mode->w, mode->h);
+#endif
/* Sam - If we asked for OpenGL mode, and didn't get it, fail */
if ( is_opengl && !(mode->flags & SDL_OPENGL) ) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/os2fslib/SDL_os2fslib.c Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,2787 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2004 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <time.h>
+
+#include "SDL.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "SDL_sysvideo.h"
+#include "SDL_pixels_c.h"
+#include "SDL_events_c.h"
+
+#include "SDL_os2fslib.h"
+
+static ULONG ulFCFToUse =
+ FCF_TITLEBAR |
+ FCF_SYSMENU |
+ FCF_MINBUTTON |
+ FCF_MAXBUTTON |
+ FCF_NOBYTEALIGN |
+ FCF_SIZEBORDER |
+ FCF_TASKLIST;
+
+static int bMouseCaptured = 0;
+static int bMouseCapturable = 0;
+static HPOINTER hptrGlobalPointer = NULL;
+static HPOINTER hptrCurrentIcon = NULL;
+static int iWindowSizeX = 320;
+static int iWindowSizeY = 200;
+static int bWindowResized = 0;
+
+#pragma pack(1)
+typedef struct BMPINFO
+{
+ BITMAPINFO;
+ RGB clr;
+} BMPINFO, *PBMPINFO;
+#pragma pack()
+
+
+// Backdoors:
+DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF)
+{
+ ulFCFToUse = ulFCF;
+}
+
+// Configuration defines:
+
+// We have to report empty alpha mask, otherwise SDL will select
+// alpha blitters, and this will have unwanted results, as we don't
+// support alpha channel in FSLib yet.
+#define REPORT_EMPTY_ALPHA_MASK
+
+// Experimental: Move every FSLib_BitBlt() call into window message
+// processing function.
+// This may fix dirt left on desktop. Or not.
+//#define BITBLT_IN_WINMESSAGEPROC
+
+// Experimental-2: Use WinLockWindowUpdate() in around bitblts!
+// This is not enabled, because it seems to cause more problems
+// than good.
+//#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
+
+// Use the following to show resized image instead of black stuff
+// even if the surface is resizable.
+//#define RESIZE_EVEN_IF_RESIZABLE
+
+/* The translation table from a VK keysym to a SDL keysym */
+static SDLKey HWScanKeyMap[256];
+static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed);
+static int iShiftIsPressed;
+
+#ifdef BITBLT_IN_WINMESSAGEPROC
+#define WM_UPDATERECTSREQUEST WM_USER+50
+#endif
+
+#ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
+#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
+ { \
+ WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \
+ FSLib_BitBlt(hwnd, buffer, top, left, width, height); \
+ WinLockWindowUpdate(HWND_DESKTOP, NULL); \
+ }
+#else
+#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
+ FSLib_BitBlt(hwnd, buffer, top, left, width, height);
+#endif
+
+/////////////////////////////////////////////////////////////////////
+//
+// SetAccessableWindowPos
+//
+// Same as WinSetWindowPos(), but takes care for the window to be
+// always on the screen, the titlebar will be accessable everytime.
+//
+/////////////////////////////////////////////////////////////////////
+static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind,
+ LONG x, LONG y,
+ LONG cx, LONG cy,
+ ULONG fl)
+{
+ SWP swpDesktop, swp;
+ // Get desktop area
+ WinQueryWindowPos(HWND_DESKTOP, &swpDesktop);
+
+ if ((fl & SWP_MOVE) && (fl & SWP_SIZE))
+ {
+ // If both moving and sizing, then change size and pos now!!
+ if (x+cx>swpDesktop.cx)
+ x = swpDesktop.cx - cx;
+ if (x<0)
+ x = 0;
+ if (y<0)
+ y = 0;
+ if (y+cy>swpDesktop.cy)
+ y = swpDesktop.cy - cy;
+ return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
+ } else
+ if (fl & SWP_MOVE)
+ {
+ // Just moving
+ WinQueryWindowPos(hwnd, &swp);
+ if (x+swp.cx>swpDesktop.cx)
+ x = swpDesktop.cx - swp.cx;
+ if (x<0)
+ x = 0;
+ if (y<0)
+ y = 0;
+ if (y+swp.cy>swpDesktop.cy)
+ y = swpDesktop.cy - swp.cy;
+ return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
+ } else
+ if (fl & SWP_SIZE)
+ {
+ // Just sizing
+ WinQueryWindowPos(hwnd, &swp);
+ x = swp.x;
+ y = swp.y;
+ if (x+cx>swpDesktop.cx)
+ x = swpDesktop.cx - cx;
+ if (x<0)
+ x = 0;
+ if (y<0)
+ y = 0;
+ if (y+cy>swpDesktop.cy)
+ y = swpDesktop.cy - cy;
+ return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE);
+ } else
+ return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+// TranslateKey
+//
+// This creates SDL Keycodes from VK_ and hardware scan codes
+//
+/////////////////////////////////////////////////////////////////////
+static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed)
+{
+ keysym->scancode = (unsigned char) scancode;
+ keysym->mod = KMOD_NONE;
+ keysym->unicode = 0;
+
+ if (iPressed && SDL_TranslateUNICODE)
+ {
+ // TODO:
+ // Implement real unicode conversion!
+ if (chcode)
+ keysym->unicode = chcode;
+ else
+ keysym->unicode = vkey;
+ }
+
+ keysym->sym = HWScanKeyMap[scancode];
+
+ // Now stuffs based on state of shift key(s)!
+ if (vkey == VK_SHIFT)
+ {
+ iShiftIsPressed = iPressed;
+ }
+
+ if ((iShiftIsPressed) && (SDL_TranslateUNICODE))
+ {
+ // Change syms, if Unicode stuff is required
+ // I think it's silly, but it's SDL...
+ switch (keysym->sym)
+ {
+ case SDLK_BACKQUOTE:
+ keysym->sym = '~';
+ break;
+ case SDLK_1:
+ keysym->sym = SDLK_EXCLAIM;
+ break;
+ case SDLK_2:
+ keysym->sym = SDLK_AT;
+ break;
+ case SDLK_3:
+ keysym->sym = SDLK_HASH;
+ break;
+ case SDLK_4:
+ keysym->sym = SDLK_DOLLAR;
+ break;
+ case SDLK_5:
+ keysym->sym = '%';
+ break;
+ case SDLK_6:
+ keysym->sym = SDLK_CARET;
+ break;
+ case SDLK_7:
+ keysym->sym = SDLK_AMPERSAND;
+ break;
+ case SDLK_8:
+ keysym->sym = SDLK_ASTERISK;
+ break;
+ case SDLK_9:
+ keysym->sym = SDLK_LEFTPAREN;
+ break;
+ case SDLK_0:
+ keysym->sym = SDLK_RIGHTPAREN;
+ break;
+ case SDLK_MINUS:
+ keysym->sym = SDLK_UNDERSCORE;
+ break;
+ case SDLK_PLUS:
+ keysym->sym = SDLK_EQUALS;
+ break;
+
+ case SDLK_LEFTBRACKET:
+ keysym->sym = '{';
+ break;
+ case SDLK_RIGHTBRACKET:
+ keysym->sym = '}';
+ break;
+
+ case SDLK_SEMICOLON:
+ keysym->sym = SDLK_COLON;
+ break;
+ case SDLK_QUOTE:
+ keysym->sym = SDLK_QUOTEDBL;
+ break;
+ case SDLK_BACKSLASH:
+ keysym->sym = '|';
+ break;
+
+ case SDLK_COMMA:
+ keysym->sym = SDLK_LESS;
+ break;
+ case SDLK_PERIOD:
+ keysym->sym = SDLK_GREATER;
+ break;
+ case SDLK_SLASH:
+ keysym->sym = SDLK_QUESTION;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return keysym;
+}
+
+#define CONVERTMOUSEPOSITION() \
+ /* We have to inverse the mouse position, because every non-os/2 system */ \
+ /* has a coordinate system where the (0;0) is the top-left corner, */ \
+ /* while on os/2 it's the bottom left corner! */ \
+ if (FSLib_QueryFSMode(hwnd)) \
+ { \
+ /* We're in FS mode! */ \
+ /* In FS mode our window is as big as fullscreen mode, but not necessary as */ \
+ /* big as the source buffer (can be bigger) */ \
+ /* So, limit mouse pos to source buffer size! */ \
+ if (ppts->x<0) ppts->x = 0; \
+ if (ppts->y<0) ppts->y = 0; \
+ if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1; \
+ if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1; \
+ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ \
+ ptl.x = ppts->x; ptl.y = ppts->y; \
+ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); \
+ WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y); \
+ /* Then convert OS/2 position to SDL position */ \
+ ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1; \
+ } else \
+ { \
+ SWP swpClient; \
+ /* We're in windowed mode! */ \
+ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); \
+ /* Convert OS/2 mouse position to SDL position, and also scale it! */ \
+ (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; \
+ (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; \
+ (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y) - 1; \
+ }
+
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// WndProc
+//
+// This is the message processing window procedure for the
+// SDLWindowClass, which is the client window in our application.
+// It handles switching back and away from the app (taking care of
+// going out and back to and from fullscreen mode), sending keystrokes
+// and mouse events to where it has to be sent, etc...
+//
+/////////////////////////////////////////////////////////////////////
+static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+ HPS ps;
+ RECTL rcl;
+ SDL_VideoDevice *pVideo = NULL;
+
+ switch (msg)
+ {
+ case WM_CHAR: // Keypress notification
+#ifdef DEBUG_BUILD
+// printf("WM_CHAR\n"); fflush(stdout);
+#endif
+ pVideo = WinQueryWindowPtr(hwnd, 0);
+ if (pVideo)
+ {
+ /*
+ // We skip repeated keys:
+ if (CHARMSG(&msg)->cRepeat>1)
+ {
+#ifdef DEBUG_BUILD
+// printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout);
+#endif
+ return (MRESULT) TRUE;
+ }
+ */
+
+ // If it's not repeated, then let's see if its pressed or released!
+ if (SHORT1FROMMP(mp1) & KC_KEYUP)
+ {
+ // A key has been released
+ SDL_keysym keysym;
+
+#ifdef DEBUG_BUILD
+// printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
+#endif
+
+ // One problem is with F1, which gets only the keyup message because
+ // it is a system key.
+ // So, when we get keyup message, we simulate keydown too!
+ // UPDATE:
+ // This problem should be solved now, that the accelerator keys are
+ // disabled for this window!
+ /*
+ if (SHORT2FROMMP(mp2)==VK_F1)
+ {
+ SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
+ SHORT1FROMMP(mp2), // Character code
+ CHAR4FROMMP(mp1), // HW Scan code
+ &keysym,0));
+ }*/
+
+ SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
+ SHORT1FROMMP(mp2), // Character code
+ CHAR4FROMMP(mp1), // HW Scan code
+ &keysym,0));
+
+ } else
+ {
+ // A key has been pressed
+ SDL_keysym keysym;
+
+#ifdef DEBUG_BUILD
+// printf("WM_CHAR, keydown, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
+#endif
+ // Check for fastkeys: ALT+HOME to toggle FS mode
+ // ALT+END to close app
+ if ((SHORT1FROMMP(mp1) & KC_ALT) &&
+ (SHORT2FROMMP(mp2) == VK_HOME))
+ {
+#ifdef DEBUG_BUILD
+ printf(" Pressed ALT+HOME!\n"); fflush(stdout);
+#endif
+ // Only switch between fullscreen and back if it's not
+ // a resizable mode!
+ if (
+ (!pVideo->hidden->pSDLSurface) ||
+ ((pVideo->hidden->pSDLSurface)
+ && ((pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE)==0)
+ )
+ )
+ FSLib_ToggleFSMode(hwnd, !FSLib_QueryFSMode(hwnd));
+#ifdef DEBUG_BUILD
+ else
+ printf(" Resizable mode, so discarding ALT+HOME!\n"); fflush(stdout);
+#endif
+ } else
+ if ((SHORT1FROMMP(mp1) & KC_ALT) &&
+ (SHORT2FROMMP(mp2) == VK_END))
+ {
+#ifdef DEBUG_BUILD
+ printf(" Pressed ALT+END!\n"); fflush(stdout);
+#endif
+ // Close window, and get out of loop!
+ // Also send event to SDL application, but we won't
+ // wait for it to be processed!
+ SDL_PrivateQuit();
+ WinPostMsg(hwnd, WM_QUIT, 0, 0);
+ } else
+ {
+
+ SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
+ SHORT1FROMMP(mp2), // Character code
+ CHAR4FROMMP(mp1), // HW Scan code
+ &keysym,1));
+
+ }
+ }
+ }
+ return (MRESULT) TRUE;
+
+ case WM_TRANSLATEACCEL:
+ {
+ PQMSG pqmsg;
+ pqmsg = (PQMSG) mp1;
+ if (mp1)
+ {
+ if (pqmsg->msg == WM_CHAR)
+ {
+ // WM_CHAR message!
+ // Let's filter the ALT keypress and all other acceleration keys!
+ return (MRESULT) FALSE;
+ }
+ }
+ break; // Default processing (pass to parent until frame control)
+ }
+
+ case WM_PAINT: // Window redraw!
+#ifdef DEBUG_BUILD
+ printf("WM_PAINT (0x%x)\n", hwnd); fflush(stdout);
+#endif
+ ps = WinBeginPaint(hwnd,0,&rcl);
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ if (!pVideo->hidden->pSDLSurface)
+ {
+ RECTL rclRect;
+ // So, don't blit now!
+#ifdef DEBUG_BUILD
+ printf("WM_PAINT : Skipping blit while resizing (Pre!)!\n"); fflush(stdout);
+#endif
+ WinQueryWindowRect(hwnd, &rclRect);
+ // Fill with black
+ WinFillRect(ps, &rclRect, CLR_BLACK);
+ } else
+ {
+ if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
+ {
+ int iTop, iLeft, iWidth, iHeight;
+ int iXScaleError, iYScaleError;
+ int iXScaleError2, iYScaleError2;
+ SWP swp;
+
+ // Re-blit the modified area!
+ // For this, we have to calculate the points, scaled!
+ WinQueryWindowPos(hwnd, &swp);
+#ifdef DEBUG_BUILD
+ printf("WM_PAINT : WinSize: %d %d, BufSize: %d %d\n",
+ swp.cx,
+ swp.cy,
+ pVideo->hidden->SrcBufferDesc.uiXResolution,
+ pVideo->hidden->SrcBufferDesc.uiYResolution
+ );
+ fflush(stdout);
+#endif
+
+#ifndef RESIZE_EVEN_IF_RESIZABLE
+ // But only blit if the window is not resizable, or if
+ // the window is resizable and the source buffer size is the
+ // same as the destination buffer size!
+ if ((!pVideo->hidden->pSDLSurface) ||
+ ((pVideo->hidden->pSDLSurface) &&
+ (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
+ ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
+ (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
+ ) &&
+ (!FSLib_QueryFSMode(hwnd))
+ )
+ )
+ {
+ RECTL rclRect;
+ // Resizable surface and in resizing!
+ // So, don't blit now!
+#ifdef DEBUG_BUILD
+ printf("WM_PAINT : Skipping blit while resizing!\n"); fflush(stdout);
+#endif
+ WinQueryWindowRect(hwnd, &rclRect);
+ // Fill with black
+ WinFillRect(ps, &rclRect, CLR_BLACK);
+ } else
+#endif
+ {
+
+ iXScaleError = (pVideo->hidden->SrcBufferDesc.uiXResolution-1) / swp.cx;
+ iYScaleError = (pVideo->hidden->SrcBufferDesc.uiYResolution-1) / swp.cy;
+ if (iXScaleError<0) iXScaleError = 0;
+ if (iYScaleError<0) iYScaleError = 0;
+ iXScaleError2 = (swp.cx-1)/(pVideo->hidden->SrcBufferDesc.uiXResolution);
+ iYScaleError2 = (swp.cy-1)/(pVideo->hidden->SrcBufferDesc.uiYResolution);
+ if (iXScaleError2<0) iXScaleError2 = 0;
+ if (iYScaleError2<0) iYScaleError2 = 0;
+
+ iTop = (swp.cy - rcl.yTop) * pVideo->hidden->SrcBufferDesc.uiYResolution / swp.cy - iYScaleError;
+ iLeft = rcl.xLeft * pVideo->hidden->SrcBufferDesc.uiXResolution / swp.cx - iXScaleError;
+ iWidth = ((rcl.xRight-rcl.xLeft) * pVideo->hidden->SrcBufferDesc.uiXResolution + swp.cx-1)
+ / swp.cx + 2*iXScaleError;
+ iHeight = ((rcl.yTop-rcl.yBottom) * pVideo->hidden->SrcBufferDesc.uiYResolution + swp.cy-1)
+ / swp.cy + 2*iYScaleError;
+
+ iWidth+=iXScaleError2;
+ iHeight+=iYScaleError2;
+
+ if (iTop<0) iTop = 0;
+ if (iLeft<0) iLeft = 0;
+ if (iTop+iHeight>pVideo->hidden->SrcBufferDesc.uiYResolution) iHeight = pVideo->hidden->SrcBufferDesc.uiYResolution-iTop;
+ if (iLeft+iWidth>pVideo->hidden->SrcBufferDesc.uiXResolution) iWidth = pVideo->hidden->SrcBufferDesc.uiXResolution-iLeft;
+
+#ifdef DEBUG_BUILD
+ printf("WM_PAINT : BitBlt: %d %d -> %d %d (Buf %d x %d)\n",
+ iTop, iLeft, iWidth, iHeight,
+ pVideo->hidden->SrcBufferDesc.uiXResolution,
+ pVideo->hidden->SrcBufferDesc.uiYResolution
+ );
+ fflush(stdout);
+#endif
+
+ FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, iTop, iLeft, iWidth, iHeight);
+ }
+
+ DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
+ }
+ }
+ }
+#ifdef DEBUG_BUILD
+ else
+ {
+ printf("WM_PAINT : No pVideo!\n"); fflush(stdout);
+ }
+#endif
+ WinEndPaint(ps);
+#ifdef DEBUG_BUILD
+ printf("WM_PAINT : Done.\n");
+ fflush(stdout);
+#endif
+ return 0;
+
+ case WM_SIZE:
+ {
+#ifdef DEBUG_BUILD
+ printf("WM_SIZE : (%d %d)\n",
+ SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); fflush(stdout);
+#endif
+ iWindowSizeX = SHORT1FROMMP(mp2);
+ iWindowSizeY = SHORT2FROMMP(mp2);
+ bWindowResized = 1;
+
+ // Make sure the window will be redrawn
+ WinInvalidateRegion(hwnd, NULL, TRUE);
+ }
+ break;
+
+ case WM_FSLIBNOTIFICATION:
+#ifdef DEBUG_BUILD
+ printf("WM_FSLIBNOTIFICATION\n"); fflush(stdout);
+#endif
+ if ((int)mp1 == FSLN_TOGGLEFSMODE)
+ {
+ // FS mode changed, reblit image!
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ if (!pVideo->hidden->pSDLSurface)
+ {
+ // Resizable surface and in resizing!
+ // So, don't blit now!
+#ifdef DEBUG_BUILD
+ printf("WM_FSLIBNOTIFICATION : Can not blit if there is no surface, doing nothing.\n"); fflush(stdout);
+#endif
+ } else
+ {
+ if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
+ {
+ if (pVideo->hidden->pSDLSurface)
+ {
+#ifndef RESIZE_EVEN_IF_RESIZABLE
+ SWP swp;
+
+ // But only blit if the window is not resizable, or if
+ // the window is resizable and the source buffer size is the
+ // same as the destination buffer size!
+ WinQueryWindowPos(hwnd, &swp);
+ if ((!pVideo->hidden->pSDLSurface) ||
+ (
+ (pVideo->hidden->pSDLSurface) &&
+ (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
+ ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
+ (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
+ ) &&
+ (!FSLib_QueryFSMode(hwnd))
+ )
+ )
+ {
+ // Resizable surface and in resizing!
+ // So, don't blit now!
+#ifdef DEBUG_BUILD
+ printf("WM_FSLIBNOTIFICATION : Cannot blit while resizing, doing nothing.\n"); fflush(stdout);
+#endif
+ } else
+#endif
+ {
+#ifdef DEBUG_BUILD
+ printf("WM_FSLIBNOTIFICATION : Blitting!\n"); fflush(stdout);
+#endif
+ FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
+ 0, 0,
+ pVideo->hidden->SrcBufferDesc.uiXResolution,
+ pVideo->hidden->SrcBufferDesc.uiYResolution);
+ }
+ }
+#ifdef DEBUG_BUILD
+ else
+ printf("WM_FSLIBNOTIFICATION : No public surface!\n"); fflush(stdout);
+#endif
+
+ DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
+ }
+ }
+ }
+ }
+ return (MPARAM) 1;
+
+ case WM_ACTIVATE:
+#ifdef DEBUG_BUILD
+ printf("WM_ACTIVATE\n"); fflush(stdout);
+#endif
+
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ pVideo->hidden->fInFocus = (int) mp1;
+ if (pVideo->hidden->fInFocus)
+ {
+ // Went into focus
+ if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
+ WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
+ else
+ WinSetPointer(HWND_DESKTOP, NULL);
+
+ if (bMouseCapturable)
+ {
+ // Re-capture the mouse, if we captured it before!
+ WinSetCapture(HWND_DESKTOP, hwnd);
+ bMouseCaptured = 1;
+ {
+ SWP swpClient;
+ POINTL ptl;
+ // Center the mouse to the middle of the window!
+ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
+ ptl.x = 0; ptl.y = 0;
+ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
+ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
+ WinSetPointerPos(HWND_DESKTOP,
+ ptl.x + swpClient.cx/2,
+ ptl.y + swpClient.cy/2);
+ }
+ }
+ } else
+ {
+ // Went out of focus
+ WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
+
+ if (bMouseCaptured)
+ {
+ // Release the mouse
+ WinSetCapture(HWND_DESKTOP, hwnd);
+ bMouseCaptured = 0;
+ }
+ }
+ }
+#ifdef DEBUG_BUILD
+ printf("WM_ACTIVATE done\n"); fflush(stdout);
+#endif
+
+ break;
+
+ case WM_BUTTON1DOWN:
+#ifdef DEBUG_BUILD
+ printf("WM_BUTTON1DOWN\n"); fflush(stdout);
+#endif
+
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ SDL_PrivateMouseButton(SDL_PRESSED,
+ SDL_BUTTON_LEFT,
+ 0, 0); // Don't report mouse movement!
+
+ if (bMouseCapturable)
+ {
+ // We should capture the mouse!
+ if (!bMouseCaptured)
+ {
+ WinSetCapture(HWND_DESKTOP, hwnd);
+ WinSetPointer(HWND_DESKTOP, NULL);
+ bMouseCaptured = 1;
+ {
+ SWP swpClient;
+ POINTL ptl;
+ // Center the mouse to the middle of the window!
+ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
+ ptl.x = 0; ptl.y = 0;
+ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
+ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
+ WinSetPointerPos(HWND_DESKTOP,
+ ptl.x + swpClient.cx/2,
+ ptl.y + swpClient.cy/2);
+ }
+ }
+ }
+ }
+ break;
+ case WM_BUTTON1UP:
+#ifdef DEBUG_BUILD
+ printf("WM_BUTTON1UP\n"); fflush(stdout);
+#endif
+ SDL_PrivateMouseButton(SDL_RELEASED,
+ SDL_BUTTON_LEFT,
+ 0, 0); // Don't report mouse movement!
+ break;
+ case WM_BUTTON2DOWN:
+#ifdef DEBUG_BUILD
+ printf("WM_BUTTON2DOWN\n"); fflush(stdout);
+#endif
+
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ SDL_PrivateMouseButton(SDL_PRESSED,
+ SDL_BUTTON_RIGHT,
+ 0, 0); // Don't report mouse movement!
+
+ if (bMouseCapturable)
+ {
+ // We should capture the mouse!
+ if (!bMouseCaptured)
+ {
+ WinSetCapture(HWND_DESKTOP, hwnd);
+ WinSetPointer(HWND_DESKTOP, NULL);
+ bMouseCaptured = 1;
+ {
+ SWP swpClient;
+ POINTL ptl;
+ // Center the mouse to the middle of the window!
+ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
+ ptl.x = 0; ptl.y = 0;
+ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
+ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
+ WinSetPointerPos(HWND_DESKTOP,
+ ptl.x + swpClient.cx/2,
+ ptl.y + swpClient.cy/2);
+ }
+ }
+ }
+
+ }
+ break;
+ case WM_BUTTON2UP:
+#ifdef DEBUG_BUILD
+ printf("WM_BUTTON2UP\n"); fflush(stdout);
+#endif
+ SDL_PrivateMouseButton(SDL_RELEASED,
+ SDL_BUTTON_RIGHT,
+ 0, 0); // Don't report mouse movement!
+ break;
+ case WM_BUTTON3DOWN:
+#ifdef DEBUG_BUILD
+ printf("WM_BUTTON3DOWN\n"); fflush(stdout);
+#endif
+
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ SDL_PrivateMouseButton(SDL_PRESSED,
+ SDL_BUTTON_MIDDLE,
+ 0, 0); // Don't report mouse movement!
+
+ if (bMouseCapturable)
+ {
+ // We should capture the mouse!
+ if (!bMouseCaptured)
+ {
+ WinSetCapture(HWND_DESKTOP, hwnd);
+ WinSetPointer(HWND_DESKTOP, NULL);
+ bMouseCaptured = 1;
+ {
+ SWP swpClient;
+ POINTL ptl;
+ // Center the mouse to the middle of the window!
+ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
+ ptl.x = 0; ptl.y = 0;
+ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
+ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
+ WinSetPointerPos(HWND_DESKTOP,
+ ptl.x + swpClient.cx/2,
+ ptl.y + swpClient.cy/2);
+ }
+ }
+ }
+ }
+ break;
+ case WM_BUTTON3UP:
+#ifdef DEBUG_BUILD
+ printf("WM_BUTTON3UP\n"); fflush(stdout);
+#endif
+ SDL_PrivateMouseButton(SDL_RELEASED,
+ SDL_BUTTON_MIDDLE,
+ 0, 0); // Don't report mouse movement!
+ break;
+ case WM_MOUSEMOVE:
+#ifdef DEBUG_BUILD
+// printf("WM_MOUSEMOVE\n"); fflush(stdout);
+#endif
+
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ if (pVideo->hidden->iSkipWMMOUSEMOVE)
+ {
+ pVideo->hidden->iSkipWMMOUSEMOVE--;
+ } else
+ {
+ POINTS *ppts = (POINTS *) (&mp1);
+ POINTL ptl;
+
+ CONVERTMOUSEPOSITION();
+
+ if (bMouseCaptured)
+ {
+ SWP swpClient;
+ // Send relative mouse position, and re-center the mouse
+ // Reposition the mouse to the center of the screen/window
+ SDL_PrivateMouseMotion(0, // Buttons not changed
+ 1, // Relative position
+ ppts->x - (pVideo->hidden->SrcBufferDesc.uiXResolution/2),
+ ppts->y+1 - (pVideo->hidden->SrcBufferDesc.uiYResolution/2));
+
+ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
+ ptl.x = 0; ptl.y = 0;
+ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
+ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
+ // Center the mouse to the middle of the window!
+ WinSetPointerPos(HWND_DESKTOP,
+ ptl.x + swpClient.cx/2,
+ ptl.y + swpClient.cy/2);
+ } else
+ {
+ // Send absolute mouse position
+ SDL_PrivateMouseMotion(0, // Buttons not changed
+ 0, // Absolute position
+ ppts->x,
+ ppts->y);
+ }
+ }
+ if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
+ {
+#ifdef DEBUG_BUILD
+// printf("WM_MOUSEMOVE : ptr = %p\n", hptrGlobalPointer); fflush(stdout);
+#endif
+
+ if (hptrGlobalPointer)
+ WinSetPointer(HWND_DESKTOP, hptrGlobalPointer);
+ else
+ WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
+ }
+ else
+ {
+ WinSetPointer(HWND_DESKTOP, NULL);
+ }
+ }
+#ifdef DEBUG_BUILD
+// printf("WM_MOUSEMOVE done\n"); fflush(stdout);
+#endif
+
+ return (MRESULT) FALSE;
+ case WM_CLOSE: // Window close
+#ifdef DEBUG_BUILD
+ printf("WM_CLOSE\n"); fflush(stdout);
+#endif
+
+ pVideo = FSLib_GetUserParm(hwnd);
+ if (pVideo)
+ {
+ // Send Quit message to the SDL application!
+ SDL_PrivateQuit();
+ return 0;
+ }
+ break;
+
+#ifdef BITBLT_IN_WINMESSAGEPROC
+ case WM_UPDATERECTSREQUEST:
+ pVideo = FSLib_GetUserParm(hwnd);
+ if ((pVideo) && (pVideo->hidden->pSDLSurface))
+ {
+ if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
+ {
+ int numrects;
+ SDL_Rect *rects;
+ int i;
+ SWP swp;
+
+ numrects = (int) mp1;
+ rects = (SDL_Rect *) mp2;
+
+ WinQueryWindowPos(hwnd, &swp);
+#ifndef RESIZE_EVEN_IF_RESIZABLE
+ if ((!pVideo->hidden->pSDLSurface) ||
+ (
+ (pVideo->hidden->pSDLSurface) &&
+ (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
+ ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
+ (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
+ ) &&
+ (!FSLib_QueryFSMode(hwnd))
+ )
+ )
+ {
+ // Resizable surface and in resizing!
+ // So, don't blit now!
+#ifdef DEBUG_BUILD
+ printf("[WM_UPDATERECTSREQUEST] : Skipping blit while resizing!\n"); fflush(stdout);
+#endif
+ } else
+#endif
+ {
+#ifdef DEBUG_BUILD
+ printf("[WM_UPDATERECTSREQUEST] : Blitting!\n"); fflush(stdout);
+#endif
+
+ // Blit the changed areas
+ for (i=0; i<numrects; i++)
+ FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
+ rects[i].y, rects[i].x, rects[i].w, rects[i].h);
+ }
+ DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
+ }
+ }
+ return 0;
+#endif
+
+ default:
+#ifdef DEBUG_BUILD
+ printf("Unhandled: %x\n", msg); fflush(stdout);
+#endif
+
+ break;
+ }
+ // Run the default window procedure for unhandled stuffs
+ return WinDefWindowProc(hwnd, msg, mp1, mp2);
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+// PMThreadFunc
+//
+// This function implements the PM-Thread, which initializes the
+// application window itself, the DIVE, and start message processing.
+//
+/////////////////////////////////////////////////////////////////////
+int iNumOfPMThreadInstances = 0; // Global!
+static void PMThreadFunc(void *pParm)
+{
+ SDL_VideoDevice *pVideo = pParm;
+ HAB hab;
+ HMQ hmq;
+ QMSG msg;
+ ULONG fcf;
+
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : Starting\n"); fflush(stdout);
+#endif
+
+ iNumOfPMThreadInstances++;
+
+ // Initialize PM, create a message queue.
+
+ hab=WinInitialize(0);
+ hmq=WinCreateMsgQueue(hab,0);
+ if (hmq==0)
+ {
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : Could not create message queue!\n");
+ printf(" It might be that the application using SDL is not a PM app!\n");
+ fflush(stdout);
+#endif
+ pVideo->hidden->iPMThreadStatus = 2;
+ } else
+ {
+ int rc;
+ RECTL rectl;
+
+ fcf = ulFCFToUse; // Get from global setting
+
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : FSLib_CreateWindow()!\n");
+ fflush(stdout);
+#endif
+
+ rc = FSLib_CreateWindow(HWND_DESKTOP, 0, &fcf,
+ "SDL Application",
+ NULLHANDLE, 0,
+ &(pVideo->hidden->SrcBufferDesc),
+ WndProc,
+ &(pVideo->hidden->hwndClient),
+ &(pVideo->hidden->hwndFrame));
+
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : FSLib_CreateWindow() rc = %d\n", rc);
+ fflush(stdout);
+#endif
+
+ if (!rc)
+ {
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : Could not create FSLib window!\n");
+ fflush(stdout);
+#endif
+ pVideo->hidden->iPMThreadStatus = 3;
+ } else
+ {
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : FSLib_AddUserParm()!\n");
+ fflush(stdout);
+#endif
+
+ // Store pVideo pointer in window data for client window, so
+ // it will know the instance to which it belongs to.
+ FSLib_AddUserParm(pVideo->hidden->hwndClient, pVideo);
+
+ // Now set default image width height and fourcc!
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : SetWindowPos()!\n");
+ fflush(stdout);
+#endif
+
+ // Set the position and size of the main window,
+ // and make it visible!
+ // Calculate frame window size from client window size
+ rectl.xLeft = 0;
+ rectl.yBottom = 0;
+ rectl.xRight = pVideo->hidden->SrcBufferDesc.uiXResolution; // Noninclusive
+ rectl.yTop = pVideo->hidden->SrcBufferDesc.uiYResolution; // Noninclusive
+ WinCalcFrameRect(pVideo->hidden->hwndFrame, &rectl, FALSE);
+
+ SetAccessableWindowPos(pVideo->hidden->hwndFrame,
+ HWND_TOP,
+ (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - (rectl.xRight-rectl.xLeft)) / 2,
+ (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - (rectl.yTop-rectl.yBottom)) / 2,
+ (rectl.xRight-rectl.xLeft),
+ (rectl.yTop-rectl.yBottom),
+ SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE);
+
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : Entering message loop\n"); fflush(stdout);
+#endif
+ pVideo->hidden->iPMThreadStatus = 1;
+
+ while (WinGetMsg(hab, (PQMSG)&msg, 0, 0, 0))
+ WinDispatchMsg(hab, (PQMSG) &msg);
+
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : Leaving message loop\n"); fflush(stdout);
+#endif
+ // We should release the captured the mouse!
+ if (bMouseCaptured)
+ {
+ WinSetCapture(HWND_DESKTOP, NULLHANDLE);
+ bMouseCaptured = 0;
+ }
+ // Destroy our window
+ WinDestroyWindow(pVideo->hidden->hwndFrame); pVideo->hidden->hwndFrame=NULL;
+ // Show pointer to make sure it will not be left hidden.
+ WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
+ WinShowPointer(HWND_DESKTOP, TRUE);
+ }
+ // Uninitialize PM
+ WinDestroyMsgQueue(hmq);
+ // All done!
+ pVideo->hidden->iPMThreadStatus = 0;
+ }
+ WinTerminate(hab);
+ /* Commented out, should not be needed anymore, because we send it
+ from WM_CLOSE.
+ // Notify SDL that it should really die now...
+ SDL_PrivateQuit(); SDL_PrivateQuit(); SDL_PrivateQuit(); //... :))
+ */
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : End, status is %d!\n", pVideo->hidden->iPMThreadStatus); fflush(stdout);
+#endif
+
+ iNumOfPMThreadInstances--;
+
+ // HACK to prevent zombie and hanging SDL applications, which does not take
+ // care of closing the window for some reason:
+ // There are some apps which do not process messages, so do a lot of things
+ // without noticing that the application should close. To close these,
+ // I've thought about the following:
+ // If the window is closed (the execution came here), I wait a bit to
+ // give time to the app to finish its execution. If it does not, I kill it
+ // using DosExit(). Brute force, but should work.
+ if (pVideo->hidden->iPMThreadStatus==0)
+ {
+ DosSleep(5000); // Wait 5 secs
+ // If a new PM thread has been spawned (reinitializing video mode), then all right.
+ // Otherwise, we have a problem, the app doesn't want to stop. Kill!
+ if (iNumOfPMThreadInstances==0)
+ {
+#ifdef DEBUG_BUILD
+ printf("[PMThreadFunc] : It seems that the application haven't terminated itself\n"); fflush(stdout);
+ printf("[PMThreadFunc] : in the last 5 seconds, so we go berserk.\n"); fflush(stdout);
+ printf("[PMThreadFunc] : Brute force mode. :) Killing process! Dieeeee...\n"); fflush(stdout);
+#endif
+ DosExit(EXIT_PROCESS, -1);
+ }
+ }
+ _endthread();
+}
+
+struct WMcursor
+{
+ HBITMAP hbm;
+ HPOINTER hptr;
+ char *pchData;
+};
+
+/* Free a window manager cursor */
+void os2fslib_FreeWMCursor(_THIS, WMcursor *cursor)
+{
+ if (cursor)
+ {
+ GpiDeleteBitmap(cursor->hbm);
+ WinDestroyPointer(cursor->hptr);
+ free(cursor->pchData);
+ free(cursor);
+ }
+}
+
+/* Local functions to convert the SDL cursor mask into OS/2 format */
+static void memnot(Uint8 *dst, Uint8 *src, int len)
+{
+ while ( len-- > 0 )
+ *dst++ = ~*src++;
+}
+static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
+{
+ while ( len-- > 0 )
+ *dst++ = (*src1++)^(*src2++);
+}
+
+/* Create a black/white window manager cursor */
+WMcursor *os2fslib_CreateWMCursor_Win(_THIS, Uint8 *data, Uint8 *mask,
+ int w, int h, int hot_x, int hot_y)
+{
+ HPOINTER hptr;
+ HBITMAP hbm;
+ BITMAPINFOHEADER bmih;
+ BMPINFO bmi;
+ HPS hps;
+ char *pchTemp;
+ char *xptr, *aptr;
+ int maxx, maxy;
+ int i, run, pad;
+ WMcursor *pResult;
+
+ maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXPOINTER);
+ maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER);
+
+ // Check for max size!
+ if ((w>maxx) || (h>maxy))
+ return (WMcursor *) NULL;
+
+ pResult = (WMcursor *) malloc(sizeof(WMcursor));
+ if (!pResult) return (WMcursor *) NULL;
+
+ pchTemp = (char *) malloc((maxx + 7)/8 * maxy*2);
+ if (!pchTemp)
+ {
+ free(pResult);
+ return (WMcursor *) NULL;
+ }
+
+ memset(pchTemp, 0, (maxx + 7)/8 * maxy*2);
+
+ hps = WinGetPS(_this->hidden->hwndClient);
+
+ bmi.cbFix = sizeof(BITMAPINFOHEADER);
+ bmi.cx = maxx;
+ bmi.cy = 2*maxy;
+ bmi.cPlanes = 1;
+ bmi.cBitCount = 1;
+ bmi.argbColor[0].bBlue = 0x00;
+ bmi.argbColor[0].bGreen = 0x00;
+ bmi.argbColor[0].bRed = 0x00;
+ bmi.argbColor[1].bBlue = 0x00;
+ bmi.argbColor[1].bGreen = 0x00;
+ bmi.argbColor[1].bRed = 0xff;
+
+ memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
+ bmih.cbFix = sizeof(BITMAPINFOHEADER);
+ bmih.cx = maxx;
+ bmih.cy = 2*maxy;
+ bmih.cPlanes = 1;
+ bmih.cBitCount = 1;
+
+ run = (w+7)/8;
+ pad = (maxx+7)/8 - run;
+
+ for (i=0; i<h; i++)
+ {
+ xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
+ aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
+ memxor(xptr, data, mask, run);
+ xptr += run;
+ data += run;
+ memnot(aptr, mask, run);
+ mask += run;
+ aptr += run;
+ memset(xptr, 0, pad);
+ xptr += pad;
+ memset(aptr, ~0, pad);
+ aptr += pad;
+ }
+ pad += run;
+ for (i=h ; i<maxy; i++ )
+ {
+ xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
+ aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
+
+ memset(xptr, 0, (maxx+7)/8);
+ xptr += (maxx+7)/8;
+ memset(aptr, ~0, (maxx+7)/8);
+ aptr += (maxx+7)/8;
+ }
+
+ hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
+ hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, hot_x, maxy - hot_y - 1);
+
+#ifdef DEBUG_BUILD
+ printf("HotSpot : %d ; %d\n", hot_x, hot_y);
+ printf("HPS returned : %x\n", (ULONG)hps);
+ printf("HBITMAP returned : %x\n", (ULONG)hbm);
+ printf("HPOINTER returned: %x\n", (ULONG)hptr);
+#endif
+
+ WinReleasePS(hps);
+
+#ifdef DEBUG_BUILD
+ printf("[CreateWMCursor] : ptr = %p\n", hptr); fflush(stdout);
+#endif
+
+ pResult->hptr = hptr;
+ pResult->hbm = hbm;
+ pResult->pchData = pchTemp;
+
+#ifdef DEBUG_BUILD
+ printf("[CreateWMCursor] : ptr = %p return.\n", hptr); fflush(stdout);
+#endif
+
+ return (WMcursor *) pResult;
+}
+
+WMcursor *os2fslib_CreateWMCursor_FS(_THIS, Uint8 *data, Uint8 *mask,
+ int w, int h, int hot_x, int hot_y)
+{
+#ifdef DEBUG_BUILD
+ printf("[CreateWMCursor_FS] : returning pointer NULL\n"); fflush(stdout);
+#endif
+
+ // In FS mode we'll use software cursor
+ return (WMcursor *) NULL;
+}
+
+/* Show the specified cursor, or hide if cursor is NULL */
+int os2fslib_ShowWMCursor(_THIS, WMcursor *cursor)
+{
+#ifdef DEBUG_BUILD
+ printf("[ShowWMCursor] : ptr = %p\n", cursor); fflush(stdout);
+#endif
+
+ if (cursor)
+ {
+ WinSetPointer(HWND_DESKTOP, cursor->hptr);
+ hptrGlobalPointer = cursor->hptr;
+ _this->hidden->iMouseVisible = 1;
+ }
+ else
+ {
+ WinSetPointer(HWND_DESKTOP, FALSE);
+ hptrGlobalPointer = NULL;
+ _this->hidden->iMouseVisible = 0;
+ }
+
+#ifdef DEBUG_BUILD
+ printf("[ShowWMCursor] : ptr = %p, DONE\n", cursor); fflush(stdout);
+#endif
+
+ return 1;
+}
+
+/* Warp the window manager cursor to (x,y)
+ If NULL, a mouse motion event is posted internally.
+ */
+void os2fslib_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
+{
+ LONG lx, ly;
+ SWP swpClient;
+ POINTL ptlPoints;
+ WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
+ ptlPoints.x = swpClient.x;
+ ptlPoints.y = swpClient.y;
+ WinMapWindowPoints(_this->hidden->hwndFrame, HWND_DESKTOP, &ptlPoints, 1);
+ lx = ptlPoints.x + (x*swpClient.cx) / _this->hidden->SrcBufferDesc.uiXResolution;
+ ly = ptlPoints.y + swpClient.cy - ((y*swpClient.cy) / _this->hidden->SrcBufferDesc.uiYResolution) - 1;
+
+ SDL_PrivateMouseMotion(0, // Buttons not changed
+ 0, // Absolute position
+ x,
+ y);
+
+ WinSetPointerPos(HWND_DESKTOP, lx, ly);
+
+}
+
+/* If not NULL, this is called when a mouse motion event occurs */
+void os2fslib_MoveWMCursor(_THIS, int x, int y)
+{
+ /*
+ SDL_Rect rect;
+
+#ifdef DEBUG_BUILD
+ printf("[MoveWMCursor] : at %d ; %d\n", x, y); fflush(stdout);
+#endif
+
+ rect.x = x;
+ rect.y = y;
+ rect.w = 32;
+ rect.h = 32;
+ os2fslib_UpdateRects(_this, 1, &rect);
+ // TODO!
+ */
+}
+
+/* Determine whether the mouse should be in relative mode or not.
+ This function is called when the input grab state or cursor
+ visibility state changes.
+ If the cursor is not visible, and the input is grabbed, the
+ driver can place the mouse in relative mode, which may result
+ in higher accuracy sampling of the pointer motion.
+ */
+void os2fslib_CheckMouseMode(_THIS)
+{
+}
+
+static void os2fslib_PumpEvents(_THIS)
+{
+ // Notify SDL that if window has been resized!
+ if (
+ (_this->hidden->pSDLSurface) &&
+ (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
+ (
+ (_this->hidden->SrcBufferDesc.uiXResolution!=iWindowSizeX) ||
+ (_this->hidden->SrcBufferDesc.uiYResolution!=iWindowSizeY)
+ ) &&
+ (iWindowSizeX>0) &&
+ (iWindowSizeY>0)
+ )
+ {
+ static time_t prev_time;
+ time_t curr_time;
+
+ curr_time = time(NULL);
+ if ((difftime(curr_time, prev_time)>=0.25) ||
+ (bWindowResized))
+ {
+ // Make sure we won't flood the event queue with resize events,
+ // only send them at 250 msecs!
+ // (or when the window is resized)
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_PumpEvents] : Calling PrivateResize (%d %d).\n",
+ iWindowSizeX, iWindowSizeY);
+ fflush(stdout);
+#endif
+ // Tell SDL the new size
+ SDL_PrivateResize(iWindowSizeX, iWindowSizeY);
+ prev_time = curr_time;
+ bWindowResized = 0;
+ }
+ }
+}
+
+/* We don't actually allow hardware surfaces other than the main one */
+static int os2fslib_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+ return(-1);
+}
+static void os2fslib_FreeHWSurface(_THIS, SDL_Surface *surface)
+{
+ return;
+}
+
+/* We need to wait for vertical retrace on page flipped displays */
+static int os2fslib_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+ return(0);
+}
+
+static void os2fslib_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+ return;
+}
+
+static int os2fslib_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
+{
+ printf("[os2fslib_SetColors] : TODO!\n"); fflush(stdout);
+ // TODO: Implement paletted modes
+ return(1);
+}
+
+static void os2fslib_DestroyIcon(HWND hwndFrame)
+{
+ if (hptrCurrentIcon)
+ {
+ WinDestroyPointer(hptrCurrentIcon);
+ hptrCurrentIcon = NULL;
+
+ WinSendMsg(hwndFrame,
+ WM_SETICON,
+ NULL,
+ NULL);
+ }
+
+}
+
+/* Set the window icon image */
+void os2fslib_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
+{
+ HWND hwndFrame;
+ SDL_Surface *icon_rgb;
+ HPOINTER hptrIcon;
+ HBITMAP hbm;
+ BITMAPINFOHEADER bmih;
+ BMPINFO bmi;
+ HPS hps;
+ char *pchTemp;
+ char *pptr, *mptr, *dptr, *dmptr;
+ int maxx, maxy, w, h, x, y;
+ SDL_Rect bounds;
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetIcon] : Creating and setting new icon\n"); fflush(stdout);
+#endif
+
+ hwndFrame = WinQueryWindow(_this->hidden->hwndClient, QW_PARENT);
+
+ // Make sure the old icon resource will be free'd!
+ os2fslib_DestroyIcon(hwndFrame);
+
+ if ((!icon) || (!mask))
+ return;
+
+ w = icon->w;
+ h = icon->h;
+
+ maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
+ maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
+
+ // Check for max size!
+ if ((w>maxx) || (h>maxy))
+ return;
+
+ pchTemp = (char *) malloc(w * h*2 * 4);
+ if (!pchTemp)
+ return;
+
+ memset(pchTemp, 0, w * h*2 * 4);
+
+ // Convert surface to RGB, if it's not RGB yet!
+ icon_rgb = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
+ 32, 0, 0, 0, 0);
+ if ( icon_rgb == NULL )
+ {
+ free(pchTemp);
+ return;
+ }
+ bounds.x = 0;
+ bounds.y = 0;
+ bounds.w = icon->w;
+ bounds.h = icon->h;
+ if ( SDL_LowerBlit(icon, &bounds, icon_rgb, &bounds) < 0 )
+ {
+ SDL_FreeSurface(icon_rgb);
+ free(pchTemp);
+ return;
+ }
+
+ /* Copy pixels upside-down from RGB surface into BMP, masked with the icon mask */
+
+ // Pixels
+ pptr = (char *) (icon_rgb->pixels);
+ // Mask
+ mptr = mask;
+
+ for (y=0; y<h; y++)
+ {
+ unsigned char uchMaskByte;
+
+ // Destination
+ dptr = pchTemp + w*4 * (h-y-1);
+ // Destination mask
+ dmptr = pchTemp + w*h*4 + w*4 * (h-y-1);
+
+ for (x=0; x<w; x++)
+ {
+ if (x%8==0)
+ {
+ uchMaskByte = (unsigned char) (*mptr);
+ mptr++;
+ } else
+ uchMaskByte <<= 1;
+
+ if (uchMaskByte & 0x80)
+ {
+ // Copy RGB
+ *dptr++ = *pptr++;
+ *dptr++ = *pptr++;
+ *dptr++ = *pptr++;
+ *dptr++ = *pptr++;
+
+ *dmptr++ = 0;
+ *dmptr++ = 0;
+ *dmptr++ = 0;
+ *dmptr++ = 0;
+ } else
+ {
+ // Set pixels to fully transparent
+ *dptr++ = 0; pptr++;
+ *dptr++ = 0; pptr++;
+ *dptr++ = 0; pptr++;
+ *dptr++ = 0; pptr++;
+
+ *dmptr++ = 255;
+ *dmptr++ = 255;
+ *dmptr++ = 255;
+ *dmptr++ = 255;
+ }
+ }
+ }
+
+ // There is no more need for the RGB surface
+ SDL_FreeSurface(icon_rgb);
+
+ hps = WinGetPS(_this->hidden->hwndClient);
+
+ bmi.cbFix = sizeof(BITMAPINFOHEADER);
+ bmi.cx = w;
+ bmi.cy = 2*h;
+ bmi.cPlanes = 1;
+ bmi.cBitCount = 32;
+
+ memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
+ bmih.cbFix = sizeof(BITMAPINFOHEADER);
+ bmih.cx = w;
+ bmih.cy = 2*h;
+ bmih.cPlanes = 1;
+ bmih.cBitCount = 32;
+
+ hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
+ hptrIcon = WinCreatePointer(HWND_DESKTOP, hbm, FALSE, 0, 0);
+
+ WinReleasePS(hps);
+
+ // Free pixel array
+ free(pchTemp);
+
+ // Change icon in frame window
+ WinSendMsg(hwndFrame,
+ WM_SETICON,
+ (MPARAM) hptrIcon,
+ NULL);
+
+ /*
+ // Change icon in switchlist
+ // Seems like it's not needed, the WM_SETICON already does it.
+ {
+ PID pidFrame;
+ HSWITCH hswitchFrame;
+ SWCNTRL swctl;
+
+ WinQueryWindowProcess(hwndFrame, &pidFrame, NULL);
+ hswitchFrame = WinQuerySwitchHandle(hwndFrame, pidFrame);
+ WinQuerySwitchEntry(hswitchFrame, &swctl);
+
+ swctl.hwndIcon = hptrIcon;
+
+ WinChangeSwitchEntry(hswitchFrame, &swctl);
+ }
+ */
+
+ // Store icon handle in global variable
+ hptrCurrentIcon = hptrIcon;
+}
+
+// ------------------------ REAL FUNCTIONS -----------------
+
+
+static void os2fslib_SetCursorManagementFunctions(_THIS, int iForWindowedMode)
+{
+ if (iForWindowedMode)
+ {
+ _this->FreeWMCursor = os2fslib_FreeWMCursor;
+ _this->CreateWMCursor = os2fslib_CreateWMCursor_Win;
+ _this->ShowWMCursor = os2fslib_ShowWMCursor;
+ _this->WarpWMCursor = os2fslib_WarpWMCursor;
+ _this->MoveWMCursor = os2fslib_MoveWMCursor;
+ _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
+ } else
+ {
+ // We'll have software mouse cursor in FS mode!
+ _this->FreeWMCursor = os2fslib_FreeWMCursor;
+ _this->CreateWMCursor = os2fslib_CreateWMCursor_FS;
+ _this->ShowWMCursor = os2fslib_ShowWMCursor;
+ _this->WarpWMCursor = os2fslib_WarpWMCursor;
+ _this->MoveWMCursor = os2fslib_MoveWMCursor;
+ _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
+ }
+}
+
+static void os2fslib_InitOSKeymap(_THIS)
+{
+ int i;
+
+ iShiftIsPressed = 0;
+
+ /* Map the VK and CH keysyms */
+ for ( i=0; i<=255; ++i )
+ HWScanKeyMap[i] = SDLK_UNKNOWN;
+
+ // First line of keyboard:
+ HWScanKeyMap[0x1] = SDLK_ESCAPE;
+ HWScanKeyMap[0x3b] = SDLK_F1;
+ HWScanKeyMap[0x3c] = SDLK_F2;
+ HWScanKeyMap[0x3d] = SDLK_F3;
+ HWScanKeyMap[0x3e] = SDLK_F4;
+ HWScanKeyMap[0x3f] = SDLK_F5;
+ HWScanKeyMap[0x40] = SDLK_F6;
+ HWScanKeyMap[0x41] = SDLK_F7;
+ HWScanKeyMap[0x42] = SDLK_F8;
+ HWScanKeyMap[0x43] = SDLK_F9;
+ HWScanKeyMap[0x44] = SDLK_F10;
+ HWScanKeyMap[0x57] = SDLK_F11;
+ HWScanKeyMap[0x58] = SDLK_F12;
+ HWScanKeyMap[0x5d] = SDLK_PRINT;
+ HWScanKeyMap[0x46] = SDLK_SCROLLOCK;
+ HWScanKeyMap[0x5f] = SDLK_PAUSE;
+
+ // Second line of keyboard:
+ HWScanKeyMap[0x29] = SDLK_BACKQUOTE;
+ HWScanKeyMap[0x2] = SDLK_1;
+ HWScanKeyMap[0x3] = SDLK_2;
+ HWScanKeyMap[0x4] = SDLK_3;
+ HWScanKeyMap[0x5] = SDLK_4;
+ HWScanKeyMap[0x6] = SDLK_5;
+ HWScanKeyMap[0x7] = SDLK_6;
+ HWScanKeyMap[0x8] = SDLK_7;
+ HWScanKeyMap[0x9] = SDLK_8;
+ HWScanKeyMap[0xa] = SDLK_9;
+ HWScanKeyMap[0xb] = SDLK_0;
+ HWScanKeyMap[0xc] = SDLK_MINUS;
+ HWScanKeyMap[0xd] = SDLK_EQUALS;
+ HWScanKeyMap[0xe] = SDLK_BACKSPACE;
+ HWScanKeyMap[0x68] = SDLK_INSERT;
+ HWScanKeyMap[0x60] = SDLK_HOME;
+ HWScanKeyMap[0x62] = SDLK_PAGEUP;
+ HWScanKeyMap[0x45] = SDLK_NUMLOCK;
+ HWScanKeyMap[0x5c] = SDLK_KP_DIVIDE;
+ HWScanKeyMap[0x37] = SDLK_KP_MULTIPLY;
+ HWScanKeyMap[0x4a] = SDLK_KP_MINUS;
+
+ // Third line of keyboard:
+ HWScanKeyMap[0xf] = SDLK_TAB;
+ HWScanKeyMap[0x10] = SDLK_q;
+ HWScanKeyMap[0x11] = SDLK_w;
+ HWScanKeyMap[0x12] = SDLK_e;
+ HWScanKeyMap[0x13] = SDLK_r;
+ HWScanKeyMap[0x14] = SDLK_t;
+ HWScanKeyMap[0x15] = SDLK_y;
+ HWScanKeyMap[0x16] = SDLK_u;
+ HWScanKeyMap[0x17] = SDLK_i;
+ HWScanKeyMap[0x18] = SDLK_o;
+ HWScanKeyMap[0x19] = SDLK_p;
+ HWScanKeyMap[0x1a] = SDLK_LEFTBRACKET;
+ HWScanKeyMap[0x1b] = SDLK_RIGHTBRACKET;
+ HWScanKeyMap[0x1c] = SDLK_RETURN;
+ HWScanKeyMap[0x69] = SDLK_DELETE;
+ HWScanKeyMap[0x65] = SDLK_END;
+ HWScanKeyMap[0x67] = SDLK_PAGEDOWN;
+ HWScanKeyMap[0x47] = SDLK_KP7;
+ HWScanKeyMap[0x48] = SDLK_KP8;
+ HWScanKeyMap[0x49] = SDLK_KP9;
+ HWScanKeyMap[0x4e] = SDLK_KP_PLUS;
+
+ // Fourth line of keyboard:
+ HWScanKeyMap[0x3a] = SDLK_CAPSLOCK;
+ HWScanKeyMap[0x1e] = SDLK_a;
+ HWScanKeyMap[0x1f] = SDLK_s;
+ HWScanKeyMap[0x20] = SDLK_d;
+ HWScanKeyMap[0x21] = SDLK_f;
+ HWScanKeyMap[0x22] = SDLK_g;
+ HWScanKeyMap[0x23] = SDLK_h;
+ HWScanKeyMap[0x24] = SDLK_j;
+ HWScanKeyMap[0x25] = SDLK_k;
+ HWScanKeyMap[0x26] = SDLK_l;
+ HWScanKeyMap[0x27] = SDLK_SEMICOLON;
+ HWScanKeyMap[0x28] = SDLK_QUOTE;
+ HWScanKeyMap[0x2b] = SDLK_BACKSLASH;
+ HWScanKeyMap[0x4b] = SDLK_KP4;
+ HWScanKeyMap[0x4c] = SDLK_KP5;
+ HWScanKeyMap[0x4d] = SDLK_KP6;
+
+ // Fifth line of keyboard:
+ HWScanKeyMap[0x2a] = SDLK_LSHIFT;
+ HWScanKeyMap[0x56] = SDLK_WORLD_1; // Code 161, letter i' on hungarian keyboard
+ HWScanKeyMap[0x2c] = SDLK_z;
+ HWScanKeyMap[0x2d] = SDLK_x;
+ HWScanKeyMap[0x2e] = SDLK_c;
+ HWScanKeyMap[0x2f] = SDLK_v;
+ HWScanKeyMap[0x30] = SDLK_b;
+ HWScanKeyMap[0x31] = SDLK_n;
+ HWScanKeyMap[0x32] = SDLK_m;
+ HWScanKeyMap[0x33] = SDLK_COMMA;
+ HWScanKeyMap[0x34] = SDLK_PERIOD;
+ HWScanKeyMap[0x35] = SDLK_SLASH;
+ HWScanKeyMap[0x36] = SDLK_RSHIFT;
+ HWScanKeyMap[0x61] = SDLK_UP;
+ HWScanKeyMap[0x4f] = SDLK_KP1;
+ HWScanKeyMap[0x50] = SDLK_KP2;
+ HWScanKeyMap[0x51] = SDLK_KP3;
+ HWScanKeyMap[0x5a] = SDLK_KP_ENTER;
+
+ // Sixth line of keyboard:
+ HWScanKeyMap[0x1d] = SDLK_LCTRL;
+ HWScanKeyMap[0x7e] = SDLK_LSUPER; // Windows key
+ HWScanKeyMap[0x38] = SDLK_LALT;
+ HWScanKeyMap[0x39] = SDLK_SPACE;
+ HWScanKeyMap[0x5e] = SDLK_RALT;// Actually, altgr on my keyboard...
+ HWScanKeyMap[0x7f] = SDLK_RSUPER;
+ HWScanKeyMap[0x7c] = SDLK_MENU;
+ HWScanKeyMap[0x5b] = SDLK_RCTRL;
+ HWScanKeyMap[0x63] = SDLK_LEFT;
+ HWScanKeyMap[0x66] = SDLK_DOWN;
+ HWScanKeyMap[0x64] = SDLK_RIGHT;
+ HWScanKeyMap[0x52] = SDLK_KP0;
+ HWScanKeyMap[0x53] = SDLK_KP_PERIOD;
+}
+
+
+/* Iconify the window.
+ This function returns 1 if there is a window manager and the
+ window was actually iconified, it returns 0 otherwise.
+ */
+int os2fslib_IconifyWindow(_THIS)
+{
+ HAB hab;
+ HMQ hmq;
+ ERRORID hmqerror;
+
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1) return 0;
+
+ // Cannot do anything in fullscreen mode!
+ if (FSLib_QueryFSMode(_this->hidden->hwndClient))
+ return 0;
+
+ // Make sure this thread is prepared for using the Presentation Manager!
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab,0);
+ // Remember if there was an error at WinCreateMsgQueue(), because we don't
+ // want to destroy somebody else's queue later. :)
+ hmqerror = WinGetLastError(hab);
+
+ WinSetWindowPos(_this->hidden->hwndFrame, HWND_TOP,
+ 0, 0, 0, 0, SWP_MINIMIZE);
+
+ // Now destroy the message queue, if we've created it!
+ if (ERRORIDERROR(hmqerror)==0)
+ WinDestroyMsgQueue(hmq);
+
+ return 1;
+}
+
+static SDL_GrabMode os2fslib_GrabInput(_THIS, SDL_GrabMode mode)
+{
+ HAB hab;
+ HMQ hmq;
+ ERRORID hmqerror;
+
+
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1)
+ return SDL_GRAB_OFF;
+
+ // Make sure this thread is prepared for using the Presentation Manager!
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab,0);
+ // Remember if there was an error at WinCreateMsgQueue(), because we don't
+ // want to destroy somebody else's queue later. :)
+ hmqerror = WinGetLastError(hab);
+
+
+ if (mode == SDL_GRAB_OFF)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_GrabInput] : Releasing mouse\n"); fflush(stdout);
+#endif
+
+ // Release the mouse
+ bMouseCapturable = 0;
+ if (bMouseCaptured)
+ {
+ WinSetCapture(HWND_DESKTOP, NULLHANDLE);
+ bMouseCaptured = 0;
+ }
+ } else
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_GrabInput] : Capturing mouse\n"); fflush(stdout);
+#endif
+
+ // Capture the mouse
+ bMouseCapturable = 1;
+ if (WinQueryFocus(HWND_DESKTOP) == _this->hidden->hwndClient)
+ {
+ WinSetCapture(HWND_DESKTOP, _this->hidden->hwndClient);
+ bMouseCaptured = 1;
+ {
+ SWP swpClient;
+ POINTL ptl;
+ // Center the mouse to the middle of the window!
+ WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
+ ptl.x = 0; ptl.y = 0;
+ WinMapWindowPoints(_this->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
+ _this->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
+ WinSetPointerPos(HWND_DESKTOP,
+ ptl.x + swpClient.cx/2,
+ ptl.y + swpClient.cy/2);
+ }
+ }
+ }
+
+ // Now destroy the message queue, if we've created it!
+ if (ERRORIDERROR(hmqerror)==0)
+ WinDestroyMsgQueue(hmq);
+
+ return mode;
+}
+
+/* Set the title and icon text */
+static void os2fslib_SetCaption(_THIS, const char *title, const char *icon)
+{
+ HAB hab;
+ HMQ hmq;
+ ERRORID hmqerror;
+
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1) return;
+
+ // Make sure this thread is prepared for using the Presentation Manager!
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab,0);
+ // Remember if there was an error at WinCreateMsgQueue(), because we don't
+ // want to destroy somebody else's queue later. :)
+ hmqerror = WinGetLastError(hab);
+
+ WinSetWindowText(_this->hidden->hwndFrame, (char *) title);
+
+ // Now destroy the message queue, if we've created it!
+ if (ERRORIDERROR(hmqerror)==0)
+ WinDestroyMsgQueue(hmq);
+}
+
+static int os2fslib_ToggleFullScreen(_THIS, int on)
+{
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_ToggleFullScreen] : %d\n", on); fflush(stdout);
+#endif
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1) return 0;
+
+ FSLib_ToggleFSMode(_this->hidden->hwndClient, on);
+ /* Cursor manager functions to Windowed/FS mode*/
+ os2fslib_SetCursorManagementFunctions(_this, !on);
+ return 1;
+}
+
+/* This is called after the video mode has been set, to get the
+ initial mouse state. It should queue events as necessary to
+ properly represent the current mouse focus and position.
+ */
+static void os2fslib_UpdateMouse(_THIS)
+{
+ POINTL ptl;
+ HAB hab;
+ HMQ hmq;
+ ERRORID hmqerror;
+ SWP swpClient;
+
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1) return;
+
+
+ // Make sure this thread is prepared for using the Presentation Manager!
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab,0);
+ // Remember if there was an error at WinCreateMsgQueue(), because we don't
+ // want to destroy somebody else's queue later. :)
+ hmqerror = WinGetLastError(hab);
+
+
+
+ if (_this->hidden->fInFocus)
+ {
+ // If our app is in focus
+ SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
+ SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
+ SDL_PrivateAppActive(1, SDL_APPACTIVE);
+ WinQueryPointerPos(HWND_DESKTOP, &ptl);
+ WinMapWindowPoints(HWND_DESKTOP, _this->hidden->hwndClient, &ptl, 1);
+ WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
+ // Convert OS/2 mouse position to SDL position, and also scale it!
+ ptl.x = ptl.x * _this->hidden->SrcBufferDesc.uiXResolution / swpClient.cx;
+ ptl.y = ptl.y * _this->hidden->SrcBufferDesc.uiYResolution / swpClient.cy;
+ ptl.y = _this->hidden->SrcBufferDesc.uiYResolution - ptl.y - 1;
+ SDL_PrivateMouseMotion(0, 0, (Sint16) (ptl.x), (Sint16) (ptl.y));
+ } else
+ {
+ // If we're not in focus
+ SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
+ SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
+ SDL_PrivateAppActive(0, SDL_APPACTIVE);
+ SDL_PrivateMouseMotion(0, 0, (Sint16) -1, (Sint16) -1);
+ }
+
+ // Now destroy the message queue, if we've created it!
+ if (ERRORIDERROR(hmqerror)==0)
+ WinDestroyMsgQueue(hmq);
+
+}
+
+/* This pointer should exist in the native video subsystem and should
+ point to an appropriate update function for the current video mode
+ */
+static void os2fslib_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
+{
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1) return;
+
+#ifdef BITBLT_IN_WINMESSAGEPROC
+ WinSendMsg(_this->hidden->hwndClient,
+ WM_UPDATERECTSREQUEST,
+ (MPARAM) numrects,
+ (MPARAM) rects);
+#else
+ if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
+ {
+ int i;
+
+ if (_this->hidden->pSDLSurface)
+ {
+#ifndef RESIZE_EVEN_IF_RESIZABLE
+ SWP swp;
+ // But only blit if the window is not resizable, or if
+ // the window is resizable and the source buffer size is the
+ // same as the destination buffer size!
+ WinQueryWindowPos(_this->hidden->hwndClient, &swp);
+ if ((_this->hidden->pSDLSurface) &&
+ (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
+ ((swp.cx != _this->hidden->SrcBufferDesc.uiXResolution) ||
+ (swp.cy != _this->hidden->SrcBufferDesc.uiYResolution)
+ ) &&
+ (!FSLib_QueryFSMode(_this->hidden->hwndClient))
+ )
+ {
+ // Resizable surface and in resizing!
+ // So, don't blit now!
+#ifdef DEBUG_BUILD
+ printf("[UpdateRects] : Skipping blit while resizing!\n"); fflush(stdout);
+#endif
+ } else
+#endif
+ {
+ /*
+ // Blit the whole window
+ FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
+ 0, 0,
+ _this->hidden->SrcBufferDesc.uiXResolution,
+ _this->hidden->SrcBufferDesc.uiYResolution);
+ */
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_UpdateRects] : Blitting!\n"); fflush(stdout);
+#endif
+
+ // Blit the changed areas
+ for (i=0; i<numrects; i++)
+ FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
+ rects[i].y, rects[i].x, rects[i].w, rects[i].h);
+ }
+ }
+#ifdef DEBUG_BUILD
+ else
+ printf("[os2fslib_UpdateRects] : No public surface!\n"); fflush(stdout);
+#endif
+ DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
+ }
+#ifdef DEBUG_BUILD
+ else
+ printf("[os2fslib_UpdateRects] : Error in mutex!\n"); fflush(stdout);
+#endif
+#endif
+}
+
+
+/* Reverse the effects VideoInit() -- called if VideoInit() fails
+ or if the application is shutting down the video subsystem.
+ */
+static void os2fslib_VideoQuit(_THIS)
+{
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoQuit]\n"); fflush(stdout);
+#endif
+ // Close PM stuff if running!
+ if (_this->hidden->iPMThreadStatus == 1)
+ {
+ int iTimeout;
+ WinPostMsg(_this->hidden->hwndFrame, WM_QUIT, (MPARAM) 0, (MPARAM) 0);
+ // HACK: We had this line before:
+ //DosWaitThread((TID *) &(_this->hidden->tidPMThread), DCWW_WAIT);
+ // We don't use it, because the PMThread will never stop, or if it stops,
+ // it will kill the whole process as a emergency fallback.
+ // So, we only check for the iPMThreadStatus stuff!
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoQuit] : Waiting for PM thread to die\n"); fflush(stdout);
+#endif
+
+ iTimeout=0;
+ while ((_this->hidden->iPMThreadStatus == 1) && (iTimeout<100))
+ {
+ iTimeout++;
+ DosSleep(64);
+ }
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoQuit] : End of wait.\n"); fflush(stdout);
+#endif
+
+ if (_this->hidden->iPMThreadStatus == 1)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoQuit] : Killing PM thread!\n"); fflush(stdout);
+#endif
+
+ _this->hidden->iPMThreadStatus = 0;
+ DosKillThread(_this->hidden->tidPMThread);
+
+ if (_this->hidden->hwndFrame)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoQuit] : Destroying PM window!\n"); fflush(stdout);
+#endif
+
+ WinDestroyWindow(_this->hidden->hwndFrame); _this->hidden->hwndFrame=NULL;
+ }
+ }
+
+ }
+
+ // Free result of an old ListModes() call, because there is
+ // no FreeListModes() call in SDL!
+ if (_this->hidden->pListModesResult)
+ {
+ free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
+ }
+
+ // Free list of available fullscreen modes
+ if (_this->hidden->pAvailableFSLibVideoModes)
+ {
+ FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
+ _this->hidden->pAvailableFSLibVideoModes = NULL;
+ }
+
+ // Free application icon if we had one
+ if (hptrCurrentIcon)
+ {
+ WinDestroyPointer(hptrCurrentIcon);
+ hptrCurrentIcon = NULL;
+ }
+}
+
+/* Set the requested video mode, returning a surface which will be
+ set to the SDL_VideoSurface. The width and height will already
+ be verified by ListModes(), and the video subsystem is free to
+ set the mode to a supported bit depth different from the one
+ specified -- the desired bpp will be emulated with a shadow
+ surface if necessary. If a new mode is returned, this function
+ should take care of cleaning up the current mode.
+ */
+static SDL_Surface *os2fslib_SetVideoMode(_THIS, SDL_Surface *current,
+ int width, int height, int bpp, Uint32 flags)
+{
+ static int bFirstCall = 1;
+ FSLib_VideoMode_p pModeInfo, pModeInfoFound;
+ FSLib_VideoMode TempModeInfo;
+ HAB hab;
+ HMQ hmq;
+ ERRORID hmqerror;
+ RECTL rectl;
+ SDL_Surface *pResult;
+
+ // If there is no more window, nothing we can do!
+ if (_this->hidden->iPMThreadStatus!=1) return NULL;
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Request for %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
+#endif
+
+ // We don't support palette modes!
+ if (bpp==8) bpp=32;
+
+ // Also, we don't support resizable modes in fullscreen mode.
+ if (flags & SDL_RESIZABLE)
+ flags &= ~SDL_FULLSCREEN;
+
+ // No double buffered mode
+ if (flags & SDL_DOUBLEBUF)
+ flags &= ~SDL_DOUBLEBUF;
+
+ // And, we don't support HWSURFACE yet.
+ if (flags & SDL_HWSURFACE)
+ {
+ flags &= ~SDL_HWSURFACE;
+ flags |= SDL_SWSURFACE;
+ }
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Changed request to %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
+#endif
+
+ // First check if there is such a video mode they want!
+ pModeInfoFound = NULL;
+
+ // For fullscreen mode we don't support every resolution!
+ // So, go through the video modes, and check for such a resolution!
+ pModeInfoFound = NULL;
+ pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
+
+ while (pModeInfo)
+ {
+ // Check all available fullscreen modes for this resolution
+ if ((pModeInfo->uiXResolution == width) &&
+ (pModeInfo->uiYResolution == height) &&
+ (pModeInfo->uiBPP!=8)) // palettized modes not yet supported
+ {
+ // If good resolution, try to find the exact BPP, or at least
+ // something similar...
+ if (!pModeInfoFound)
+ pModeInfoFound = pModeInfo;
+ else
+ if ((pModeInfoFound->uiBPP!=bpp) &&
+ (pModeInfoFound->uiBPP<pModeInfo->uiBPP))
+ pModeInfoFound = pModeInfo;
+ }
+ pModeInfo = pModeInfo->pNext;
+ }
+
+ // If we did not find a good fullscreen mode, then try a similar
+ if (!pModeInfoFound)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Requested video mode not found, looking for a similar one!\n"); fflush(stdout);
+#endif
+ // Go through the video modes again, and find a similar resolution!
+ pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
+ while (pModeInfo)
+ {
+ // Check all available fullscreen modes for this resolution
+ if ((pModeInfo->uiXResolution >= width) &&
+ (pModeInfo->uiYResolution >= height) &&
+ (pModeInfo->uiBPP == bpp))
+ {
+ if (!pModeInfoFound)
+ pModeInfoFound = pModeInfo;
+ else
+ if (((pModeInfoFound->uiXResolution-width)*(pModeInfoFound->uiYResolution-height))>
+ ((pModeInfo->uiXResolution-width)*(pModeInfo->uiYResolution-height)))
+ {
+ // Found a mode which is closer than the current one
+ pModeInfoFound = pModeInfo;
+ }
+ }
+ pModeInfo = pModeInfo->pNext;
+ }
+ }
+
+ // If we did not find a good fullscreen mode, then return NULL
+ if (!pModeInfoFound)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Requested video mode not found!\n"); fflush(stdout);
+#endif
+ return NULL;
+ }
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Found mode!\n"); fflush(stdout);
+#endif
+
+ // We'll possibly adjust the structure, so copy out the values
+ // into TempModeInfo!
+ memcpy(&TempModeInfo, pModeInfoFound, sizeof(TempModeInfo));
+ pModeInfoFound = &TempModeInfo;
+
+ if (flags & SDL_RESIZABLE)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Requested mode is resizable, changing width/height\n"); fflush(stdout);
+#endif
+ // Change width and height to requested one!
+ TempModeInfo.uiXResolution = width;
+ TempModeInfo.uiYResolution = height;
+ TempModeInfo.uiScanLineSize = width * ((TempModeInfo.uiBPP+7)/8);
+ }
+
+ // We can try create new surface!
+
+ // Make sure this thread is prepared for using the Presentation Manager!
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab,0);
+ // Remember if there was an error at WinCreateMsgQueue(), because we don't
+ // want to destroy somebody else's queue later. :)
+ hmqerror = WinGetLastError(hab);
+
+
+
+ if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Creating new SW surface\n"); fflush(stdout);
+#endif
+
+ // Create new software surface!
+ pResult = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ pModeInfoFound->uiXResolution,
+ pModeInfoFound->uiYResolution,
+ pModeInfoFound->uiBPP,
+ ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition,
+ ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition,
+ ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition,
+ ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition);
+
+ if (pResult == NULL)
+ {
+ DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Adjusting pixel format\n"); fflush(stdout);
+#endif
+
+ // Adjust pixel format mask!
+ pResult->format->Rmask = ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition;
+ pResult->format->Rshift = pModeInfoFound->PixelFormat.ucRedPosition;
+ pResult->format->Rloss = pModeInfoFound->PixelFormat.ucRedAdjust;
+ pResult->format->Gmask = ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition;
+ pResult->format->Gshift = pModeInfoFound->PixelFormat.ucGreenPosition;
+ pResult->format->Gloss = pModeInfoFound->PixelFormat.ucGreenAdjust;
+ pResult->format->Bmask = ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition;
+ pResult->format->Bshift = pModeInfoFound->PixelFormat.ucBluePosition;
+ pResult->format->Bloss = pModeInfoFound->PixelFormat.ucBlueAdjust;
+ pResult->format->Amask = ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition;
+ pResult->format->Ashift = pModeInfoFound->PixelFormat.ucAlphaPosition;
+ pResult->format->Aloss = pModeInfoFound->PixelFormat.ucAlphaAdjust;
+
+#ifdef REPORT_EMPTY_ALPHA_MASK
+ pResult->format->Amask =
+ pResult->format->Ashift =
+ pResult->format->Aloss = 0;
+#endif
+
+ // Adjust surface flags
+ pResult->flags |= (flags & SDL_FULLSCREEN);
+ pResult->flags |= (flags & SDL_RESIZABLE);
+
+ // It might be that the software surface pitch is not the same as
+ // the pitch we have, so adjust that!
+ pModeInfoFound->uiScanLineSize = pResult->pitch;
+
+ // Store new source buffer parameters!
+ memcpy(&(_this->hidden->SrcBufferDesc), pModeInfoFound, sizeof(*pModeInfoFound));
+ _this->hidden->pchSrcBuffer = pResult->pixels;
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Telling FSLib the stuffs\n"); fflush(stdout);
+#endif
+
+ // Tell the FSLib window the new source image format
+ FSLib_SetSrcBufferDesc(_this->hidden->hwndClient, &(_this->hidden->SrcBufferDesc));
+
+ if (
+ ((flags & SDL_RESIZABLE)==0) ||
+ (bFirstCall)
+ )
+ {
+ bFirstCall = 0;
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Modifying window size\n"); fflush(stdout);
+#endif
+
+ // Calculate frame window size from client window size
+ rectl.xLeft = 0;
+ rectl.yBottom = 0;
+ rectl.xRight = pModeInfoFound->uiXResolution; // Noninclusive
+ rectl.yTop = pModeInfoFound->uiYResolution; // Noninclusive
+ WinCalcFrameRect(_this->hidden->hwndFrame, &rectl, FALSE);
+
+ // Set the new size of the main window
+ SetAccessableWindowPos(_this->hidden->hwndFrame,
+ HWND_TOP,
+ 0, 0,
+ (rectl.xRight-rectl.xLeft),
+ (rectl.yTop-rectl.yBottom),
+ SWP_SIZE | SWP_ACTIVATE | SWP_SHOW);
+ }
+
+ // Set fullscreen mode flag, and switch to fullscreen if needed!
+ if (flags & SDL_FULLSCREEN)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Also trying to switch to fullscreen\n");
+ fflush(stdout);
+#endif
+ FSLib_ToggleFSMode(_this->hidden->hwndClient, 1);
+ /* Cursor manager functions to FS mode*/
+ os2fslib_SetCursorManagementFunctions(_this, 0);
+ } else
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Also trying to switch to desktop mode\n");
+ fflush(stdout);
+#endif
+ FSLib_ToggleFSMode(_this->hidden->hwndClient, 0);
+ /* Cursor manager functions to Windowed mode*/
+ os2fslib_SetCursorManagementFunctions(_this, 1);
+ }
+
+ _this->hidden->pSDLSurface = pResult;
+
+ DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
+ } else
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Could not get hmtxUseSrcBuffer!\n"); fflush(stdout);
+#endif
+
+ pResult = NULL;
+ }
+
+ // As we have the new surface, we don't need the current one anymore!
+ if ((pResult) && (current))
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Freeing old surface\n"); fflush(stdout);
+#endif
+ SDL_FreeSurface(current);
+ }
+
+ // Redraw window
+ WinInvalidateRegion(_this->hidden->hwndClient, NULL, TRUE);
+
+ // Now destroy the message queue, if we've created it!
+ if (ERRORIDERROR(hmqerror)==0)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Destroying message queue\n"); fflush(stdout);
+#endif
+ WinDestroyMsgQueue(hmq);
+ }
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_SetVideoMode] : Done\n"); fflush(stdout);
+#endif
+
+ /* We're done */
+
+ // Return with the new surface!
+ return pResult;
+}
+
+/* List the available video modes for the given pixel format, sorted
+ from largest to smallest.
+ */
+static SDL_Rect **os2fslib_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
+{
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_ListModes] : ListModes of %d Bpp\n", format->BitsPerPixel);
+#endif
+ // Destroy result of previous call, if there is any
+ if (_this->hidden->pListModesResult)
+ {
+ free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
+ }
+
+ // For resizable and windowed mode we support every resolution!
+ if ((flags & SDL_RESIZABLE) && ((flags & SDL_FULLSCREEN) == 0))
+ return (SDL_Rect **)-1;
+
+ // Check if they need fullscreen or non-fullscreen video modes!
+ if ((flags & SDL_FULLSCREEN) == 0)
+
+ {
+ // For windowed mode we support every resolution!
+ return (SDL_Rect **)-1;
+ } else
+ {
+ FSLib_VideoMode_p pFSMode;
+ // For fullscreen mode we don't support every resolution!
+ // Now create a new list
+ pFSMode = _this->hidden->pAvailableFSLibVideoModes;
+ while (pFSMode)
+ {
+ if (pFSMode->uiBPP == format->BitsPerPixel)
+ {
+ SDL_Rect *pRect = (SDL_Rect *) malloc(sizeof(SDL_Rect));
+ if (pRect)
+ {
+ // Fill description
+ pRect->x = 0;
+ pRect->y = 0;
+ pRect->w = pFSMode->uiXResolution;
+ pRect->h = pFSMode->uiYResolution;
+#ifdef DEBUG_BUILD
+// printf("!!! Seems to be good!\n");
+// printf("F: %dx%d\n", pRect->w, pRect->h);
+#endif
+ // And insert into list of pRects
+ if (!(_this->hidden->pListModesResult))
+ {
+#ifdef DEBUG_BUILD
+// printf("!!! Inserting to beginning\n");
+#endif
+
+ // We're the first one to be inserted!
+ _this->hidden->pListModesResult = (SDL_Rect**) malloc(2*sizeof(SDL_Rect*));
+ if (_this->hidden->pListModesResult)
+ {
+ _this->hidden->pListModesResult[0] = pRect;
+ _this->hidden->pListModesResult[1] = NULL;
+ } else
+ {
+ free(pRect);
+ }
+ } else
+ {
+ // We're not the first ones, so find the place where we
+ // have to insert ourselves
+ SDL_Rect **pNewList;
+ int iPlace, iNumOfSlots, i;
+
+#ifdef DEBUG_BUILD
+// printf("!!! Searching where to insert\n");
+#endif
+
+ iPlace = -1; iNumOfSlots = 1; // Count the last NULL too!
+ for (i=0; _this->hidden->pListModesResult[i]; i++)
+ {
+ iNumOfSlots++;
+ if (iPlace==-1)
+ {
+ if ((_this->hidden->pListModesResult[i]->w*_this->hidden->pListModesResult[i]->h)<
+ (pRect->w*pRect->h))
+ {
+ iPlace = i;
+ }
+ }
+ }
+ if (iPlace==-1) iPlace = iNumOfSlots-1;
+
+#ifdef DEBUG_BUILD
+// printf("!!! From %d slots, it will be at %d\n", iNumOfSlots, iPlace);
+#endif
+
+ pNewList = (SDL_Rect**) realloc(_this->hidden->pListModesResult, (iNumOfSlots+1)*sizeof(SDL_Rect*));
+ if (pNewList)
+ {
+ for (i=iNumOfSlots;i>iPlace;i--)
+ pNewList[i] = pNewList[i-1];
+ pNewList[iPlace] = pRect;
+ _this->hidden->pListModesResult = pNewList;
+ } else
+ {
+ free(pRect);
+ }
+ }
+ }
+ }
+ pFSMode = pFSMode->pNext;
+ }
+ }
+#ifdef DEBUG_BUILD
+// printf("Returning list\n");
+#endif
+ return _this->hidden->pListModesResult;
+}
+
+/* Initialize the native video subsystem, filling 'vformat' with the
+ "best" display pixel format, returning 0 or -1 if there's an error.
+ */
+static int os2fslib_VideoInit(_THIS, SDL_PixelFormat *vformat)
+{
+ FSLib_VideoMode_p pDesktopMode;
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoInit] : Enter\n"); fflush(stdout);
+#endif
+
+ // Report the best pixel format. For this,
+ // we'll use the current desktop format.
+ pDesktopMode = FSLib_GetDesktopVideoMode();
+ if (!pDesktopMode)
+ {
+ SDL_SetError("Could not query desktop video mode!");
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoInit] : Could not query desktop video mode!\n");
+#endif
+ return -1;
+ }
+
+ /* Determine the screen depth */
+ vformat->BitsPerPixel = pDesktopMode->uiBPP;
+ vformat->BytesPerPixel = (vformat->BitsPerPixel+7)/8;
+
+ vformat->Rmask = ((unsigned int) pDesktopMode->PixelFormat.ucRedMask) << pDesktopMode->PixelFormat.ucRedPosition;
+ vformat->Rshift = pDesktopMode->PixelFormat.ucRedPosition;
+ vformat->Rloss = pDesktopMode->PixelFormat.ucRedAdjust;
+ vformat->Gmask = ((unsigned int) pDesktopMode->PixelFormat.ucGreenMask) << pDesktopMode->PixelFormat.ucGreenPosition;
+ vformat->Gshift = pDesktopMode->PixelFormat.ucGreenPosition;
+ vformat->Gloss = pDesktopMode->PixelFormat.ucGreenAdjust;
+ vformat->Bmask = ((unsigned int) pDesktopMode->PixelFormat.ucBlueMask) << pDesktopMode->PixelFormat.ucBluePosition;
+ vformat->Bshift = pDesktopMode->PixelFormat.ucBluePosition;
+ vformat->Bloss = pDesktopMode->PixelFormat.ucBlueAdjust;
+ vformat->Amask = ((unsigned int) pDesktopMode->PixelFormat.ucAlphaMask) << pDesktopMode->PixelFormat.ucAlphaPosition;
+ vformat->Ashift = pDesktopMode->PixelFormat.ucAlphaPosition;
+ vformat->Aloss = pDesktopMode->PixelFormat.ucAlphaAdjust;
+
+#ifdef REPORT_EMPTY_ALPHA_MASK
+ vformat->Amask =
+ vformat->Ashift =
+ vformat->Aloss = 0;
+#endif
+
+ // Fill in some window manager capabilities
+ _this->info.wm_available = 1;
+
+ // Initialize some internal variables
+ _this->hidden->pListModesResult = NULL;
+ _this->hidden->fInFocus = 0;
+ _this->hidden->iSkipWMMOUSEMOVE = 0;
+ _this->hidden->iMouseVisible = 1;
+ DosCreateMutexSem(NULL, &(_this->hidden->hmtxUseSrcBuffer), 0, FALSE);
+
+ // Now create our window with a default size
+
+ // For this, we select the first available fullscreen mode as
+ // current window size!
+ memcpy(&(_this->hidden->SrcBufferDesc), _this->hidden->pAvailableFSLibVideoModes, sizeof(_this->hidden->SrcBufferDesc));
+ // Allocate new video buffer!
+ _this->hidden->pchSrcBuffer = (char *) malloc(_this->hidden->pAvailableFSLibVideoModes->uiScanLineSize * _this->hidden->pAvailableFSLibVideoModes->uiYResolution);
+ if (!_this->hidden->pchSrcBuffer)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoInit] : Yikes, not enough memory for new video buffer!\n"); fflush(stdout);
+#endif
+ SDL_SetError("Not enough memory for new video buffer!\n");
+ return -1;
+ }
+
+ // For this, we need a message processing thread.
+ // We'll create a new thread for this, which will do everything
+ // what is related to PM
+ _this->hidden->iPMThreadStatus = 0;
+ _this->hidden->tidPMThread = _beginthread(PMThreadFunc, NULL, 65536, (void *) _this);
+ if (_this->hidden->tidPMThread <= 0)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoInit] : Could not create PM thread!\n");
+#endif
+ SDL_SetError("Could not create PM thread");
+ return -1;
+ }
+#ifdef USE_DOSSETPRIORITY
+ // Burst the priority of PM Thread!
+ DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, _this->hidden->tidPMThread);
+#endif
+ // Wait for the PM thread to initialize!
+ while (_this->hidden->iPMThreadStatus==0)
+ DosSleep(32);
+ // If the PM thread could not set up everything, then
+ // report an error!
+ if (_this->hidden->iPMThreadStatus!=1)
+ {
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_VideoInit] : PMThread reported an error : %d\n", _this->hidden->iPMThreadStatus);
+#endif
+ SDL_SetError("Error initializing PM thread");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void os2fslib_DeleteDevice(_THIS)
+{
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_DeleteDevice]\n"); fflush(stdout);
+#endif
+ // Free used memory
+ FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
+ if (_this->hidden->pListModesResult)
+ free(_this->hidden->pListModesResult);
+ if (_this->hidden->pchSrcBuffer)
+ free(_this->hidden->pchSrcBuffer);
+ DosCloseMutexSem(_this->hidden->hmtxUseSrcBuffer);
+ free(_this->hidden);
+ free(_this);
+ FSLib_Uninitialize();
+}
+
+static int os2fslib_Available(void)
+{
+
+ // If we can run, it means that we could load FSLib,
+ // so we assume that it's available then!
+ return 1;
+}
+
+static void os2fslib_MorphToPM()
+{
+ PPIB pib;
+ PTIB tib;
+
+ DosGetInfoBlocks(&tib, &pib);
+
+ // Change flag from VIO to PM:
+ if (pib->pib_ultype==2) pib->pib_ultype = 3;
+}
+
+static SDL_VideoDevice *os2fslib_CreateDevice(int devindex)
+{
+ SDL_VideoDevice *device;
+
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_CreateDevice] : Enter\n"); fflush(stdout);
+#endif
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
+ if ( device )
+ {
+ memset(device, 0, (sizeof *device));
+ // Also allocate memory for private data
+ device->hidden = (struct SDL_PrivateVideoData *) malloc((sizeof(struct SDL_PrivateVideoData)));
+ }
+ if ( (device == NULL) || (device->hidden == NULL) )
+ {
+ SDL_OutOfMemory();
+ if ( device )
+ free(device);
+ return NULL;
+ }
+ memset(device->hidden, 0, (sizeof *device->hidden));
+
+ /* Set the function pointers */
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_CreateDevice] : VideoInit is %p\n", os2fslib_VideoInit); fflush(stdout);
+#endif
+
+ /* Initialization/Query functions */
+ device->VideoInit = os2fslib_VideoInit;
+ device->ListModes = os2fslib_ListModes;
+ device->SetVideoMode = os2fslib_SetVideoMode;
+ device->ToggleFullScreen = os2fslib_ToggleFullScreen;
+ device->UpdateMouse = os2fslib_UpdateMouse;
+ device->CreateYUVOverlay = NULL;
+ device->SetColors = os2fslib_SetColors;
+ device->UpdateRects = os2fslib_UpdateRects;
+ device->VideoQuit = os2fslib_VideoQuit;
+ /* Hardware acceleration functions */
+ device->AllocHWSurface = os2fslib_AllocHWSurface;
+ device->CheckHWBlit = NULL;
+ device->FillHWRect = NULL;
+ device->SetHWColorKey = NULL;
+ device->SetHWAlpha = NULL;
+ device->LockHWSurface = os2fslib_LockHWSurface;
+ device->UnlockHWSurface = os2fslib_UnlockHWSurface;
+ device->FlipHWSurface = NULL;
+ device->FreeHWSurface = os2fslib_FreeHWSurface;
+ /* Window manager functions */
+ device->SetCaption = os2fslib_SetCaption;
+ device->SetIcon = os2fslib_SetIcon;
+ device->IconifyWindow = os2fslib_IconifyWindow;
+ device->GrabInput = os2fslib_GrabInput;
+ device->GetWMInfo = NULL;
+ /* Cursor manager functions to Windowed mode*/
+ os2fslib_SetCursorManagementFunctions(device, 1);
+ /* Event manager functions */
+ device->InitOSKeymap = os2fslib_InitOSKeymap;
+ device->PumpEvents = os2fslib_PumpEvents;
+ /* The function used to dispose of this structure */
+ device->free = os2fslib_DeleteDevice;
+
+ // Make sure we'll be able to use Win* API even if the application
+ // was linked to be a VIO application!
+ os2fslib_MorphToPM();
+
+ // Now initialize FSLib, and query available video modes!
+ if (!FSLib_Initialize())
+ {
+ // Could not initialize FSLib!
+#ifdef DEBUG_BUILD
+ printf("[os2fslib_CreateDevice] : Could not initialize FSLib!\n");
+#endif
+ SDL_SetError("Could not initialize FSLib!");
+ free(device->hidden);
+ free(device);
+ return NULL;
+ }
+ device->hidden->pAvailableFSLibVideoModes =
+ FSLib_GetVideoModeList();
+
+ return device;
+}
+
+VideoBootStrap OS2FSLib_bootstrap = {
+ "os2fslib", "OS/2 Video Output using FSLib",
+ os2fslib_Available, os2fslib_CreateDevice
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/os2fslib/SDL_os2fslib.h Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,63 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifndef _SDL_os2fslib_h
+#define _SDL_os2fslib_h
+
+
+// OS2 specific includes
+#define INCL_TYPES
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_DOSPROCESS
+#define INCL_WIN
+#define INCL_GPI
+#include <os2.h>
+
+#include <FSLib.h>
+
+/* Hidden "this" pointer for the video functions */
+#define _THIS SDL_VideoDevice *_this
+
+/* Private display data */
+struct SDL_PrivateVideoData
+{
+ FSLib_VideoMode_p pAvailableFSLibVideoModes;
+ SDL_Rect **pListModesResult; // Allocated memory to return list of modes for os2fslib_ListModes() API
+
+ FSLib_VideoMode SrcBufferDesc; // Description of current source image buffer
+ char *pchSrcBuffer; // The source image buffer itself
+ SDL_Surface *pSDLSurface; // The SDL surface describing the buffer
+ HMTX hmtxUseSrcBuffer; // Mutex semaphore to manipulate src buffer
+ HWND hwndFrame, hwndClient; // Window handle of frame and client
+ int iPMThreadStatus; // 0: Not running
+ // 1: Running
+ // Other: Not running, had an error
+ int tidPMThread; // Thread ID of PM Thread
+ int fInFocus; // True if we're in focus!
+ int iSkipWMMOUSEMOVE; // Number of WM_MOUSEMOVE messages to skip!
+ int iMouseVisible; //
+};
+
+extern DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF);
+
+#endif /* _SDL_os2fslib_h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/os2fslib/SDL_vkeys.h Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,79 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#ifndef VK_0
+#define VK_0 '0'
+#define VK_1 '1'
+#define VK_2 '2'
+#define VK_3 '3'
+#define VK_4 '4'
+#define VK_5 '5'
+#define VK_6 '6'
+#define VK_7 '7'
+#define VK_8 '8'
+#define VK_9 '9'
+#define VK_A 'A'
+#define VK_B 'B'
+#define VK_C 'C'
+#define VK_D 'D'
+#define VK_E 'E'
+#define VK_F 'F'
+#define VK_G 'G'
+#define VK_H 'H'
+#define VK_I 'I'
+#define VK_J 'J'
+#define VK_K 'K'
+#define VK_L 'L'
+#define VK_M 'M'
+#define VK_N 'N'
+#define VK_O 'O'
+#define VK_P 'P'
+#define VK_Q 'Q'
+#define VK_R 'R'
+#define VK_S 'S'
+#define VK_T 'T'
+#define VK_U 'U'
+#define VK_V 'V'
+#define VK_W 'W'
+#define VK_X 'X'
+#define VK_Y 'Y'
+#define VK_Z 'Z'
+#endif /* VK_0 */
+
+/* These keys haven't been defined, but were experimentally determined */
+#define VK_SEMICOLON 0xBA
+#define VK_EQUALS 0xBB
+#define VK_COMMA 0xBC
+#define VK_MINUS 0xBD
+#define VK_PERIOD 0xBE
+#define VK_SLASH 0xBF
+#define VK_GRAVE 0xC0
+#define VK_LBRACKET 0xDB
+#define VK_BACKSLASH 0xDC
+#define VK_RBRACKET 0xDD
+#define VK_APOSTROPHE 0xDE
+#define VK_BACKTICK 0xDF
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/Makefile.wat Wed Nov 23 07:29:56 2005 +0000
@@ -0,0 +1,52 @@
+#=============================================================================
+# This is a Watcom makefile to build SDL.DLL for OS/2
+#
+# Makefile for test applications
+#=============================================================================
+
+# Create debug build or not?
+debug_build=defined
+
+#-----------------------------------------------------------------------------
+# The next part is somewhat general, for creation of EXE files.
+#-----------------------------------------------------------------------------
+
+cflags = $(debugflags) -bm -bt=OS2 -5 -fpi -sg -otexan -wx -ei
+
+.before
+ set include=$(%os2tk)\h;$(%include);../include
+
+.extensions:
+.extensions: .exe .obj .c
+
+all : testalpha.exe &
+ testbitmap.exe &
+ testcdrom.exe &
+ testcpuinfo.exe &
+ testjoystick.exe &
+ testkeys.exe &
+ testlock.exe &
+ testsem.exe &
+ testsprite.exe &
+ testtimer.exe &
+ testtypes.exe &
+ testver.exe &
+ testvidinfo.exe &
+ testwin.exe &
+ testwm.exe &
+ threadwin.exe &
+ torturethread.exe &
+ checkkeys.exe
+
+.c.obj : .AUTODEPEND
+ wcc386 -zq -bm -5s -ei -oteaxan -wx $[* $(cflags)
+
+.obj.exe : .AUTODEPEND
+ wlink system os2v2 F $* L ..\src\sdl.lib name $@ op quiet
+
+clean : .SYMBOLIC
+ @if exist *.exe del *.exe
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.res del *.res
+ @if exist *.lst del *.lst