OS/2 port!
authorRyan C. Gordon <icculus@icculus.org>
Wed, 23 Nov 2005 07:29:56 +0000
changeset 1190173c063d4f55
parent 1189 c96b326b90ba
child 1191 2bd4cec0de63
OS/2 port!

This was mostly, if not entirely, written by "Doodle" and "Caetano":
doodle@scenergy.dfmk.hu
daniel@caetano.eng.br

--ryan.
README.OS2
Watcom.mif
include/SDL_byteorder.h
include/SDL_thread.h
include/SDL_types.h
include/begin_code.h
setvars.cmd
src/Makefile.wat
src/SDL.c
src/SDL_loadso.c
src/audio/Makefile.wat
src/audio/SDL_audio.c
src/audio/SDL_mixer_MMX_VC.c
src/audio/SDL_sysaudio.h
src/audio/dart/SDL_dart.c
src/audio/dart/SDL_dart.h
src/cdrom/Makefile.wat
src/cdrom/os2/SDL_syscdrom.c
src/cpuinfo/Makefile.wat
src/endian/Makefile.wat
src/events/Makefile.wat
src/events/SDL_events.c
src/events/SDL_resize.c
src/events/SDL_sysevents.h
src/file/Makefile.wat
src/joystick/Makefile.wat
src/joystick/os2/SDL_sysjoystick.c
src/joystick/os2/joyos2.h
src/loadso/macosx/SDL_loadso.c
src/loadso/os2/SDL_loadso.c
src/thread/Makefile.wat
src/thread/SDL_systhread.h
src/thread/SDL_thread.c
src/thread/os2/SDL_syscond.c
src/thread/os2/SDL_syscond_c.h
src/thread/os2/SDL_sysmutex.c
src/thread/os2/SDL_syssem.c
src/thread/os2/SDL_systhread.c
src/thread/os2/SDL_systhread_c.h
src/timer/Makefile.wat
src/timer/SDL_timer.c
src/timer/os2/SDL_systimer.c
src/video/Makefile.wat
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/os2fslib/SDL_os2fslib.c
src/video/os2fslib/SDL_os2fslib.h
src/video/os2fslib/SDL_vkeys.h
test/Makefile.wat
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/README.OS2	Wed Nov 23 07:29:56 2005 +0000
     1.3 @@ -0,0 +1,133 @@
     1.4 +
     1.5 +===========
     1.6 +SDL on OS/2
     1.7 +===========
     1.8 +
     1.9 +Last updated on Oct 02, 2005.
    1.10 +
    1.11 +
    1.12 +1. How to compile?
    1.13 +------------------
    1.14 +
    1.15 +To compile this, you'll need the followings installed:
    1.16 +- The OS/2 Developer's Toolkit
    1.17 +- The OpenWatcom compiler 
    1.18 +  (http://www.openwatcom.org)
    1.19 +- The FSLib library
    1.20 +  (ftp://ftp.netlabs.org/pub/SDL)
    1.21 +
    1.22 +Please edit the second, fourth and fifth lines of setvars.cmd file
    1.23 +to set the folders where the toolkit, the OW compiler and the FSLib are. 
    1.24 +You won't need NASM yet (The Netwide Assembler), you can leave that line.
    1.25 +Run setvars.cmd, and you should get a shell in which you can
    1.26 +compile SDL.
    1.27 +
    1.28 +Check the "Watcom.mif" file. This is the file which is included by all the
    1.29 +Watcom makefiles, so changes here will affect the whole build process.
    1.30 +There is a line in there which determines if the resulting SDL.DLL will be
    1.31 +a 'debug' or a 'release' build. The 'debug' version is full of printf()'s,
    1.32 +so if something goes wrong, its output can help a lot for debugging.
    1.33 +
    1.34 +Then go to the 'src' folder, and run "wmake -f makefile.wat".
    1.35 +This should create the SDL.DLL and the corresponding SDL.LIB file there.
    1.36 +
    1.37 +To test applications, it's a good idea to use the 'debug' build of SDL, and
    1.38 +redirect the standard output and standard error output to files, to see what
    1.39 +happens internally in SDL.
    1.40 +(like: testsprite >stdout.txt 2>stderr.txt)
    1.41 +
    1.42 +To rebuild SDL, use the following commands in 'src' folder:
    1.43 +wmake -f makefile.wat clean
    1.44 +wmake -f makefile.wat
    1.45 +
    1.46 +
    1.47 +
    1.48 +2. How to compile the testapps?
    1.49 +-------------------------------
    1.50 +
    1.51 +Once you have SDL.DLL compiled, navigate into the 'test' folder, copy in there
    1.52 +the newly built SDL.DLL, and copy in there FSLib.DLL.
    1.53 +
    1.54 +Then run "wmake -f makefile.wat" in there to compile some of the testapps.
    1.55 +
    1.56 +
    1.57 +
    1.58 +3. What is missing?
    1.59 +-------------------
    1.60 +
    1.61 +The following things are missing from this SDL implementation:
    1.62 +- MMX, SSE and 3DNOW! optimized video blitters?
    1.63 +- HW Video surfaces
    1.64 +- OpenGL support
    1.65 +
    1.66 +
    1.67 +
    1.68 +4. Special Keys / Full-Screen support
    1.69 +-------------------------------------
    1.70 +
    1.71 +There are two special hot-keys implemented:
    1.72 +- Alt+Home switches between fullscreen and windowed mode
    1.73 +- Alt+End simulates closing the window (can be used as a Panic key)
    1.74 +Only the LEFT Alt key will work.
    1.75 +
    1.76 +
    1.77 +
    1.78 +5. Joysticks on SDL/2
    1.79 +---------------------
    1.80 +
    1.81 +The Joystick detection only works for standard joysticks (2 buttons, 2 axes
    1.82 +and the like). Therefore, if you use a non-standard joystick, you should
    1.83 +specify its features in the SDL_OS2_JOYSTICK environment variable in a batch
    1.84 +file or CONFIG.SYS, so SDL applications can provide full capability to your
    1.85 +device. The syntax is:
    1.86 +
    1.87 +SET SDL_OS2_JOYSTICK=[JOYSTICK_NAME] [AXES] [BUTTONS] [HATS] [BALLS]
    1.88 +
    1.89 +So, it you have a Gravis GamePad with 4 axes, 2 buttons, 2 hats and 0 balls,
    1.90 +the line should be:
    1.91 +
    1.92 +SET SDL_OS2_JOYSTICK=Gravis_GamePad 4 2 2 0
    1.93 +
    1.94 +If you want to add spaces in your joystick name, just surround it with
    1.95 +quotes or double-quotes:
    1.96 +
    1.97 +SET SDL_OS2_JOYSTICK='Gravis GamePad' 4 2 2 0
    1.98 +
    1.99 +or
   1.100 +
   1.101 +SET SDL_OS2_JOYSTICK="Gravis GamePad" 4 2 2 0
   1.102 +
   1.103 +   Notive However that Balls and Hats are not supported under OS/2, and the
   1.104 +value will be ignored... but it is wise to define these correctly because 
   1.105 +in the future those can be supported.
   1.106 +   Also the number of buttons is limited to 2 when using two joysticks,
   1.107 +4 when using one joystick with 4 axes, 6 when using a joystick with 3 axes
   1.108 +and 8 when using a joystick with 2 axes. Notice however these are limitations 
   1.109 +of the Joystick Port hardware, not OS/2.
   1.110 +
   1.111 +
   1.112 +
   1.113 +6. Next steps...
   1.114 +----------------
   1.115 +
   1.116 +Things to do:
   1.117 +- Implement missing stuffs (look for 'TODO' string in source code!)
   1.118 +- Finish video driver (the 'wincommon' can be a good example for missing
   1.119 +  things like application icon and so on...)
   1.120 +- Enable MMX/SSE/SSE2 acceleration functions
   1.121 +- Rewrite CDROM support using DOS Ioctl for better support.
   1.122 +
   1.123 +
   1.124 +
   1.125 +7. Contacts
   1.126 +-----------
   1.127 +
   1.128 +   You can contact the developers for bugs:
   1.129 +
   1.130 +   Area					Developer		email
   1.131 +   General (Audio/Video/System)		Doodle			doodle@scenergy.dfmk.hu
   1.132 +   CDROM and Joystick			Caetano			daniel@caetano.eng.br
   1.133 +
   1.134 +   Notice however that SDL/2 is 'in development' stage so ... if you want to help,
   1.135 +please, be our guest and contact us!
   1.136 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Watcom.mif	Wed Nov 23 07:29:56 2005 +0000
     2.3 @@ -0,0 +1,33 @@
     2.4 +#=============================================================================
     2.5 +#             This file contains the common includes for the
     2.6 +#               Watcom makefiles to build SDL.DLL for OS/2
     2.7 +#
     2.8 +#
     2.9 +#=============================================================================
    2.10 +
    2.11 +# Create debug build or not?
    2.12 +#debug_build=defined
    2.13 +
    2.14 +# Special flags for building SDL
    2.15 +SDLCFlags = -dBUILD_SDL -dCHECK_LEAKS
    2.16 +
    2.17 +#
    2.18 +#==============================================================================
    2.19 +#
    2.20 +
    2.21 +!ifdef debug_build
    2.22 +debugflags = -d2 -dDEBUG_BUILD
    2.23 +!else
    2.24 +debugflags =
    2.25 +!endif
    2.26 +
    2.27 +cflags = -zq $(debugflags) -bd -bm -bt=OS2 -5s -fpi -sg -otexan -wx -ei $(SDLCFlags) $(ExtraCFlags)
    2.28 +
    2.29 +.extensions:
    2.30 +.extensions: .lib .dll .obj .c .asm
    2.31 +
    2.32 +.c.obj : .AUTODEPEND
    2.33 +    wcc386 $[* $(cflags)
    2.34 +
    2.35 +.asm.obj : .AUTODEPEND
    2.36 +    nasm -t -O2 -f obj -I$(%include) $[*.asm
     3.1 --- a/include/SDL_byteorder.h	Wed Nov 23 07:23:48 2005 +0000
     3.2 +++ b/include/SDL_byteorder.h	Wed Nov 23 07:29:56 2005 +0000
     3.3 @@ -55,9 +55,8 @@
     3.4      (defined(__arm__) || defined(__thumb__)) || \
     3.5      (defined(__sh__) || defined(__sh64__)) || \
     3.6      (defined(__mips__) && defined(__MIPSEL__)) || \
     3.7 -     defined(__SYMBIAN32__) || \
     3.8 -     defined(__x86_64__) || \
     3.9 -     defined(__LITTLE_ENDIAN__)
    3.10 +     defined(__SYMBIAN32__) || defined(__x86_64__) || \
    3.11 +     defined(__OS2__) || defined(__LITTLE_ENDIAN__)
    3.12  #define SDL_BYTEORDER	SDL_LIL_ENDIAN
    3.13  #else
    3.14  #define SDL_BYTEORDER	SDL_BIG_ENDIAN
     4.1 --- a/include/SDL_thread.h	Wed Nov 23 07:23:48 2005 +0000
     4.2 +++ b/include/SDL_thread.h	Wed Nov 23 07:29:56 2005 +0000
     4.3 @@ -50,7 +50,50 @@
     4.4  typedef struct SDL_Thread SDL_Thread;
     4.5  
     4.6  /* Create a thread */
     4.7 +#ifdef __OS2__
     4.8 +/*
     4.9 +   We compile SDL into a DLL on OS/2. This means, that it's the DLL which
    4.10 +   creates a new thread for the calling process with the SDL_CreateThread()
    4.11 +   API. There is a problem with this, that only the RTL of the SDL.DLL will
    4.12 +   be initialized for those threads, and not the RTL of the calling application!
    4.13 +   To solve this, we make a little hack here.
    4.14 +   We'll always use the caller's _beginthread() and _endthread() APIs to
    4.15 +   start a new thread. This way, it it's the SDL.DLL which uses this API,
    4.16 +   then the RTL of SDL.DLL will be used to create the new thread, and if it's
    4.17 +   the application, then the RTL of the application will be used.
    4.18 +   So, in short:
    4.19 +   Always use the _beginthread() and _endthread() of the calling runtime library!
    4.20 +*/
    4.21 +
    4.22 +#ifdef __WATCOMC__
    4.23 +#include <process.h> // This has _beginthread() and _endthread() defined!
    4.24 +#endif
    4.25 +#ifdef __EMX__
    4.26 +#include <stdlib.h> // This has _beginthread() and _endthread() defined, if -Zmt flag is used!
    4.27 +#endif
    4.28 +
    4.29 +typedef Uint32 SDLCALL (*pfnSDL_CurrentBeginThread)(void (*pfnThreadFn)(void *), Uint32 uiStackSize, void *pParam);
    4.30 +typedef void   SDLCALL (*pfnSDL_CurrentEndThread)(void);
    4.31 +
    4.32 +extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread_Core(int (*fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
    4.33 +
    4.34 +// Disable warnings about unreferenced symbol!
    4.35 +#pragma disable_message (202)
    4.36 +static Uint32 SDLCALL SDL_CurrentBeginThread(void (*pfnThreadFn)(void *), Uint32 uiStackSize, void *pParam)
    4.37 +{
    4.38 +  return _beginthread(pfnThreadFn, NULL, uiStackSize, pParam);
    4.39 +}
    4.40 +
    4.41 +static void   SDLCALL SDL_CurrentEndThread(void)
    4.42 +{
    4.43 +  _endthread();
    4.44 +}
    4.45 +
    4.46 +#define SDL_CreateThread(fn, data) SDL_CreateThread_Core(fn, data, SDL_CurrentBeginThread, SDL_CurrentEndThread)
    4.47 +
    4.48 +#else
    4.49  extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data);
    4.50 +#endif
    4.51  
    4.52  /* Get the 32-bit thread identifier for the current thread */
    4.53  extern DECLSPEC Uint32 SDLCALL SDL_ThreadID(void);
     5.1 --- a/include/SDL_types.h	Wed Nov 23 07:23:48 2005 +0000
     5.2 +++ b/include/SDL_types.h	Wed Nov 23 07:29:56 2005 +0000
     5.3 @@ -57,7 +57,7 @@
     5.4  #if !defined(__STRICT_ANSI__)
     5.5  #ifdef __osf__ /* Tru64 */
     5.6  #define SDL_HAS_64BIT_TYPE	long
     5.7 -#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DECC)
     5.8 +#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DECC) || defined(__WATCOMC__)
     5.9  #define SDL_HAS_64BIT_TYPE	long long
    5.10  #elif defined(_MSC_VER) /* VC++ */
    5.11  #define SDL_HAS_64BIT_TYPE	__int64
     6.1 --- a/include/begin_code.h	Wed Nov 23 07:23:48 2005 +0000
     6.2 +++ b/include/begin_code.h	Wed Nov 23 07:29:56 2005 +0000
     6.3 @@ -56,8 +56,20 @@
     6.4  #   define DECLSPEC	__declspec(dllexport)
     6.5  #  endif
     6.6  # else
     6.7 +# ifdef __OS2__
     6.8 +#  ifdef __WATCOMC__
     6.9 +#   ifdef BUILD_SDL
    6.10 +#    define DECLSPEC __declspec(dllexport)
    6.11 +#   else
    6.12  #  define DECLSPEC
    6.13  # endif
    6.14 +#  else
    6.15 +#   define DECLSPEC
    6.16 +#  endif
    6.17 +# else
    6.18 +#  define DECLSPEC
    6.19 +# endif
    6.20 +# endif
    6.21  # endif
    6.22  #endif
    6.23  
    6.24 @@ -66,8 +78,14 @@
    6.25  #if defined(WIN32) && !defined(__GNUC__)
    6.26  #define SDLCALL __cdecl
    6.27  #else
    6.28 +#ifdef __OS2__
    6.29 +/* But on OS/2, we use the _System calling convention */
    6.30 +/* to be compatible with every compiler */
    6.31 +#define SDLCALL _System
    6.32 +#else
    6.33  #define SDLCALL
    6.34  #endif
    6.35 +#endif
    6.36  #endif /* SDLCALL */
    6.37  
    6.38  /* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/setvars.cmd	Wed Nov 23 07:29:56 2005 +0000
     7.3 @@ -0,0 +1,16 @@
     7.4 +@ECHO OFF
     7.5 +SET WATCOM=d:\watcom
     7.6 +SET NASM=d:\nasm
     7.7 +SET OS2TK=d:\os2tk45
     7.8 +SET FSLIB=d:\watcom\projects\FSLib
     7.9 +
    7.10 +SET PATH=%WATCOM%\BINP;%WATCOM%\BINW;%os2tk%\bin;%NASM%;%PATH%
    7.11 +SET INCLUDE=%WATCOM%\H;%WATCOM%\H\OS2
    7.12 +SET FINCLUDE=%WATCOM%\SRC\FORTRAN
    7.13 +SET EDPATH=%WATCOM%\EDDAT
    7.14 +SET HELP=%WATCOM%\BINP\HELP;%HELP%
    7.15 +SET BOOKSHELF=%WATCOM%\BINP\HELP;%BOOKSHELF%
    7.16 +SET BEGINLIBPATH=%WATCOM%\BINP\DLL
    7.17 +
    7.18 +cmd
    7.19 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
     8.3 @@ -0,0 +1,132 @@
     8.4 +#=============================================================================
     8.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
     8.6 +#
     8.7 +#
     8.8 +#=============================================================================
     8.9 +
    8.10 +dllname=SDL
    8.11 +
    8.12 +audioobjs = audio\SDL_audio.obj audio\SDL_audiocvt.obj audio\SDL_audiomem.obj &
    8.13 +            audio\SDL_mixer.obj audio\SDL_mixer_MMX_VC.obj audio\SDL_wave.obj &
    8.14 +            audio\SDL_dart.obj
    8.15 +cdromobjs = cdrom\SDL_cdrom.obj cdrom\SDL_syscdrom.obj
    8.16 +cpuinfoobjs = cpuinfo\SDL_cpuinfo.obj
    8.17 +endianobjs = endian\SDL_endian.obj
    8.18 +eventsobjs = events\SDL_active.obj events\SDL_events.obj events\SDL_expose.obj &
    8.19 +             events\SDL_keyboard.obj events\SDL_mouse.obj events\SDL_quit.obj &
    8.20 +             events\SDL_resize.obj
    8.21 +fileobjs = file\SDL_rwops.obj
    8.22 +hermesobjs = hermes\mmx_main.obj hermes\mmxp2_32.obj hermes\x86_main.obj &
    8.23 +             hermes\x86p_16.obj hermes\x86p_32.obj
    8.24 +joystickobjs = joystick\SDL_joystick.obj joystick\SDL_sysjoystick.obj
    8.25 +threadobjs = thread\SDL_thread.obj thread\SDL_sysmutex.obj &
    8.26 +             thread\SDL_syssem.obj thread\SDL_systhread.obj &
    8.27 +             thread\SDL_syscond.obj
    8.28 +timerobjs = timer\SDL_timer.obj timer\SDL_systimer.obj
    8.29 +videoobjs = video\SDL_blit.obj video\SDL_blit_0.obj video\SDL_blit_1.obj &
    8.30 +            video\SDL_blit_A.obj video\SDL_blit_N.obj video\SDL_bmp.obj &
    8.31 +            video\SDL_cursor.obj video\SDL_gamma.obj video\SDL_pixels.obj &
    8.32 +            video\SDL_RLEaccel.obj video\SDL_stretch.obj video\SDL_surface.obj &
    8.33 +            video\SDL_video.obj video\SDL_yuv.obj video\SDL_yuv_mmx.obj &
    8.34 +            video\SDL_yuv_sw.obj video\SDL_os2fslib.obj
    8.35 +
    8.36 +object_files= SDL.obj SDL_error.obj SDL_fatal.obj SDL_getenv.obj &
    8.37 +              SDL_loadso.obj $(audioobjs) $(cpuinfoobjs) $(endianobjs) &
    8.38 +              $(eventsobjs) $(fileobjs) $(joystickobjs) &
    8.39 +              $(threadobjs) $(timerobjs) $(videoobjs) $(cdromobjs)
    8.40 +	      
    8.41 +
    8.42 +# Extra stuffs to pass to C compiler:
    8.43 +ExtraCFlags=
    8.44 +
    8.45 +#
    8.46 +#==============================================================================
    8.47 +#
    8.48 +!include ..\Watcom.mif
    8.49 +
    8.50 +.before
    8.51 +    @set include=$(%os2tk)\h;$(%include);../include;./thread;./thread/os2;./video;./cdrom;./cdrom/os2;./joystick;./joystick/os2;
    8.52 +
    8.53 +all : check_subdir_objects $(dllname).dll $(dllname).lib
    8.54 +
    8.55 +$(dllname).dll : $(dllname).lnk $(object_files)
    8.56 +    wlink @$(dllname)
    8.57 +
    8.58 +check_subdir_objects: .always .symbolic
    8.59 +    @cd audio
    8.60 +    @wmake -h -f Makefile.wat
    8.61 +    @cd ..\cdrom
    8.62 +    @wmake -h -f Makefile.wat
    8.63 +    @cd ..\cpuinfo
    8.64 +    @wmake -h -f Makefile.wat
    8.65 +    @cd ..\endian
    8.66 +    @wmake -h -f Makefile.wat
    8.67 +    @cd ..\events
    8.68 +    @wmake -h -f Makefile.wat
    8.69 +    @cd ..\file
    8.70 +    @wmake -h -f Makefile.wat
    8.71 +    @cd ..\joystick
    8.72 +    @wmake -h -f Makefile.wat
    8.73 +    @cd ..\thread
    8.74 +    @wmake -h -f Makefile.wat
    8.75 +    @cd ..\timer
    8.76 +    @wmake -h -f Makefile.wat
    8.77 +    @cd ..\video
    8.78 +    @wmake -h -f Makefile.wat
    8.79 +    @cd ..
    8.80 +
    8.81 +$(dllname).lnk :
    8.82 +    @echo Creating linker file ($(dllname).lnk)...
    8.83 +    @echo $#============================================================================= >$^@
    8.84 +    @echo $#              This is a linker file to build SDL.DLL for OS/2 >>$^@
    8.85 +    @echo $# >>$^@
    8.86 +    @echo $# Generated automatically by Makefile.wat >>$^@
    8.87 +    @echo $#============================================================================= >>$^@
    8.88 +    @echo SYSTEM 386 LX DLL INITINSTANCE TERMINSTANCE >>$^@
    8.89 +    @echo NAME $^& >>$^@
    8.90 +    @for %i in ($(object_files)) do @echo FILE %i >>$^@
    8.91 +    @echo LIBPATH %os2tk%\lib >>$^@
    8.92 +    @echo LIBPATH %fslib% >>$^@
    8.93 +    @echo LIB mmpm2.lib >>$^@
    8.94 +    @echo LIB fslib.lib >>$^@
    8.95 +    @echo OPTION QUIET >>$^@
    8.96 +    @echo OPTION MAP=$^&.map >>$^@
    8.97 +    @echo OPTION DESCRIPTION 'Simple DirectMedia Layer v1.2.7' >>$^@
    8.98 +    @echo OPTION ELIMINATE >>$^@
    8.99 +    @echo OPTION MANYAUTODATA >>$^@
   8.100 +    @echo OPTION OSNAME='OS/2 and eComStation' >>$^@
   8.101 +    @echo OPTION SHOWDEAD >>$^@
   8.102 +    @echo Linker file created!
   8.103 +
   8.104 +$(dllname).lib : $(dllname).dll
   8.105 +    implib $(dllname).lib $(dllname).dll
   8.106 +
   8.107 +clean : .SYMBOLIC
   8.108 +    @if exist *.dll del *.dll
   8.109 +    @if exist *.lib del *.lib
   8.110 +    @if exist *.obj del *.obj
   8.111 +    @if exist *.lnk del *.lnk
   8.112 +    @if exist *.map del *.map
   8.113 +    @if exist *.res del *.res
   8.114 +    @if exist *.lst del *.lst
   8.115 +    @cd audio
   8.116 +    @wmake -h -f Makefile.wat clean
   8.117 +    @cd ..\cdrom
   8.118 +    @wmake -h -f Makefile.wat clean
   8.119 +    @cd ..\cpuinfo
   8.120 +    @wmake -h -f Makefile.wat clean
   8.121 +    @cd ..\endian
   8.122 +    @wmake -h -f Makefile.wat clean
   8.123 +    @cd ..\events
   8.124 +    @wmake -h -f Makefile.wat clean
   8.125 +    @cd ..\file
   8.126 +    @wmake -h -f Makefile.wat clean
   8.127 +    @cd ..\joystick
   8.128 +    @wmake -h -f Makefile.wat clean
   8.129 +    @cd ..\thread
   8.130 +    @wmake -h -f Makefile.wat clean
   8.131 +    @cd ..\timer
   8.132 +    @wmake -h -f Makefile.wat clean
   8.133 +    @cd ..\video
   8.134 +    @wmake -h -f Makefile.wat clean
   8.135 +    @cd ..
     9.1 --- a/src/SDL.c	Wed Nov 23 07:23:48 2005 +0000
     9.2 +++ b/src/SDL.c	Wed Nov 23 07:29:56 2005 +0000
     9.3 @@ -220,15 +220,25 @@
     9.4  void SDL_Quit(void)
     9.5  {
     9.6  	/* Quit all subsystems */
     9.7 +#ifdef DEBUG_BUILD
     9.8 +  printf("[SDL_Quit] : Enter! Calling QuitSubSystem()\n"); fflush(stdout);
     9.9 +#endif
    9.10  	SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
    9.11  
    9.12  #ifdef CHECK_LEAKS
    9.13 +#ifdef DEBUG_BUILD
    9.14 +  printf("[SDL_Quit] : CHECK_LEAKS\n"); fflush(stdout);
    9.15 +#endif
    9.16 +
    9.17  	/* Print the number of surfaces not freed */
    9.18  	if ( surfaces_allocated != 0 ) {
    9.19  		fprintf(stderr, "SDL Warning: %d SDL surfaces extant\n", 
    9.20  							surfaces_allocated);
    9.21  	}
    9.22  #endif
    9.23 +#ifdef DEBUG_BUILD
    9.24 +  printf("[SDL_Quit] : SDL_UninstallParachute()\n"); fflush(stdout);
    9.25 +#endif
    9.26  
    9.27  	/* Uninstall any parachute signal handlers */
    9.28  	SDL_UninstallParachute();
    9.29 @@ -236,6 +246,10 @@
    9.30  #if !defined(DISABLE_THREADS) && defined(ENABLE_PTH)
    9.31  	pth_kill();
    9.32  #endif
    9.33 +#ifdef DEBUG_BUILD
    9.34 +  printf("[SDL_Quit] : Returning!\n"); fflush(stdout);
    9.35 +#endif
    9.36 +
    9.37  }
    9.38  
    9.39  /* Return the library version number */
    9.40 @@ -244,6 +258,7 @@
    9.41  	return(&version);
    9.42  }
    9.43  
    9.44 +#ifndef __OS2__
    9.45  #if defined(_WIN32_WCE) || (defined(__WATCOMC__) && defined(BUILD_DLL))
    9.46  /* Need to include DllMain() on Windows CE and Watcom C for some reason.. */
    9.47  #include <windows.h>
    9.48 @@ -262,3 +277,75 @@
    9.49  	return TRUE;
    9.50  }
    9.51  #endif /* _WIN32_WCE and building DLL with Watcom C */
    9.52 +#else
    9.53 +// Building for OS/2
    9.54 +#ifdef __WATCOMC__
    9.55 +
    9.56 +#define INCL_DOSERRORS
    9.57 +#define INCL_DOSEXCEPTIONS
    9.58 +#include <os2.h>
    9.59 +
    9.60 +// Exception handler to prevent the Audio thread hanging, making a zombie process!
    9.61 +ULONG _System SDL_Main_ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
    9.62 +                                        PEXCEPTIONREGISTRATIONRECORD pERegRec,
    9.63 +                                        PCONTEXTRECORD pCtxRec,
    9.64 +                                        PVOID p)
    9.65 +{
    9.66 +  if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
    9.67 +    return XCPT_CONTINUE_SEARCH;
    9.68 +  if (pERepRec->fHandlerFlags & EH_UNWINDING)
    9.69 +    return XCPT_CONTINUE_SEARCH;
    9.70 +  if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
    9.71 +    return XCPT_CONTINUE_SEARCH;
    9.72 +
    9.73 +  // Do cleanup at every fatal exception!
    9.74 +  if (((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION) &&
    9.75 +      (pERepRec->ExceptionNum != XCPT_BREAKPOINT) &&
    9.76 +      (pERepRec->ExceptionNum != XCPT_SINGLE_STEP)
    9.77 +     )
    9.78 +  {
    9.79 +    if (SDL_initialized & SDL_INIT_AUDIO)
    9.80 +    {
    9.81 +      // This removes the zombie audio thread in case of emergency.
    9.82 +#ifdef DEBUG_BUILD
    9.83 +      printf("[SDL_Main_ExceptionHandler] : Calling SDL_CloseAudio()!\n");
    9.84 +#endif
    9.85 +      SDL_CloseAudio();
    9.86 +    }
    9.87 +  }
    9.88 +  return (XCPT_CONTINUE_SEARCH);
    9.89 +}
    9.90 +
    9.91 +
    9.92 +EXCEPTIONREGISTRATIONRECORD SDL_Main_xcpthand = {0, SDL_Main_ExceptionHandler};
    9.93 +
    9.94 +// The main DLL entry for DLL Initialization and Uninitialization:
    9.95 +unsigned _System LibMain(unsigned hmod, unsigned termination)
    9.96 +{
    9.97 +  if (termination)
    9.98 +  {
    9.99 +#ifdef DEBUG_BUILD
   9.100 +//    printf("[SDL DLL Unintialization] : Removing exception handler\n");
   9.101 +#endif
   9.102 +    DosUnsetExceptionHandler(&SDL_Main_xcpthand);
   9.103 +    return 1;
   9.104 +  } else
   9.105 +  {
   9.106 +#ifdef DEBUG_BUILD
   9.107 +    // Make stdout and stderr unbuffered!
   9.108 +    setbuf(stdout, NULL);
   9.109 +    setbuf(stderr, NULL);
   9.110 +#endif
   9.111 +    // Fire up exception handler
   9.112 +#ifdef DEBUG_BUILD
   9.113 +//    printf("[SDL DLL Initialization] : Setting exception handler\n");
   9.114 +#endif
   9.115 +    // Set exception handler
   9.116 +    DosSetExceptionHandler(&SDL_Main_xcpthand);
   9.117 +
   9.118 +    return 1;
   9.119 +  }
   9.120 +}
   9.121 +
   9.122 +#endif
   9.123 +#endif
    10.1 --- a/src/SDL_loadso.c	Wed Nov 23 07:23:48 2005 +0000
    10.2 +++ b/src/SDL_loadso.c	Wed Nov 23 07:29:56 2005 +0000
    10.3 @@ -44,6 +44,8 @@
    10.4  # include "loadso/beos/SDL_loadso.c"
    10.5  #elif defined(__MINT__) && defined(ENABLE_LDG)
    10.6  # include "loadso/mint/SDL_loadso.c"
    10.7 +#elif defined(__OS2__)
    10.8 +# include "loadso/os2/SDL_loadso.c"
    10.9  #else
   10.10  # include "loadso/dummy/SDL_loadso.c"
   10.11  #endif /* system type */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/audio/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    11.3 @@ -0,0 +1,27 @@
    11.4 +#=============================================================================
    11.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    11.6 +#
    11.7 +# Makefile for DART (audio support)
    11.8 +#=============================================================================
    11.9 +
   11.10 +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
   11.11 +ExtraCFlags=-dUSE_ASM_MIXER_VC -dUSE_DOSSETPRIORITY
   11.12 +
   11.13 +#
   11.14 +#==============================================================================
   11.15 +#
   11.16 +!include ..\..\Watcom.mif
   11.17 +
   11.18 +.before
   11.19 +    set include=$(%os2tk)\h;$(%include);../../include;./dart
   11.20 +
   11.21 +all : $(object_files)
   11.22 +
   11.23 +SDL_dart.obj: .AUTODEPEND
   11.24 +    wcc386 dart\SDL_dart.c $(cflags)
   11.25 +
   11.26 +clean : .SYMBOLIC
   11.27 +        @if exist *.obj del *.obj
   11.28 +        @if exist *.map del *.map
   11.29 +        @if exist *.res del *.res
   11.30 +        @if exist *.lst del *.lst
    12.1 --- a/src/audio/SDL_audio.c	Wed Nov 23 07:23:48 2005 +0000
    12.2 +++ b/src/audio/SDL_audio.c	Wed Nov 23 07:29:56 2005 +0000
    12.3 @@ -38,6 +38,12 @@
    12.4  #include "SDL_audiomem.h"
    12.5  #include "SDL_sysaudio.h"
    12.6  
    12.7 +#ifdef __OS2__
    12.8 +// We'll need the DosSetPriority() API!
    12.9 +#define INCL_DOSPROCESS
   12.10 +#include <os2.h>
   12.11 +#endif
   12.12 +
   12.13  /* Available audio drivers */
   12.14  static AudioBootStrap *bootstrap[] = {
   12.15  #ifdef OPENBSD_AUDIO_SUPPORT
   12.16 @@ -108,6 +114,9 @@
   12.17  #ifdef DRENDERER_SUPPORT
   12.18  	&DRENDERER_bootstrap,
   12.19  #endif
   12.20 +#ifdef __OS2__
   12.21 +        &DART_bootstrap,
   12.22 +#endif
   12.23  	NULL
   12.24  };
   12.25  SDL_AudioDevice *current_audio = NULL;
   12.26 @@ -181,6 +190,16 @@
   12.27  	D(bug("Entering audio loop...\n"));
   12.28  #endif
   12.29  
   12.30 +#ifdef __OS2__
   12.31 +        // Increase the priority of this thread to make sure that
   12.32 +        // the audio will be continuous all the time!
   12.33 +#ifdef USE_DOSSETPRIORITY
   12.34 +#ifdef DEBUG_BUILD
   12.35 +        printf("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID());
   12.36 +#endif
   12.37 +        DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
   12.38 +#endif
   12.39 +#endif
   12.40  
   12.41  	/* Loop, filling the audio buffers */
   12.42  	while ( audio->enabled ) {
   12.43 @@ -249,6 +268,11 @@
   12.44  	D(bug("CloseAudio..Done, subtask exiting...\n"));
   12.45  	audio_configured = 0;
   12.46  #endif
   12.47 +#ifdef __OS2__
   12.48 +#ifdef DEBUG_BUILD
   12.49 +        printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
   12.50 +#endif
   12.51 +#endif
   12.52  	return(0);
   12.53  }
   12.54  
    13.1 --- a/src/audio/SDL_mixer_MMX_VC.c	Wed Nov 23 07:23:48 2005 +0000
    13.2 +++ b/src/audio/SDL_mixer_MMX_VC.c	Wed Nov 23 07:29:56 2005 +0000
    13.3 @@ -12,8 +12,10 @@
    13.4  // Mixing for 16 bit signed buffers
    13.5  ////////////////////////////////////////////////
    13.6  
    13.7 +#ifndef __WATCOMC__
    13.8  #include <windows.h>
    13.9  #include <stdio.h>
   13.10 +#endif
   13.11  
   13.12  void SDL_MixAudio_MMX_S16_VC(char* dst,char* src,unsigned int nSize,int volume)
   13.13  {
   13.14 @@ -41,7 +43,9 @@
   13.15  		psllq	mm0, 16			//$16,%%mm0
   13.16  		por		mm0, mm1		//%%mm1,%%mm0			// mm0 = vol|vol|vol|vol
   13.17  
   13.18 +		#ifndef __WATCOMC__
   13.19  		align	16
   13.20 +		#endif
   13.21  mixloopS16:
   13.22  		movq	mm1, [esi]		//(%%esi),%%mm1\n" // mm1 = a|b|c|d
   13.23  		movq	mm2, mm1		//%%mm1,%%mm2\n" // mm2 = a|b|c|d
   13.24 @@ -121,7 +125,9 @@
   13.25  		cmp		ebx, 0		//$0,%%ebx
   13.26  		je		endS8
   13.27  
   13.28 +		#ifndef __WATCOMC__
   13.29  		align 16
   13.30 +		#endif
   13.31  mixloopS8:
   13.32  		pxor	mm2, mm2	//%%mm2,%%mm2		// mm2 = 0
   13.33  		movq	mm1, [esi]	//(%%esi),%%mm1	// mm1 = a|b|c|d|e|f|g|h
    14.1 --- a/src/audio/SDL_sysaudio.h	Wed Nov 23 07:23:48 2005 +0000
    14.2 +++ b/src/audio/SDL_sysaudio.h	Wed Nov 23 07:29:56 2005 +0000
    14.3 @@ -172,6 +172,9 @@
    14.4  #ifdef MMEAUDIO_SUPPORT
    14.5  extern AudioBootStrap MMEAUDIO_bootstrap;
    14.6  #endif
    14.7 +#ifdef __OS2__
    14.8 +extern AudioBootStrap DART_bootstrap;
    14.9 +#endif
   14.10  
   14.11  /* This is the current audio device */
   14.12  extern SDL_AudioDevice *current_audio;
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/audio/dart/SDL_dart.c	Wed Nov 23 07:29:56 2005 +0000
    15.3 @@ -0,0 +1,436 @@
    15.4 +/*
    15.5 +    SDL - Simple DirectMedia Layer
    15.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    15.7 +
    15.8 +    This library is free software; you can redistribute it and/or
    15.9 +    modify it under the terms of the GNU Library General Public
   15.10 +    License as published by the Free Software Foundation; either
   15.11 +    version 2 of the License, or (at your option) any later version.
   15.12 +
   15.13 +    This library is distributed in the hope that it will be useful,
   15.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15.16 +    Library General Public License for more details.
   15.17 +
   15.18 +    You should have received a copy of the GNU Library General Public
   15.19 +    License along with this library; if not, write to the Free
   15.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   15.21 +
   15.22 +    Sam Lantinga
   15.23 +    slouken@libsdl.org
   15.24 +*/
   15.25 +
   15.26 +#ifdef SAVE_RCSID
   15.27 +static char rcsid =
   15.28 + "@(#) $Id$";
   15.29 +#endif
   15.30 +
   15.31 +/* Allow access to a raw mixing buffer */
   15.32 +
   15.33 +#include <stdio.h>
   15.34 +#include <stdlib.h>
   15.35 +#include <string.h>
   15.36 +
   15.37 +#include "SDL_types.h"
   15.38 +#include "SDL_error.h"
   15.39 +#include "SDL_timer.h"
   15.40 +#include "SDL_audio.h"
   15.41 +#include "SDL_audio_c.h"
   15.42 +#include "SDL_dart.h"
   15.43 +
   15.44 +// Buffer states:
   15.45 +#define BUFFER_EMPTY       0
   15.46 +#define BUFFER_USED        1
   15.47 +
   15.48 +typedef struct _tMixBufferDesc {
   15.49 +  int              iBufferUsage;      // BUFFER_EMPTY or BUFFER_USED
   15.50 +  SDL_AudioDevice *pSDLAudioDevice;
   15.51 +} tMixBufferDesc, *pMixBufferDesc;
   15.52 +
   15.53 +
   15.54 +//---------------------------------------------------------------------
   15.55 +// DARTEventFunc
   15.56 +//
   15.57 +// This function is called by DART, when an event occures, like end of 
   15.58 +// playback of a buffer, etc...
   15.59 +//---------------------------------------------------------------------
   15.60 +LONG APIENTRY DARTEventFunc(ULONG ulStatus,
   15.61 +			    PMCI_MIX_BUFFER pBuffer,
   15.62 +			    ULONG ulFlags)
   15.63 +{
   15.64 +  if (ulFlags && MIX_WRITE_COMPLETE)
   15.65 +  { // Playback of buffer completed!
   15.66 +
   15.67 +    // Get pointer to buffer description
   15.68 +    pMixBufferDesc pBufDesc;
   15.69 +
   15.70 +    if (pBuffer)
   15.71 +    {
   15.72 +      pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm;
   15.73 +
   15.74 +      if (pBufDesc)
   15.75 +      {
   15.76 +        SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice;
   15.77 +        // Set the buffer to be empty
   15.78 +        pBufDesc->iBufferUsage = BUFFER_EMPTY;
   15.79 +        // And notify DART feeder thread that it will have to work a bit.
   15.80 +        if (pSDLAudioDevice)
   15.81 +        DosPostEventSem(pSDLAudioDevice->hidden->hevAudioBufferPlayed);
   15.82 +      }
   15.83 +    }
   15.84 +  }
   15.85 +  return TRUE;
   15.86 +}
   15.87 +
   15.88 +
   15.89 +int DART_OpenAudio(_THIS, SDL_AudioSpec *spec)
   15.90 +{
   15.91 +  MCI_AMP_OPEN_PARMS AmpOpenParms;
   15.92 +  MCI_GENERIC_PARMS GenericParms;
   15.93 +  int iDeviceOrd = 0; // Default device to be used
   15.94 +  int bOpenShared = 1; // Try opening it shared
   15.95 +  int iBits = 16; // Default is 16 bits signed
   15.96 +  int iFreq = 44100; // Default is 44KHz
   15.97 +  int iChannels = 2; // Default is 2 channels (Stereo)
   15.98 +  int iNumBufs = 2;  // Number of audio buffers: 2
   15.99 +  int iBufSize;
  15.100 +  int iOpenMode;
  15.101 +  int iSilence;
  15.102 +  int rc;
  15.103 +
  15.104 +  // First thing is to try to open a given DART device!
  15.105 +  memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
  15.106 +  // pszDeviceType should contain the device type in low word, and device ordinal in high word!
  15.107 +  AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16));
  15.108 +
  15.109 +  iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID;
  15.110 +  if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE;
  15.111 +
  15.112 +  rc = mciSendCommand( 0, MCI_OPEN,
  15.113 +                       iOpenMode,
  15.114 +		       (PVOID) &AmpOpenParms, 0);
  15.115 +  if (rc!=MCIERR_SUCCESS) // No audio available??
  15.116 +    return (-1);
  15.117 +  // Save the device ID we got from DART!
  15.118 +  // We will use this in the next calls!
  15.119 +  iDeviceOrd = AmpOpenParms.usDeviceID;
  15.120 +
  15.121 +  // Determine the audio parameters from the AudioSpec
  15.122 +  switch ( spec->format & 0xFF )
  15.123 +  {
  15.124 +    case 8:
  15.125 +        /* Unsigned 8 bit audio data */
  15.126 +        spec->format = AUDIO_U8;
  15.127 +        iSilence = 0x80;
  15.128 +        iBits = 8;
  15.129 +        break;
  15.130 +    case 16:
  15.131 +        /* Signed 16 bit audio data */
  15.132 +        spec->format = AUDIO_S16;
  15.133 +        iSilence = 0x00;
  15.134 +        iBits = 16;
  15.135 +        break;
  15.136 +    default:
  15.137 +        // Close DART, and exit with error code!
  15.138 +        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.139 +        SDL_SetError("Unsupported audio format");
  15.140 +        return(-1);
  15.141 +  }
  15.142 +  iFreq = spec->freq;
  15.143 +  iChannels = spec->channels;
  15.144 +  /* Update the fragment size as size in bytes */
  15.145 +  SDL_CalculateAudioSpec(spec);
  15.146 +  iBufSize = spec->size;
  15.147 +
  15.148 +  // Now query this device if it supports the given freq/bits/channels!
  15.149 +  memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS));
  15.150 +  _this->hidden->MixSetupParms.ulBitsPerSample = iBits;
  15.151 +  _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
  15.152 +  _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq;
  15.153 +  _this->hidden->MixSetupParms.ulChannels = iChannels;
  15.154 +  _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY;
  15.155 +  _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  15.156 +  _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc;
  15.157 +  rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP,
  15.158 +                       MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
  15.159 +                       &(_this->hidden->MixSetupParms), 0);
  15.160 +  if (rc!=MCIERR_SUCCESS)
  15.161 +  { // The device cannot handle this format!
  15.162 +    // Close DART, and exit with error code!
  15.163 +    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.164 +    SDL_SetError("Audio device doesn't support requested audio format");
  15.165 +    return(-1);
  15.166 +  }
  15.167 +  // The device can handle this format, so initialize!
  15.168 +  rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
  15.169 +                      MCI_WAIT | MCI_MIXSETUP_INIT,
  15.170 +                      &(_this->hidden->MixSetupParms), 0);
  15.171 +  if (rc!=MCIERR_SUCCESS)
  15.172 +  { // The device could not be opened!
  15.173 +    // Close DART, and exit with error code!
  15.174 +    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.175 +    SDL_SetError("Audio device could not be set up");
  15.176 +    return(-1);
  15.177 +  }
  15.178 +  // Ok, the device is initialized.
  15.179 +  // Now we should allocate buffers. For this, we need a place where
  15.180 +  // the buffer descriptors will be:
  15.181 +  _this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs);
  15.182 +  if (!(_this->hidden->pMixBuffers))
  15.183 +  { // Not enough memory!
  15.184 +    // Close DART, and exit with error code!
  15.185 +    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.186 +    SDL_SetError("Not enough memory for audio buffer descriptors");
  15.187 +    return(-1);
  15.188 +  }
  15.189 +  // Now that we have the place for buffer list, we can ask DART for the
  15.190 +  // buffers!
  15.191 +  _this->hidden->BufferParms.ulNumBuffers = iNumBufs;               // Number of buffers
  15.192 +  _this->hidden->BufferParms.ulBufferSize = iBufSize;               // each with this size
  15.193 +  _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list
  15.194 +  // Allocate buffers!
  15.195 +  rc = mciSendCommand(iDeviceOrd, MCI_BUFFER,
  15.196 +                      MCI_WAIT | MCI_ALLOCATE_MEMORY,
  15.197 +                      &(_this->hidden->BufferParms), 0);
  15.198 +  if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0))
  15.199 +  { // Could not allocate memory!
  15.200 +    // Close DART, and exit with error code!
  15.201 +    free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
  15.202 +    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.203 +    SDL_SetError("DART could not allocate buffers");
  15.204 +    return(-1);
  15.205 +  }
  15.206 +  // Ok, we have all the buffers allocated, let's mark them!
  15.207 +  {
  15.208 +    int i;
  15.209 +    for (i=0; i<iNumBufs; i++)
  15.210 +    {
  15.211 +      pMixBufferDesc pBufferDesc = (pMixBufferDesc) malloc(sizeof(tMixBufferDesc));;
  15.212 +      // Check if this buffer was really allocated by DART
  15.213 +      if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc))
  15.214 +      { // Wrong buffer!
  15.215 +        // Close DART, and exit with error code!
  15.216 +        // Free buffer descriptions
  15.217 +        { int j;
  15.218 +          for (j=0; j<i; j++) free((void *)(_this->hidden->pMixBuffers[j].ulUserParm));
  15.219 +        }
  15.220 +        // and cleanup
  15.221 +        mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
  15.222 +        free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
  15.223 +        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.224 +        SDL_SetError("Error at internal buffer check");
  15.225 +        return(-1);
  15.226 +      }
  15.227 +      pBufferDesc->iBufferUsage = BUFFER_EMPTY;
  15.228 +      pBufferDesc->pSDLAudioDevice = _this;
  15.229 +
  15.230 +      _this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize;
  15.231 +      _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer
  15.232 +      _this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of
  15.233 +                                            // audio data, but as we will continously send
  15.234 +                                            // audio data, there will be no end.:)
  15.235 +      memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize);
  15.236 +    }
  15.237 +  }
  15.238 +  _this->hidden->iNextFreeBuffer = 0;
  15.239 +  _this->hidden->iLastPlayedBuf = -1;
  15.240 +  // Create event semaphore
  15.241 +  if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR)
  15.242 +  {
  15.243 +    // Could not create event semaphore!
  15.244 +    {
  15.245 +      int i;
  15.246 +      for (i=0; i<iNumBufs; i++) free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
  15.247 +    }
  15.248 +    mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
  15.249 +    free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
  15.250 +    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  15.251 +    SDL_SetError("Could not create event semaphore");
  15.252 +    return(-1);
  15.253 +  }
  15.254 +
  15.255 +  // Store the new settings in global variables
  15.256 +  _this->hidden->iCurrDeviceOrd = iDeviceOrd;
  15.257 +  _this->hidden->iCurrFreq = iFreq;
  15.258 +  _this->hidden->iCurrBits = iBits;
  15.259 +  _this->hidden->iCurrChannels = iChannels;
  15.260 +  _this->hidden->iCurrNumBufs = iNumBufs;
  15.261 +  _this->hidden->iCurrBufSize = iBufSize;
  15.262 +
  15.263 +  return (0);
  15.264 +}
  15.265 +
  15.266 +
  15.267 +
  15.268 +void DART_ThreadInit(_THIS)
  15.269 +{
  15.270 +  return;
  15.271 +}
  15.272 +
  15.273 +/* This function waits until it is possible to write a full sound buffer */
  15.274 +void DART_WaitAudio(_THIS)
  15.275 +{
  15.276 +  int i;
  15.277 +  pMixBufferDesc pBufDesc;
  15.278 +  ULONG ulPostCount;
  15.279 +
  15.280 +  DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
  15.281 +  // If there is already an empty buffer, then return now!
  15.282 +  for (i=0; i<_this->hidden->iCurrNumBufs; i++)
  15.283 +  {
  15.284 +    pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm;
  15.285 +    if (pBufDesc->iBufferUsage == BUFFER_EMPTY)
  15.286 +      return;
  15.287 +  }
  15.288 +  // If there is no empty buffer, wait for one to be empty!
  15.289 +  DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important!
  15.290 +  return;
  15.291 +}
  15.292 +
  15.293 +void DART_PlayAudio(_THIS)
  15.294 +{
  15.295 +  int iFreeBuf = _this->hidden->iNextFreeBuffer;
  15.296 +  pMixBufferDesc pBufDesc;
  15.297 +
  15.298 +  pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm;
  15.299 +  pBufDesc->iBufferUsage = BUFFER_USED;
  15.300 +  // Send it to DART to be queued
  15.301 +  _this->hidden->MixSetupParms.pmixWrite(_this->hidden->MixSetupParms.ulMixHandle,
  15.302 +                                        &(_this->hidden->pMixBuffers[iFreeBuf]), 1);
  15.303 +
  15.304 +  _this->hidden->iLastPlayedBuf = iFreeBuf;
  15.305 +  iFreeBuf = (iFreeBuf+1) % _this->hidden->iCurrNumBufs;
  15.306 +  _this->hidden->iNextFreeBuffer = iFreeBuf;
  15.307 +}
  15.308 +
  15.309 +Uint8 *DART_GetAudioBuf(_THIS)
  15.310 +{
  15.311 +  int iFreeBuf;
  15.312 +  Uint8 *pResult;
  15.313 +  pMixBufferDesc pBufDesc;
  15.314 +
  15.315 +  if (_this)
  15.316 +  {
  15.317 +    if (_this->hidden)
  15.318 +    {
  15.319 +      iFreeBuf = _this->hidden->iNextFreeBuffer;
  15.320 +      pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm;
  15.321 +      
  15.322 +      if (pBufDesc)
  15.323 +      {
  15.324 +        if (pBufDesc->iBufferUsage == BUFFER_EMPTY)
  15.325 +        {
  15.326 +          pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer;
  15.327 +          return pResult; 
  15.328 +        }
  15.329 +      } else
  15.330 +        printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", pBufDesc);
  15.331 +    } else
  15.332 +      printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", _this->hidden);
  15.333 +  } else
  15.334 +    printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this);
  15.335 +  return NULL;
  15.336 +}
  15.337 +
  15.338 +void DART_WaitDone(_THIS)
  15.339 +{
  15.340 +  pMixBufferDesc pBufDesc;
  15.341 +  ULONG ulPostCount;
  15.342 +  APIRET rc;
  15.343 +
  15.344 +  pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm;
  15.345 +  rc = NO_ERROR;
  15.346 +  while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc==NO_ERROR))
  15.347 +  {
  15.348 +    DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
  15.349 +    rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important!
  15.350 +  }
  15.351 +}
  15.352 +
  15.353 +void DART_CloseAudio(_THIS)
  15.354 +{
  15.355 +  MCI_GENERIC_PARMS GenericParms;
  15.356 +  int rc;
  15.357 +
  15.358 +  // Stop DART playback
  15.359 +  rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, &GenericParms, 0);
  15.360 +  if (rc!=MCIERR_SUCCESS)
  15.361 +  {
  15.362 +#ifdef SFX_DEBUG_BUILD
  15.363 +    printf("Could not stop DART playback!\n");
  15.364 +    fflush(stdout);
  15.365 +#endif
  15.366 +  }
  15.367 +
  15.368 +  // Close event semaphore
  15.369 +  DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
  15.370 +
  15.371 +  // Free memory of buffer descriptions
  15.372 +  {
  15.373 +    int i;
  15.374 +    for (i=0; i<_this->hidden->iCurrNumBufs; i++) free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
  15.375 +  }
  15.376 +
  15.377 +  // Deallocate buffers
  15.378 +  rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
  15.379 +
  15.380 +  // Free bufferlist
  15.381 +  free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
  15.382 +
  15.383 +  // Close dart
  15.384 +  rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, &(GenericParms), 0);
  15.385 +}
  15.386 +
  15.387 +/* Audio driver bootstrap functions */
  15.388 +
  15.389 +int Audio_Available(void)
  15.390 +{
  15.391 +  return(1);
  15.392 +}
  15.393 +
  15.394 +void Audio_DeleteDevice(SDL_AudioDevice *device)
  15.395 +{
  15.396 +  free(device->hidden);
  15.397 +  free(device);
  15.398 +}
  15.399 +
  15.400 +SDL_AudioDevice *Audio_CreateDevice(int devindex)
  15.401 +{
  15.402 +  SDL_AudioDevice *this;
  15.403 +
  15.404 +  /* Initialize all variables that we clean on shutdown */
  15.405 +  this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
  15.406 +  if ( this )
  15.407 +  {
  15.408 +    memset(this, 0, (sizeof *this));
  15.409 +    this->hidden = (struct SDL_PrivateAudioData *)
  15.410 +      malloc((sizeof *this->hidden));
  15.411 +  }
  15.412 +  if ( (this == NULL) || (this->hidden == NULL) )
  15.413 +  {
  15.414 +    SDL_OutOfMemory();
  15.415 +    if ( this )
  15.416 +      free(this);
  15.417 +    return(0);
  15.418 +  }
  15.419 +  memset(this->hidden, 0, (sizeof *this->hidden));
  15.420 +
  15.421 +  /* Set the function pointers */
  15.422 +  this->OpenAudio = DART_OpenAudio;
  15.423 +  this->ThreadInit = DART_ThreadInit;
  15.424 +  this->WaitAudio = DART_WaitAudio;
  15.425 +  this->PlayAudio = DART_PlayAudio;
  15.426 +  this->GetAudioBuf = DART_GetAudioBuf;
  15.427 +  this->WaitDone = DART_WaitDone;
  15.428 +  this->CloseAudio = DART_CloseAudio;
  15.429 +
  15.430 +  this->free = Audio_DeleteDevice;
  15.431 +
  15.432 +  return this;
  15.433 +}
  15.434 +
  15.435 +AudioBootStrap DART_bootstrap = {
  15.436 +	"dart", "OS/2 Direct Audio RouTines (DART)",
  15.437 +	Audio_Available, Audio_CreateDevice
  15.438 +};
  15.439 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/audio/dart/SDL_dart.h	Wed Nov 23 07:29:56 2005 +0000
    16.3 @@ -0,0 +1,67 @@
    16.4 +/*
    16.5 +    SDL - Simple DirectMedia Layer
    16.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    16.7 +
    16.8 +    This library is free software; you can redistribute it and/or
    16.9 +    modify it under the terms of the GNU Library General Public
   16.10 +    License as published by the Free Software Foundation; either
   16.11 +    version 2 of the License, or (at your option) any later version.
   16.12 +
   16.13 +    This library is distributed in the hope that it will be useful,
   16.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16.16 +    Library General Public License for more details.
   16.17 +
   16.18 +    You should have received a copy of the GNU Library General Public
   16.19 +    License along with this library; if not, write to the Free
   16.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   16.21 +
   16.22 +    Sam Lantinga
   16.23 +    slouken@libsdl.org
   16.24 +*/
   16.25 +
   16.26 +#ifdef SAVE_RCSID
   16.27 +static char rcsid =
   16.28 + "@(#) $Id$";
   16.29 +#endif
   16.30 +
   16.31 +#ifndef _SDL_lowaudio_h
   16.32 +#define _SDL_lowaudio_h
   16.33 +
   16.34 +#include "SDL_sysaudio.h"
   16.35 +
   16.36 +#define INCL_TYPES
   16.37 +#define INCL_DOSSEMAPHORES
   16.38 +#define INCL_DOSRESOURCES
   16.39 +#define INCL_DOSMISC
   16.40 +#define INCL_DOSERRORS
   16.41 +
   16.42 +#define INCL_OS2MM
   16.43 +#define INCL_MMIOOS2
   16.44 +#define INCL_MCIOS2
   16.45 +#include <os2.h>
   16.46 +#include <os2me.h>     // DART stuff and MMIO stuff
   16.47 +
   16.48 +/* Hidden "this" pointer for the audio functions */
   16.49 +#define _THIS	SDL_AudioDevice *_this
   16.50 +
   16.51 +/* The DirectSound objects */
   16.52 +struct SDL_PrivateAudioData
   16.53 +{
   16.54 +  int iCurrDeviceOrd;
   16.55 +  int iCurrFreq;
   16.56 +  int iCurrBits;
   16.57 +  int iCurrChannels;
   16.58 +  int iCurrNumBufs;
   16.59 +  int iCurrBufSize;
   16.60 +
   16.61 +  int iLastPlayedBuf;
   16.62 +  int iNextFreeBuffer;
   16.63 +
   16.64 +  MCI_BUFFER_PARMS BufferParms;     // Sound buffer parameters
   16.65 +  MCI_MIX_BUFFER *pMixBuffers;      // Sound buffers
   16.66 +  MCI_MIXSETUP_PARMS MixSetupParms; // Mixer setup parameters
   16.67 +  HEV hevAudioBufferPlayed;         // Event semaphore to indicate that an audio buffer has been played by DART
   16.68 +};
   16.69 +
   16.70 +#endif /* _SDL_lowaudio_h */
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/cdrom/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    17.3 @@ -0,0 +1,30 @@
    17.4 +#=============================================================================
    17.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    17.6 +#
    17.7 +# Makefile for OS/2 System CDROM support
    17.8 +#=============================================================================
    17.9 +
   17.10 +object_files=SDL_syscdrom.obj SDL_cdrom.obj
   17.11 +ExtraCFlags=
   17.12 +
   17.13 +#
   17.14 +#==============================================================================
   17.15 +#
   17.16 +!include ..\..\Watcom.mif
   17.17 +
   17.18 +.before
   17.19 +    set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
   17.20 +
   17.21 +all : $(object_files)
   17.22 +
   17.23 +SDL_syscdrom.obj : .AUTODEPEND
   17.24 +    wcc386 os2\SDL_syscdrom.c $(cflags)
   17.25 +
   17.26 +SDL_cdrom.obj : .AUTODEPEND
   17.27 +    wcc386 SDL_cdrom.c $(cflags)
   17.28 +
   17.29 +clean : .SYMBOLIC
   17.30 +        @if exist *.obj del *.obj
   17.31 +        @if exist *.map del *.map
   17.32 +        @if exist *.res del *.res
   17.33 +        @if exist *.lst del *.lst
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/cdrom/os2/SDL_syscdrom.c	Wed Nov 23 07:29:56 2005 +0000
    18.3 @@ -0,0 +1,399 @@
    18.4 +/*
    18.5 +    SDL - Simple DirectMedia Layer
    18.6 +    Copyright (C) 1997-2004 Sam Lantinga
    18.7 +
    18.8 +    This library is free software; you can redistribute it and/or
    18.9 +    modify it under the terms of the GNU Library General Public
   18.10 +    License as published by the Free Software Foundation; either
   18.11 +    version 2 of the License, or (at your option) any later version.
   18.12 +
   18.13 +    This library is distributed in the hope that it will be useful,
   18.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   18.16 +    Library General Public License for more details.
   18.17 +
   18.18 +    You should have received a copy of the GNU Library General Public
   18.19 +    License along with this library; if not, write to the Free
   18.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   18.21 +
   18.22 +    Sam Lantinga
   18.23 +    slouken@libsdl.org
   18.24 +*/
   18.25 +
   18.26 +#ifdef SAVE_RCSID
   18.27 +static char rcsid =
   18.28 + "@(#) $Id$";
   18.29 +#endif
   18.30 +
   18.31 +/* Functions for system-level CD-ROM audio control */
   18.32 +
   18.33 +#define INCL_MCIOS2
   18.34 +#include <os2.h>
   18.35 +#include <os2me.h>
   18.36 +#include <stdio.h>
   18.37 +#include <stdlib.h>
   18.38 +#include <string.h>
   18.39 +
   18.40 +#include "SDL_error.h"
   18.41 +#include "SDL_cdrom.h"
   18.42 +#include "SDL_syscdrom.h"
   18.43 +
   18.44 +/* Size of MCI result buffer (in bytes) */
   18.45 +#define MCI_CMDRETBUFSIZE	128
   18.46 +
   18.47 +/* The maximum number of CD-ROM drives we'll detect */
   18.48 +#define MAX_DRIVES	16	
   18.49 +
   18.50 +/* A list of available CD-ROM drives */
   18.51 +static char *SDL_cdlist[MAX_DRIVES];
   18.52 +//static dev_t SDL_cdmode[MAX_DRIVES];
   18.53 +
   18.54 +/* The system-dependent CD control functions */
   18.55 +static const char *SDL_SYS_CDName(int drive);
   18.56 +static int SDL_SYS_CDOpen(int drive);
   18.57 +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
   18.58 +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
   18.59 +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
   18.60 +static int SDL_SYS_CDPause(SDL_CD *cdrom);
   18.61 +static int SDL_SYS_CDResume(SDL_CD *cdrom);
   18.62 +static int SDL_SYS_CDStop(SDL_CD *cdrom);
   18.63 +static int SDL_SYS_CDEject(SDL_CD *cdrom);
   18.64 +static void SDL_SYS_CDClose(SDL_CD *cdrom);
   18.65 +
   18.66 +/* MCI Timing Functions */
   18.67 +#define	MCI_MMTIMEPERSECOND		3000
   18.68 +#define	FRAMESFROMMM(mmtime)		(((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND)
   18.69 +
   18.70 +
   18.71 +/* Ready for MCI CDAudio Devices */
   18.72 +int  SDL_SYS_CDInit(void)
   18.73 +{
   18.74 +int i; /* generig counter */
   18.75 +MCI_SYSINFO_PARMS		msp;	/* Structure to MCI SysInfo parameters */
   18.76 +CHAR 						SysInfoRet[MCI_CMDRETBUFSIZE];	/* Buffer for MCI Command result */
   18.77 +
   18.78 +/* Fill in our driver capabilities */
   18.79 +SDL_CDcaps.Name = SDL_SYS_CDName;
   18.80 +SDL_CDcaps.Open = SDL_SYS_CDOpen;
   18.81 +SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
   18.82 +SDL_CDcaps.Status = SDL_SYS_CDStatus;
   18.83 +SDL_CDcaps.Play = SDL_SYS_CDPlay;
   18.84 +SDL_CDcaps.Pause = SDL_SYS_CDPause;
   18.85 +SDL_CDcaps.Resume = SDL_SYS_CDResume;
   18.86 +SDL_CDcaps.Stop = SDL_SYS_CDStop;
   18.87 +SDL_CDcaps.Eject = SDL_SYS_CDEject;
   18.88 +SDL_CDcaps.Close = SDL_SYS_CDClose;
   18.89 +
   18.90 +/* Get the number of CD ROMs in the System */
   18.91 +/* Clean SysInfo structure */
   18.92 +memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));
   18.93 +/* Prepare structure to Ask Numer of Audio CDs */
   18.94 +msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO;	/* CD Audio Type */
   18.95 +msp.pszReturn = (PSZ)&SysInfoRet; 	/* Return Structure */
   18.96 +msp.ulRetSize = MCI_CMDRETBUFSIZE; 	/* Size of ret struct */
   18.97 +if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
   18.98 +SDL_numcds = atoi(SysInfoRet);
   18.99 +if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */
  18.100 +
  18.101 +/* Get and Add their system name to the SDL_cdlist */
  18.102 +msp.pszReturn = (PSZ)&SysInfoRet; 				/* Return Structure */
  18.103 +msp.ulRetSize = MCI_CMDRETBUFSIZE; 			/* Size of ret struct */
  18.104 +msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO;		/* CD Audio Type */
  18.105 +for (i=0; i<SDL_numcds; i++)
  18.106 +	{
  18.107 +	msp.ulNumber = i+1;
  18.108 +	mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0);
  18.109 +	SDL_cdlist[i] = (char *)malloc(strlen(SysInfoRet)+1);
  18.110 +	if ( SDL_cdlist[i] == NULL )
  18.111 +		{
  18.112 +		SDL_OutOfMemory();
  18.113 +		return(-1);
  18.114 +		}
  18.115 +	strcpy(SDL_cdlist[i], SysInfoRet);
  18.116 +	}
  18.117 +return(0);
  18.118 +}
  18.119 +
  18.120 +/* Return CDAudio System Dependent Device Name - Ready for MCI*/
  18.121 +static const char *SDL_SYS_CDName(int drive)
  18.122 +{
  18.123 +return(SDL_cdlist[drive]);
  18.124 +}
  18.125 +
  18.126 +/* Open CDAudio Device - Ready for MCI */
  18.127 +static int SDL_SYS_CDOpen(int drive)
  18.128 +{
  18.129 +MCI_OPEN_PARMS	mop;
  18.130 +MCI_SET_PARMS msp;
  18.131 +MCI_GENERIC_PARMS mgp;
  18.132 +
  18.133 +/* Open the device */
  18.134 +mop.hwndCallback = (HWND)NULL;		// None
  18.135 +mop.usDeviceID = (USHORT)NULL;		// Will be returned.
  18.136 +mop.pszDeviceType = (PSZ)SDL_cdlist[drive];		// CDAudio Device
  18.137 +if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
  18.138 +/* Set time format */
  18.139 +msp.hwndCallback = (HWND)NULL;		// None
  18.140 +msp.ulTimeFormat = MCI_FORMAT_MSF;	// Minute : Second : Frame structure
  18.141 +msp.ulSpeedFormat = (ULONG)NULL;		// No change
  18.142 +msp.ulAudio = (ULONG)NULL;				// No Channel
  18.143 +msp.ulLevel = (ULONG)NULL;				// No Volume
  18.144 +msp.ulOver = (ULONG)NULL;				// No Delay
  18.145 +msp.ulItem = (ULONG)NULL;				// No item
  18.146 +msp.ulValue = (ULONG)NULL;				// No value for item flag
  18.147 +if (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID);
  18.148 +/* Error setting time format? - Close opened device */
  18.149 +mgp.hwndCallback = (HWND)NULL;		// None
  18.150 +mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);
  18.151 +return(CD_ERROR);
  18.152 +}
  18.153 +
  18.154 +/* Get CD Table Of Contents - Ready for MCI */
  18.155 +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
  18.156 +{
  18.157 +MCI_TOC_PARMS mtp;
  18.158 +MCI_STATUS_PARMS msp;
  18.159 +MCI_TOC_REC * mtr;
  18.160 +INT i;
  18.161 +
  18.162 +/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */
  18.163 +if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;
  18.164 +
  18.165 +/* Get Number of Tracks */
  18.166 +msp.hwndCallback = (HWND)NULL; /* None */
  18.167 +msp.ulReturn = (ULONG)NULL; /* We want this information */
  18.168 +msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;
  18.169 +msp.ulValue = (ULONG)NULL; /* No additional information */
  18.170 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
  18.171 +cdrom->numtracks = msp.ulReturn;
  18.172 +if ( cdrom->numtracks > SDL_MAX_TRACKS )
  18.173 +	{
  18.174 +	cdrom->numtracks = SDL_MAX_TRACKS;
  18.175 +	}
  18.176 +/* Alocate space for TOC data */
  18.177 +mtr = (MCI_TOC_REC *)malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));
  18.178 +if ( mtr == NULL )
  18.179 +	{
  18.180 +	SDL_OutOfMemory();
  18.181 +	return(-1);
  18.182 +	}
  18.183 +/* Get TOC from CD */
  18.184 +mtp.pBuf = mtr;
  18.185 +mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);
  18.186 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS)
  18.187 +	{
  18.188 +	SDL_OutOfMemory();
  18.189 +	free(mtr);
  18.190 +	return(CD_ERROR);
  18.191 +	}
  18.192 +/* Fill SDL Tracks Structure */
  18.193 +for (i=0; i<cdrom->numtracks; i++)
  18.194 +	{
  18.195 +	/* Set Track ID */
  18.196 +	cdrom->track[i].id = (mtr+i)->TrackNum;
  18.197 +	/* Set Track Type */
  18.198 +	msp.hwndCallback = (HWND)NULL; /* None */
  18.199 +	msp.ulReturn = (ULONG)NULL; /* We want this information */
  18.200 +	msp.ulItem = MCI_CD_STATUS_TRACK_TYPE;
  18.201 +	msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */
  18.202 +	if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS)
  18.203 +		{
  18.204 +		free(mtr);
  18.205 +		return (CD_ERROR);
  18.206 +		}
  18.207 +	if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK;
  18.208 +	else cdrom->track[i].type = SDL_DATA_TRACK;
  18.209 +	/* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */
  18.210 +	cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr);
  18.211 +	/* Set Track Offset */
  18.212 +	cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr);
  18.213 +	}
  18.214 +free(mtr);
  18.215 +return(0);
  18.216 +}
  18.217 +
  18.218 +
  18.219 +/* Get CD-ROM status - Ready for MCI */
  18.220 +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
  18.221 +{
  18.222 +CDstatus status;
  18.223 +MCI_STATUS_PARMS msp;
  18.224 +
  18.225 +/* Get Status from MCI */
  18.226 +msp.hwndCallback = (HWND)NULL; /* None */
  18.227 +msp.ulReturn = (ULONG)NULL; /* We want this information */
  18.228 +msp.ulItem = MCI_STATUS_MODE;
  18.229 +msp.ulValue = (ULONG)NULL; /* No additional information */
  18.230 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;
  18.231 +else
  18.232 +	{
  18.233 +	switch(msp.ulReturn)
  18.234 +		{
  18.235 +		case	MCI_MODE_NOT_READY:
  18.236 +			status = CD_TRAYEMPTY;
  18.237 +			break;
  18.238 +		case	MCI_MODE_PAUSE:
  18.239 +			status = CD_PAUSED;
  18.240 +			break;
  18.241 +		case	MCI_MODE_PLAY:
  18.242 +			status = CD_PLAYING;
  18.243 +			break;
  18.244 +		case	MCI_MODE_STOP:
  18.245 +			status = CD_STOPPED;
  18.246 +			break;
  18.247 +		/* These cases should not occour */
  18.248 +		case	MCI_MODE_RECORD:
  18.249 +		case	MCI_MODE_SEEK:
  18.250 +		default:
  18.251 +			status = CD_ERROR;
  18.252 +			break;
  18.253 +		}
  18.254 +	}
  18.255 +
  18.256 +/* Determine position */
  18.257 +if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */
  18.258 +	{
  18.259 +		if ((status == CD_PLAYING) || (status == CD_PAUSED))
  18.260 +		{
  18.261 +		/* Get Position */
  18.262 +		msp.hwndCallback = (HWND)NULL; /* None */
  18.263 +		msp.ulReturn = (ULONG)NULL; /* We want this information */
  18.264 +		msp.ulItem = MCI_STATUS_POSITION;
  18.265 +		msp.ulValue = (ULONG)NULL; /* No additiona info */
  18.266 +		if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR);
  18.267 +		/* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */
  18.268 +		*position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn));
  18.269 +		}
  18.270 +	else *position = 0;
  18.271 +	}
  18.272 +return(status);
  18.273 +}
  18.274 +
  18.275 +/* Start play - Ready for MCI */
  18.276 +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
  18.277 +{
  18.278 +MCI_GENERIC_PARMS mgp;
  18.279 +MCI_STATUS_PARMS msp;
  18.280 +MCI_PLAY_PARMS	mpp;
  18.281 +ULONG min,sec,frm;
  18.282 +
  18.283 +/* Start MSF */
  18.284 +FRAMES_TO_MSF(start, &min, &sec, &frm);
  18.285 +MSF_MINUTE(mpp.ulFrom) = min;
  18.286 +MSF_SECOND(mpp.ulFrom) = sec;
  18.287 +MSF_FRAME(mpp.ulFrom) = frm;
  18.288 +/* End MSF */
  18.289 +FRAMES_TO_MSF(start+length, &min, &sec, &frm);
  18.290 +MSF_MINUTE(mpp.ulTo) = min;
  18.291 +MSF_SECOND(mpp.ulTo) = sec;
  18.292 +MSF_FRAME(mpp.ulTo) = frm;
  18.293 +#ifdef DEBUG_CDROM
  18.294 +	fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
  18.295 +	playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
  18.296 +	playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
  18.297 +#endif
  18.298 +/* Verifies if it is paused first... and if it is, unpause before stopping it. */
  18.299 +msp.hwndCallback = (HWND)NULL; /* None */
  18.300 +msp.ulReturn = (ULONG)NULL; /* We want this information */
  18.301 +msp.ulItem = MCI_STATUS_MODE;
  18.302 +msp.ulValue = (ULONG)NULL; /* No additional information */
  18.303 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
  18.304 +	{
  18.305 +	if (msp.ulReturn == MCI_MODE_PAUSE)
  18.306 +		{
  18.307 +		mgp.hwndCallback = (HWND)NULL;		// None
  18.308 +		mciSendCommand(cdrom->id,MCI_RESUME,NULL,&mgp, 0);
  18.309 +		}
  18.310 +	}
  18.311 +/* Now play it. */
  18.312 +mpp.hwndCallback = (HWND)NULL;		// We do not want the info. temp
  18.313 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;
  18.314 +return (CD_ERROR);
  18.315 +}
  18.316 +
  18.317 +/* Pause play - Ready for MCI */
  18.318 +static int SDL_SYS_CDPause(SDL_CD *cdrom)
  18.319 +{
  18.320 +MCI_GENERIC_PARMS mgp;
  18.321 +
  18.322 +mgp.hwndCallback = (HWND)NULL;		// None
  18.323 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
  18.324 +return(CD_ERROR);
  18.325 +}
  18.326 +
  18.327 +/* Resume play - Ready for MCI */
  18.328 +static int SDL_SYS_CDResume(SDL_CD *cdrom)
  18.329 +{
  18.330 +MCI_GENERIC_PARMS mgp;
  18.331 +
  18.332 +mgp.hwndCallback = (HWND)NULL;		// None
  18.333 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
  18.334 +return(CD_ERROR);
  18.335 +}
  18.336 +
  18.337 +/* Stop play - Ready for MCI */
  18.338 +static int SDL_SYS_CDStop(SDL_CD *cdrom)
  18.339 +{
  18.340 +MCI_GENERIC_PARMS mgp;
  18.341 +MCI_STATUS_PARMS msp;
  18.342 +
  18.343 +/* Verifies if it is paused first... and if it is, unpause before stopping it. */
  18.344 +msp.hwndCallback = (HWND)NULL; /* None */
  18.345 +msp.ulReturn = (ULONG)NULL; /* We want this information */
  18.346 +msp.ulItem = MCI_STATUS_MODE;
  18.347 +msp.ulValue = (ULONG)NULL; /* No additional information */
  18.348 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
  18.349 +	{
  18.350 +	if (msp.ulReturn == MCI_MODE_PAUSE)
  18.351 +		{
  18.352 +		mgp.hwndCallback = (HWND)NULL;		// None
  18.353 +		mciSendCommand(cdrom->id,MCI_RESUME,NULL,&mgp, 0);
  18.354 +		}
  18.355 +	}
  18.356 +/* Now stops the media */
  18.357 +mgp.hwndCallback = (HWND)NULL;		// None
  18.358 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
  18.359 +return(CD_ERROR);
  18.360 +}
  18.361 +
  18.362 +/* Eject the CD-ROM - Ready for MCI */
  18.363 +static int SDL_SYS_CDEject(SDL_CD *cdrom)
  18.364 +{
  18.365 +MCI_SET_PARMS msp;
  18.366 +
  18.367 +msp.hwndCallback = (HWND)NULL;		// None
  18.368 +msp.ulTimeFormat = (ULONG)NULL;		// No change
  18.369 +msp.ulSpeedFormat = (ULONG)NULL;		// No change
  18.370 +msp.ulAudio = (ULONG)NULL;				// No Channel
  18.371 +msp.ulLevel = (ULONG)NULL;				// No Volume
  18.372 +msp.ulOver = (ULONG)NULL;				// No Delay
  18.373 +msp.ulItem = (ULONG)NULL;					// No item
  18.374 +msp.ulValue = (ULONG)NULL;					// No value for item flag
  18.375 +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;
  18.376 +return(CD_ERROR);
  18.377 +}
  18.378 +
  18.379 +/* Close the CD-ROM handle - Ready for MCI */
  18.380 +static void SDL_SYS_CDClose(SDL_CD *cdrom)
  18.381 +{
  18.382 +MCI_GENERIC_PARMS mgp;
  18.383 +
  18.384 +mgp.hwndCallback = (HWND)NULL;		// None
  18.385 +mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);
  18.386 +}
  18.387 +
  18.388 +/* Finalize CDROM Subsystem - Ready for MCI */
  18.389 +void SDL_SYS_CDQuit(void)
  18.390 +{
  18.391 +int i;
  18.392 +
  18.393 +if ( SDL_numcds > 0 )
  18.394 +	{
  18.395 +	for ( i=0; i<SDL_numcds; ++i )
  18.396 +		{
  18.397 +		free(SDL_cdlist[i]);
  18.398 +		}
  18.399 +	SDL_numcds = 0;
  18.400 +	}
  18.401 +}
  18.402 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/cpuinfo/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    19.3 @@ -0,0 +1,27 @@
    19.4 +#=============================================================================
    19.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    19.6 +#
    19.7 +# Makefile for cpuinfo
    19.8 +#=============================================================================
    19.9 +
   19.10 +object_files=SDL_cpuinfo.obj
   19.11 +
   19.12 +# We have to define the following so the assembly parts can be
   19.13 +# compiled by Watcom, too!
   19.14 +ExtraCFlags=-d_MSC_VER
   19.15 +
   19.16 +#
   19.17 +#==============================================================================
   19.18 +#
   19.19 +!include ..\..\Watcom.mif
   19.20 +
   19.21 +.before
   19.22 +    set include=$(%os2tk)\h;$(%include);../../include
   19.23 +
   19.24 +all : $(object_files)
   19.25 +
   19.26 +clean : .SYMBOLIC
   19.27 +        @if exist *.obj del *.obj
   19.28 +        @if exist *.map del *.map
   19.29 +        @if exist *.res del *.res
   19.30 +        @if exist *.lst del *.lst
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/endian/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    20.3 @@ -0,0 +1,24 @@
    20.4 +#=============================================================================
    20.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    20.6 +#
    20.7 +# Makefile for endianness
    20.8 +#=============================================================================
    20.9 +
   20.10 +object_files=SDL_endian.obj
   20.11 +ExtraCFlags=
   20.12 +
   20.13 +#
   20.14 +#==============================================================================
   20.15 +#
   20.16 +!include ..\..\Watcom.mif
   20.17 +
   20.18 +.before
   20.19 +    set include=$(%os2tk)\h;$(%include);../../include
   20.20 +
   20.21 +all : $(object_files)
   20.22 +
   20.23 +clean : .SYMBOLIC
   20.24 +        @if exist *.obj del *.obj
   20.25 +        @if exist *.map del *.map
   20.26 +        @if exist *.res del *.res
   20.27 +        @if exist *.lst del *.lst
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/events/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    21.3 @@ -0,0 +1,24 @@
    21.4 +#=============================================================================
    21.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    21.6 +#
    21.7 +# Makefile for events
    21.8 +#=============================================================================
    21.9 +
   21.10 +object_files=SDL_active.obj SDL_events.obj SDL_expose.obj SDL_keyboard.obj SDL_mouse.obj SDL_quit.obj SDL_resize.obj
   21.11 +ExtraCFlags=-dUSE_DOSSETPRIORITY
   21.12 +
   21.13 +#
   21.14 +#==============================================================================
   21.15 +#
   21.16 +!include ..\..\Watcom.mif
   21.17 +
   21.18 +.before
   21.19 +    set include=$(%os2tk)\h;$(%include);../../include;../timer;../joystick;../video;
   21.20 +
   21.21 +all : $(object_files)
   21.22 +
   21.23 +clean : .SYMBOLIC
   21.24 +        @if exist *.obj del *.obj
   21.25 +        @if exist *.map del *.map
   21.26 +        @if exist *.res del *.res
   21.27 +        @if exist *.lst del *.lst
    22.1 --- a/src/events/SDL_events.c	Wed Nov 23 07:23:48 2005 +0000
    22.2 +++ b/src/events/SDL_events.c	Wed Nov 23 07:29:56 2005 +0000
    22.3 @@ -89,9 +89,28 @@
    22.4  	}
    22.5  }
    22.6  
    22.7 +#ifdef __OS2__
    22.8 +/*
    22.9 + * We'll increase the priority of GobbleEvents thread, so it will process
   22.10 + *  events in time for sure! For this, we need the DosSetPriority() API
   22.11 + *  from the os2.h include file.
   22.12 + */
   22.13 +#define INCL_DOSPROCESS
   22.14 +#include <os2.h>
   22.15 +#include <time.h>
   22.16 +#endif
   22.17 +
   22.18  static int SDL_GobbleEvents(void *unused)
   22.19  {
   22.20  	event_thread = SDL_ThreadID();
   22.21 +
   22.22 +#ifdef __OS2__
   22.23 +#ifdef USE_DOSSETPRIORITY
   22.24 +	/* Increase thread priority, so it will process events in time for sure! */
   22.25 +	DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +16, 0);
   22.26 +#endif
   22.27 +#endif
   22.28 +
   22.29  	while ( SDL_EventQ.active ) {
   22.30  		SDL_VideoDevice *video = current_video;
   22.31  		SDL_VideoDevice *this  = current_video;
    23.1 --- a/src/events/SDL_resize.c	Wed Nov 23 07:23:48 2005 +0000
    23.2 +++ b/src/events/SDL_resize.c	Wed Nov 23 07:29:56 2005 +0000
    23.3 @@ -45,8 +45,11 @@
    23.4  	SDL_Event events[32];
    23.5  
    23.6  	/* See if this event would change the video surface */
    23.7 -	if ( !w || !h ||
    23.8 -	     ((last_resize.w == w) && (last_resize.h == h)) ) {
    23.9 +	if ( !w || !h
   23.10 +#ifndef __OS2__
   23.11 +            || ((last_resize.w == w) && (last_resize.h == h))
   23.12 +#endif
   23.13 +    ) {
   23.14  		return(0);
   23.15  	}
   23.16          last_resize.w = w;
    24.1 --- a/src/events/SDL_sysevents.h	Wed Nov 23 07:23:48 2005 +0000
    24.2 +++ b/src/events/SDL_sysevents.h	Wed Nov 23 07:29:56 2005 +0000
    24.3 @@ -44,3 +44,7 @@
    24.4  #ifdef macintosh	/* MacOS 7/8 don't support preemptive multi-tasking */
    24.5  #define CANT_THREAD_EVENTS
    24.6  #endif
    24.7 +
    24.8 +#ifdef __OS2__		/* The OS/2 event loop runs in a separate thread */
    24.9 +#define MUST_THREAD_EVENTS
   24.10 +#endif
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/src/file/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    25.3 @@ -0,0 +1,24 @@
    25.4 +#=============================================================================
    25.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    25.6 +#
    25.7 +# Makefile for file
    25.8 +#=============================================================================
    25.9 +
   25.10 +object_files=SDL_rwops.obj
   25.11 +ExtraCFlags=
   25.12 +
   25.13 +#
   25.14 +#==============================================================================
   25.15 +#
   25.16 +!include ..\..\Watcom.mif
   25.17 +
   25.18 +.before
   25.19 +    set include=$(%os2tk)\h;$(%include);../../include
   25.20 +
   25.21 +all : $(object_files)
   25.22 +
   25.23 +clean : .SYMBOLIC
   25.24 +        @if exist *.obj del *.obj
   25.25 +        @if exist *.map del *.map
   25.26 +        @if exist *.res del *.res
   25.27 +        @if exist *.lst del *.lst
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/src/joystick/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    26.3 @@ -0,0 +1,27 @@
    26.4 +#=============================================================================
    26.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    26.6 +#
    26.7 +# Makefile for joystick (using the dummy joystick driver)
    26.8 +#=============================================================================
    26.9 +
   26.10 +object_files=SDL_joystick.obj SDL_sysjoystick.obj
   26.11 +ExtraCFlags=
   26.12 +
   26.13 +#
   26.14 +#==============================================================================
   26.15 +#
   26.16 +!include ..\..\Watcom.mif
   26.17 +
   26.18 +.before
   26.19 +    set include=$(%os2tk)\h;$(%include);../../include;./os2;../;../events;
   26.20 +
   26.21 +all : $(object_files)
   26.22 +
   26.23 +SDL_sysjoystick.obj: .AUTODEPEND
   26.24 +    wcc386 os2\SDL_sysjoystick.c $(cflags)
   26.25 +
   26.26 +clean : .SYMBOLIC
   26.27 +        @if exist *.obj del *.obj
   26.28 +        @if exist *.map del *.map
   26.29 +        @if exist *.res del *.res
   26.30 +        @if exist *.lst del *.lst
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/src/joystick/os2/SDL_sysjoystick.c	Wed Nov 23 07:29:56 2005 +0000
    27.3 @@ -0,0 +1,669 @@
    27.4 +/*
    27.5 +    SDL - Simple DirectMedia Layer
    27.6 +    Copyright (C) 1997-2004 Sam Lantinga
    27.7 +
    27.8 +    This library is free software; you can redistribute it and/or
    27.9 +    modify it under the terms of the GNU Library General Public
   27.10 +    License as published by the Free Software Foundation; either
   27.11 +    version 2 of the License, or (at your option) any later version.
   27.12 +
   27.13 +    This library is distributed in the hope that it will be useful,
   27.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   27.16 +    Library General Public License for more details.
   27.17 +
   27.18 +    You should have received a copy of the GNU Library General Public
   27.19 +    License along with this library; if not, write to the Free
   27.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27.21 +
   27.22 +    Sam Lantinga
   27.23 +    slouken@libsdl.org
   27.24 +*/
   27.25 +
   27.26 +#ifdef SAVE_RCSID
   27.27 +static char rcsid =
   27.28 + "@(#) $Id$";
   27.29 +#endif
   27.30 +
   27.31 +/* OS/2 Joystick driver, contributed by Daniel Caetano */
   27.32 +
   27.33 +#include <stdlib.h>
   27.34 +#include <stdio.h>
   27.35 +#include <mem.h>
   27.36 +
   27.37 +#define INCL_DOSDEVICES
   27.38 +#define INCL_DOSDEVIOCTL
   27.39 +#define INCL_DOSMEMMGR
   27.40 +#include <os2.h>
   27.41 +#include "joyos2.h"
   27.42 +
   27.43 +#include "SDL_error.h"
   27.44 +#include "SDL_joystick.h"
   27.45 +#include "SDL_sysjoystick.h"
   27.46 +#include "SDL_joystick_c.h"
   27.47 +
   27.48 +HFILE hJoyPort = NULL;		/* Joystick GAME$ Port Address */
   27.49 +#define MAX_JOYSTICKS	2	/* Maximum of two joysticks */
   27.50 +#define MAX_AXES	4			/* each joystick can have up to 4 axes */
   27.51 +#define MAX_BUTTONS	8		/* 8 buttons */
   27.52 +#define MAX_HATS	0			/* 0 hats - OS/2 doesn't support it */
   27.53 +#define MAX_BALLS	0			/* and 0 balls - OS/2 doesn't support it */
   27.54 +#define AXIS_MIN -32768		/* minimum value for axes coordinate */
   27.55 +#define AXIS_MAX 32767		/* maximum value for axes coordinate */
   27.56 +#define MAX_JOYNAME	128	/* Joystick name may have 128 characters */
   27.57 +/* limit axes to 256 possible positions to filter out noise */
   27.58 +#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256)
   27.59 +/* Calc Button Flag for buttons A to D */
   27.60 +#define JOY_BUTTON_FLAG(n) (1<<n)
   27.61 +
   27.62 +/* Joystick data... hold information about detected devices */
   27.63 +struct _SYS_JoyData
   27.64 +{
   27.65 +Sint8					id;								// Device ID
   27.66 +char					szDeviceName[MAX_JOYNAME];	// Device Name
   27.67 +char					axes;								// Number of axes
   27.68 +char					buttons;							// Number of buttons
   27.69 +char					hats;								// Number of buttons
   27.70 +char					balls;							// Number of buttons
   27.71 +int					axes_min[MAX_AXES];			// minimum callibration value for axes
   27.72 +int					axes_med[MAX_AXES];			// medium callibration value for axes
   27.73 +int					axes_max[MAX_AXES];			// maximum callibration value for axes
   27.74 +int					buttoncalc[4];					// Used for buttons 5, 6, 7 and 8.
   27.75 +} SYS_JoyData[MAX_JOYSTICKS];
   27.76 +
   27.77 +
   27.78 +/* Structure used to convert data from OS/2 driver format to SDL format */
   27.79 +struct joystick_hwdata
   27.80 +{
   27.81 +Sint8					id;
   27.82 +struct _transaxes
   27.83 +	{
   27.84 +	int offset;					/* Center Offset */
   27.85 +	float scale1;				/* Center to left/up Scale */
   27.86 +	float scale2;				/* Center to right/down Scale */
   27.87 +	} transaxes[MAX_AXES];
   27.88 +};
   27.89 +
   27.90 +/* Structure used to get values from Joystick Environment Variable */
   27.91 +struct _joycfg
   27.92 +{
   27.93 +char	name[MAX_JOYNAME];
   27.94 +unsigned int	axes;
   27.95 +unsigned int	buttons;
   27.96 +unsigned int	hats;
   27.97 +unsigned int	balls;
   27.98 +};
   27.99 +
  27.100 +/* OS/2 Implementation Function Prototypes */
  27.101 +APIRET joyPortOpen(HFILE * hGame);
  27.102 +void joyPortClose(HFILE * hGame);
  27.103 +int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars);
  27.104 +int joyGetEnv(struct _joycfg * joydata);
  27.105 +
  27.106 +
  27.107 +
  27.108 +/************************************************************************/
  27.109 +/* Function to scan the system for joysticks.									*/
  27.110 +/* This function should set SDL_numjoysticks to the number of available	*/
  27.111 +/* joysticks.  Joystick 0 should be the system default joystick.			*/
  27.112 +/* It should return 0, or -1 on an unrecoverable fatal error.				*/
  27.113 +/************************************************************************/
  27.114 +int SDL_SYS_JoystickInit(void)
  27.115 +{
  27.116 +APIRET rc;											/* Generic OS/2 return code */
  27.117 +GAME_PORT_STRUCT	stJoyStatus;				/* Joystick Status Structure */
  27.118 +GAME_PARM_STRUCT	stGameParms;				/* Joystick Parameter Structure */
  27.119 +GAME_CALIB_STRUCT	stGameCalib;				/* Calibration Struct */
  27.120 +ULONG ulDataLen;									/* Size of data */
  27.121 +ULONG ulLastTick;						/* Tick Counter for timing operations */
  27.122 +Uint8 maxdevs;										/* Maximum number of devices */
  27.123 +Uint8 numdevs;										/* Number of present devices */
  27.124 +Uint8 maxbut;										/* Maximum number of buttons... */
  27.125 +Uint8 i;												/* Temporary Count Vars */
  27.126 +Uint8 ucNewJoystickMask;										/* Mask for Joystick Detection */
  27.127 +struct _joycfg joycfg;							/* Joy Configuration from envvar */
  27.128 +
  27.129 +
  27.130 +/* Get Max Number of Devices */
  27.131 +rc = joyPortOpen(&hJoyPort); /* Open GAME$ port */
  27.132 +if (rc != 0) return 0;	/* Cannot open... report no joystick */
  27.133 +ulDataLen = sizeof(stGameParms);
  27.134 +rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_PARMS,
  27.135 +	NULL, 0, NULL, &stGameParms, ulDataLen, &ulDataLen); /* Ask device info */
  27.136 +if (rc != 0)
  27.137 +	{
  27.138 +	joyPortClose(&hJoyPort);
  27.139 +	SDL_SetError("Could not read joystick port.");
  27.140 +	return -1;
  27.141 +	}
  27.142 +if (stGameParms.useA != 0) maxdevs++;
  27.143 +if (stGameParms.useB != 0) maxdevs++;
  27.144 +if ( maxdevs > MAX_JOYSTICKS ) maxdevs = MAX_JOYSTICKS;
  27.145 +
  27.146 +/* Defines min/max axes values (callibration) */
  27.147 +ulDataLen = sizeof(stGameCalib);
  27.148 +rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_CALIB,
  27.149 +	NULL, 0, NULL, &stGameCalib, ulDataLen, &ulDataLen);
  27.150 +if (rc != 0)
  27.151 +	{
  27.152 +	joyPortClose(&hJoyPort);
  27.153 +	SDL_SetError("Could not read callibration data.");
  27.154 +	return -1;
  27.155 +	}
  27.156 +
  27.157 +/* Determine how many joysticks are active */
  27.158 +numdevs = 0;	/* Points no device */
  27.159 +ucNewJoystickMask = 0x0F;	/* read all 4 joystick axis */
  27.160 +ulDataLen = sizeof(ucNewJoystickMask);
  27.161 +rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_RESET,
  27.162 +		&ucNewJoystickMask, ulDataLen, &ulDataLen, NULL, 0, NULL);
  27.163 +if (rc == 0)
  27.164 +	{
  27.165 +	ulDataLen = sizeof(stJoyStatus);
  27.166 +	rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
  27.167 +		NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
  27.168 +	if (rc != 0)
  27.169 +		{
  27.170 +		joyPortClose(&hJoyPort);
  27.171 +		SDL_SetError("Could not call joystick port.");
  27.172 +		return -1;
  27.173 +		}
  27.174 +	ulLastTick = stJoyStatus.ulJs_Ticks;
  27.175 +	while (stJoyStatus.ulJs_Ticks == ulLastTick)
  27.176 +		{
  27.177 +		rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
  27.178 +			NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
  27.179 +		}
  27.180 +	if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) numdevs++;
  27.181 +	if (((stJoyStatus.ucJs_JoyStickMask >> 2) & 0x03) > 0) numdevs++;
  27.182 +	}
  27.183 +
  27.184 +if (numdevs>maxdevs) numdevs=maxdevs;
  27.185 +
  27.186 +/* If *any* joystick was detected... Let's configure SDL for them */
  27.187 +if (numdevs > 0)
  27.188 +	{
  27.189 +	/* Verify if it is a "user defined" joystick */
  27.190 +	if (joyGetEnv(&joycfg))
  27.191 +		{
  27.192 +		GAME_3POS_STRUCT * axis[4];
  27.193 +		axis[0] = &stGameCalib.Ax;
  27.194 +		axis[1] = &stGameCalib.Ay;
  27.195 +		axis[2] = &stGameCalib.Bx;
  27.196 +		axis[3] = &stGameCalib.By;
  27.197 +		/* Say it has one device only (user defined is always one device only) */
  27.198 +		numdevs = 1;
  27.199 +		/* Define Device 0 as... */
  27.200 +		SYS_JoyData[0].id=0;
  27.201 +		/* Define Number of Axes... up to 4 */
  27.202 +		if (joycfg.axes>MAX_AXES) joycfg.axes = MAX_AXES;
  27.203 +		SYS_JoyData[0].axes = joycfg.axes;
  27.204 +		/* Define number of buttons... 8 if 2 axes, 6 if 3 axes and 4 if 4 axes */
  27.205 +		maxbut = MAX_BUTTONS;
  27.206 +		if (joycfg.axes>2) maxbut-=((joycfg.axes-2)<<1); /* MAX_BUTTONS - 2*(axes-2) */
  27.207 +		if (joycfg.buttons > maxbut) joycfg.buttons = maxbut;
  27.208 +		SYS_JoyData[0].buttons = joycfg.buttons;
  27.209 +		/* Define number of hats */
  27.210 +		if (joycfg.hats > MAX_HATS) joycfg.hats = MAX_HATS;
  27.211 +		SYS_JoyData[0].hats = joycfg.hats;
  27.212 +		/* Define number of balls */
  27.213 +		if (joycfg.balls > MAX_BALLS) joycfg.balls = MAX_BALLS;
  27.214 +		SYS_JoyData[0].balls = joycfg.balls;
  27.215 +		/* Initialize Axes Callibration Values */
  27.216 +		for (i=0; i<joycfg.axes; i++)
  27.217 +			{
  27.218 +			SYS_JoyData[0].axes_min[i] = axis[i]->lower;
  27.219 +			SYS_JoyData[0].axes_med[i] = axis[i]->centre;
  27.220 +			SYS_JoyData[0].axes_max[i] = axis[i]->upper;
  27.221 +			}
  27.222 +		/* Initialize Buttons 5 to 8 structures */
  27.223 +		if (joycfg.buttons>=5) SYS_JoyData[0].buttoncalc[0]=((axis[2]->lower+axis[3]->centre)>>1);
  27.224 +		if (joycfg.buttons>=6) SYS_JoyData[0].buttoncalc[1]=((axis[3]->lower+axis[3]->centre)>>1);
  27.225 +		if (joycfg.buttons>=7) SYS_JoyData[0].buttoncalc[2]=((axis[2]->upper+axis[3]->centre)>>1);
  27.226 +		if (joycfg.buttons>=8) SYS_JoyData[0].buttoncalc[3]=((axis[3]->upper+axis[3]->centre)>>1);
  27.227 +		/* Intialize Joystick Name */
  27.228 +		strcpy (SYS_JoyData[0].szDeviceName,joycfg.name);
  27.229 +		}
  27.230 +	/* Default Init ... autoconfig */
  27.231 +	else
  27.232 +		{
  27.233 +		/* if two devices were detected... configure as Joy1 4 axis and Joy2 2 axis */
  27.234 +		if (numdevs==2)
  27.235 +			{
  27.236 +			/* Define Device 0 as 4 axes, 4 buttons */
  27.237 +			SYS_JoyData[0].id=0;
  27.238 +			SYS_JoyData[0].axes = 4;
  27.239 +			SYS_JoyData[0].buttons = 4;
  27.240 +			SYS_JoyData[0].hats = 0;
  27.241 +			SYS_JoyData[0].balls = 0;
  27.242 +			SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
  27.243 +			SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
  27.244 +			SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
  27.245 +			SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
  27.246 +			SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
  27.247 +			SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
  27.248 +			SYS_JoyData[0].axes_min[2] = stGameCalib.Bx.lower;
  27.249 +			SYS_JoyData[0].axes_med[2] = stGameCalib.Bx.centre;
  27.250 +			SYS_JoyData[0].axes_max[2] = stGameCalib.Bx.upper;
  27.251 +			SYS_JoyData[0].axes_min[3] = stGameCalib.By.lower;
  27.252 +			SYS_JoyData[0].axes_med[3] = stGameCalib.By.centre;
  27.253 +			SYS_JoyData[0].axes_max[3] = stGameCalib.By.upper;
  27.254 +			/* Define Device 1 as 2 axes, 2 buttons */
  27.255 +			SYS_JoyData[1].id=1;
  27.256 +			SYS_JoyData[1].axes = 2;
  27.257 +			SYS_JoyData[1].buttons = 2;
  27.258 +			SYS_JoyData[1].hats = 0;
  27.259 +			SYS_JoyData[1].balls = 0;
  27.260 +			SYS_JoyData[1].axes_min[0] = stGameCalib.Bx.lower;
  27.261 +			SYS_JoyData[1].axes_med[0] = stGameCalib.Bx.centre;
  27.262 +			SYS_JoyData[1].axes_max[0] = stGameCalib.Bx.upper;
  27.263 +			SYS_JoyData[1].axes_min[1] = stGameCalib.By.lower;
  27.264 +			SYS_JoyData[1].axes_med[1] = stGameCalib.By.centre;
  27.265 +			SYS_JoyData[1].axes_max[1] = stGameCalib.By.upper;
  27.266 +			}
  27.267 +		/* One joystick only? */
  27.268 +		else
  27.269 +			{
  27.270 +			/* If it is joystick A... */
  27.271 +			if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0)
  27.272 +				{
  27.273 +				/* Define Device 0 as 2 axes, 4 buttons */
  27.274 +				SYS_JoyData[0].id=0;
  27.275 +				SYS_JoyData[0].axes = 2;
  27.276 +				SYS_JoyData[0].buttons = 4;
  27.277 +				SYS_JoyData[0].hats = 0;
  27.278 +				SYS_JoyData[0].balls = 0;
  27.279 +				SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
  27.280 +				SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
  27.281 +				SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
  27.282 +				SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
  27.283 +				SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
  27.284 +				SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
  27.285 +				}
  27.286 +			/* If not, it is joystick B */
  27.287 +			else
  27.288 +				{
  27.289 +				/* Define Device 1 as 2 axes, 2 buttons */
  27.290 +				SYS_JoyData[0].id=1;
  27.291 +				SYS_JoyData[0].axes = 2;
  27.292 +				SYS_JoyData[0].buttons = 2;
  27.293 +				SYS_JoyData[0].hats = 0;
  27.294 +				SYS_JoyData[0].balls = 0;
  27.295 +				SYS_JoyData[0].axes_min[0] = stGameCalib.Bx.lower;
  27.296 +				SYS_JoyData[0].axes_med[0] = stGameCalib.Bx.centre;
  27.297 +				SYS_JoyData[0].axes_max[0] = stGameCalib.Bx.upper;
  27.298 +				SYS_JoyData[0].axes_min[1] = stGameCalib.By.lower;
  27.299 +				SYS_JoyData[0].axes_med[1] = stGameCalib.By.centre;
  27.300 +				SYS_JoyData[0].axes_max[1] = stGameCalib.By.upper;
  27.301 +				}
  27.302 +			}
  27.303 +		/* Hack to define Joystick Port Names */
  27.304 +		if ( numdevs > maxdevs ) numdevs = maxdevs;
  27.305 +		for (i=0; i<numdevs; i++) sprintf (SYS_JoyData[i].szDeviceName,"Default Joystick %c",'A'+SYS_JoyData[i].id);
  27.306 +		}
  27.307 +	}
  27.308 +/* Return the number of devices found */
  27.309 +return(numdevs);
  27.310 +}
  27.311 +
  27.312 +
  27.313 +
  27.314 +/***********************************************************/
  27.315 +/* Function to get the device-dependent name of a joystick */
  27.316 +/***********************************************************/
  27.317 +const char *SDL_SYS_JoystickName(int index)
  27.318 +{
  27.319 +/* No need to verify if device exists, already done in upper layer */
  27.320 +return(SYS_JoyData[index].szDeviceName);
  27.321 +}
  27.322 +
  27.323 +
  27.324 +
  27.325 +/******************************************************************************/
  27.326 +/* Function to open a joystick for use.													*/
  27.327 +/* The joystick to open is specified by the index field of the joystick.		*/
  27.328 +/* This should fill the nbuttons and naxes fields of the joystick structure.	*/
  27.329 +/* It returns 0, or -1 if there is an error.												*/
  27.330 +/******************************************************************************/
  27.331 +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
  27.332 +{
  27.333 +int index;		/* Index shortcut for index in joystick structure */
  27.334 +int i;			/* Generic Counter */
  27.335 +
  27.336 +/* allocate memory for system specific hardware data */
  27.337 +joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
  27.338 +if (joystick->hwdata == NULL)
  27.339 +	{
  27.340 +	SDL_OutOfMemory();
  27.341 +	return(-1);
  27.342 +	}
  27.343 +/* Reset Hardware Data */
  27.344 +memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
  27.345 +
  27.346 +/* ShortCut Pointer */
  27.347 +index = joystick->index;
  27.348 +/* Define offsets and scales for all axes */
  27.349 +joystick->hwdata->id = SYS_JoyData[index].id;
  27.350 +for ( i = 0; i < MAX_AXES; ++i )
  27.351 +	{
  27.352 +	if ( (i<2) || i < SYS_JoyData[index].axes )
  27.353 +		{
  27.354 +		joystick->hwdata->transaxes[i].offset = ((AXIS_MAX + AXIS_MIN)>>1) - SYS_JoyData[index].axes_med[i];
  27.355 +		//joystick->hwdata->transaxes[i].scale = (float)((AXIS_MAX - AXIS_MIN)/(SYS_JoyData[index].axes_max[i]-SYS_JoyData[index].axes_min[i]));
  27.356 +		joystick->hwdata->transaxes[i].scale1 = (float)abs((AXIS_MIN/SYS_JoyData[index].axes_min[i]));
  27.357 +		joystick->hwdata->transaxes[i].scale2 = (float)abs((AXIS_MAX/SYS_JoyData[index].axes_max[i]));
  27.358 +		}
  27.359 +	else
  27.360 +		{
  27.361 +		joystick->hwdata->transaxes[i].offset = 0;
  27.362 +		//joystick->hwdata->transaxes[i].scale = 1.0; /* Just in case */
  27.363 +		joystick->hwdata->transaxes[i].scale1 = 1.0; /* Just in case */
  27.364 +		joystick->hwdata->transaxes[i].scale2 = 1.0; /* Just in case */
  27.365 +		}
  27.366 +	}
  27.367 +
  27.368 +/* fill nbuttons, naxes, and nhats fields */
  27.369 +joystick->nbuttons = SYS_JoyData[index].buttons;
  27.370 +joystick->naxes = SYS_JoyData[index].axes;
  27.371 +/* joystick->nhats = SYS_JoyData[index].hats; */
  27.372 +joystick->nhats = 0; /* No support for hats at this time */
  27.373 +/* joystick->nballs = SYS_JoyData[index].balls; */
  27.374 +joystick->nballs = 0; /* No support for balls at this time */
  27.375 +return 0;
  27.376 +}
  27.377 +
  27.378 +
  27.379 +
  27.380 +/***************************************************************************/
  27.381 +/* Function to update the state of a joystick - called as a device poll.	*/
  27.382 +/* This function shouldn't update the joystick structure directly,			*/
  27.383 +/* but instead should call SDL_PrivateJoystick*() to deliver events			*/
  27.384 +/* and update joystick device state.													*/
  27.385 +/***************************************************************************/
  27.386 +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
  27.387 +{
  27.388 +APIRET rc;									/* Generic OS/2 return code */
  27.389 +int index;									/* index shortcurt to joystick index */
  27.390 +int i;										/* Generic counter */
  27.391 +int normbut;								/* Number of buttons reported by joystick */
  27.392 +int corr;									/* Correction for button names */
  27.393 +Sint16 value, change;					/* Values used to update axis values */
  27.394 +struct _transaxes *transaxes;			/* Shortcut for Correction structure */
  27.395 +Uint32 pos[MAX_AXES];					/* Vector to inform the Axis status */
  27.396 +ULONG ulDataLen;							/* Size of data */
  27.397 +GAME_STATUS_STRUCT stGameStatus;		/* Joystick Status Structure */
  27.398 +
  27.399 +ulDataLen = sizeof(stGameStatus);
  27.400 +rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_STATUS,
  27.401 +	NULL, 0, NULL, &stGameStatus, ulDataLen, &ulDataLen);
  27.402 +if (rc != 0)
  27.403 +	{
  27.404 +	SDL_SetError("Could not read joystick status.");
  27.405 +	return; /* Could not read data */
  27.406 +	}
  27.407 +
  27.408 +/* Shortcut pointer */
  27.409 +index = joystick->index;
  27.410 +/* joystick motion events */
  27.411 +
  27.412 +if (SYS_JoyData[index].id == 0)
  27.413 +	{
  27.414 +	pos[0] = stGameStatus.curdata.A.x;
  27.415 +	pos[1] = stGameStatus.curdata.A.y;
  27.416 +	if (SYS_JoyData[index].axes >= 3)	pos[2] = stGameStatus.curdata.B.x;
  27.417 +	else pos[2]=0;
  27.418 +	if (SYS_JoyData[index].axes >= 4)	pos[3] = stGameStatus.curdata.B.y;
  27.419 +	else pos[3]=0;
  27.420 +	pos[4]=0;	/* OS/2 basic drivers do not support more than 4 axes joysticks */
  27.421 +	pos[5]=0;
  27.422 +	}
  27.423 +else if (SYS_JoyData[index].id == 1)
  27.424 +	{
  27.425 +	pos[0] = stGameStatus.curdata.B.x;
  27.426 +	pos[1] = stGameStatus.curdata.B.y;
  27.427 +	pos[2]=0;
  27.428 +	pos[3]=0;
  27.429 +	pos[4]=0;
  27.430 +	pos[5]=0;
  27.431 +	}
  27.432 +
  27.433 +/* Corrects the movements using the callibration */
  27.434 +transaxes = joystick->hwdata->transaxes;
  27.435 +for (i = 0; i < joystick->naxes; i++)
  27.436 +	{
  27.437 +	value = pos[i] + transaxes[i].offset;
  27.438 +	if (value<0)
  27.439 +		{
  27.440 +		value*=transaxes[i].scale1;
  27.441 +		if (value>0) value = AXIS_MIN;
  27.442 +		}
  27.443 +	else
  27.444 +		{
  27.445 +		value*=transaxes[i].scale2;
  27.446 +		if (value<0) value = AXIS_MAX;
  27.447 +		}
  27.448 +	change = (value - joystick->axes[i]);
  27.449 +	if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) )
  27.450 +		{
  27.451 +		SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value);
  27.452 +		}
  27.453 +	}
  27.454 +
  27.455 +/* joystick button A to D events */
  27.456 +if (SYS_JoyData[index].id == 1) corr = 2;
  27.457 +else corr = 0;
  27.458 +normbut=4;	/* Number of normal buttons */
  27.459 +if (joystick->nbuttons<normbut) normbut = joystick->nbuttons;
  27.460 +for ( i = corr; (i-corr) < normbut; ++i )
  27.461 +	{
  27.462 +	/*
  27.463 +		Button A: 1110 0000
  27.464 +		Button B: 1101 0000
  27.465 +		Button C: 1011 0000
  27.466 +		Button D: 0111 0000
  27.467 +	*/
  27.468 +	if ( (~stGameStatus.curdata.butMask)>>4 & JOY_BUTTON_FLAG(i) )
  27.469 +		{
  27.470 +		if ( ! joystick->buttons[i-corr] )
  27.471 +			{
  27.472 +			SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_PRESSED);
  27.473 +			}
  27.474 +		}
  27.475 +	else
  27.476 +		{
  27.477 +		if ( joystick->buttons[i-corr] )
  27.478 +			{
  27.479 +			SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_RELEASED);
  27.480 +			}
  27.481 +		}
  27.482 +	}
  27.483 +
  27.484 +/* Joystick button E to H buttons */
  27.485 +	/*
  27.486 +		Button E: Axis 2 X Left
  27.487 +		Button F: Axis 2 Y Up
  27.488 +		Button G: Axis 2 X Right
  27.489 +		Button H: Axis 2 Y Down
  27.490 +	*/
  27.491 +if (joystick->nbuttons>=5)
  27.492 +	{
  27.493 +	if (stGameStatus.curdata.B.x < SYS_JoyData[index].buttoncalc[0]) SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_PRESSED);
  27.494 +	else SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_RELEASED);
  27.495 +	}
  27.496 +if (joystick->nbuttons>=6)
  27.497 +	{
  27.498 +	if (stGameStatus.curdata.B.y < SYS_JoyData[index].buttoncalc[1]) SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_PRESSED);
  27.499 +	else SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_RELEASED);
  27.500 +	}
  27.501 +if (joystick->nbuttons>=7)
  27.502 +	{
  27.503 +	if (stGameStatus.curdata.B.x > SYS_JoyData[index].buttoncalc[2]) SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_PRESSED);
  27.504 +	else SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_RELEASED);
  27.505 +	}
  27.506 +if (joystick->nbuttons>=8)
  27.507 +	{
  27.508 +	if (stGameStatus.curdata.B.y > SYS_JoyData[index].buttoncalc[3]) SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_PRESSED);
  27.509 +	else SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_RELEASED);
  27.510 +	}
  27.511 +
  27.512 +/* joystick hat events */
  27.513 +/* Not Supported under OS/2 */
  27.514 +/* joystick ball events */
  27.515 +/* Not Supported under OS/2 */
  27.516 +}
  27.517 +
  27.518 +
  27.519 +
  27.520 +/******************************************/
  27.521 +/* Function to close a joystick after use */
  27.522 +/******************************************/
  27.523 +void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
  27.524 +{
  27.525 +if (joystick->hwdata != NULL)
  27.526 +	{
  27.527 +	/* free system specific hardware data */
  27.528 +	free(joystick->hwdata);
  27.529 +	}
  27.530 +}
  27.531 +
  27.532 +
  27.533 +
  27.534 +/********************************************************************/
  27.535 +/* Function to perform any system-specific joystick related cleanup */
  27.536 +/********************************************************************/
  27.537 +void SDL_SYS_JoystickQuit(void)
  27.538 +{
  27.539 +joyPortClose(&hJoyPort);
  27.540 +}
  27.541 +
  27.542 +
  27.543 +
  27.544 +/************************/
  27.545 +/************************/
  27.546 +/* OS/2 Implementations */
  27.547 +/************************/
  27.548 +/************************/
  27.549 +
  27.550 +
  27.551 +/*****************************************/
  27.552 +/* Open Joystick Port, if not opened yet */
  27.553 +/*****************************************/
  27.554 +APIRET joyPortOpen(HFILE * hGame)
  27.555 +{
  27.556 +APIRET		rc;				/* Generic Return Code */
  27.557 +ULONG			ulAction;		/* ? */
  27.558 +ULONG			ulVersion;		/* Version of joystick driver */
  27.559 +ULONG			ulDataLen;		/* Size of version data */
  27.560 +
  27.561 +/* Verifies if joyport is not already open... */
  27.562 +if (*hGame != NULL) return 0;
  27.563 +/* Open GAME$ for read */
  27.564 +rc = DosOpen((PSZ)GAMEPDDNAME, hGame, &ulAction, 0, FILE_READONLY,
  27.565 +	FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL);
  27.566 +if (rc != 0)
  27.567 +	{
  27.568 +	SDL_SetError("Could not open Joystick Port.");
  27.569 +	return -1;
  27.570 +	}
  27.571 +	
  27.572 +/* Get Joystick Driver Version... must be 2.0 or higher */
  27.573 +ulVersion = 0;
  27.574 +ulDataLen = sizeof(ulVersion);
  27.575 +rc = DosDevIOCtl( *hGame, IOCTL_CAT_USER, GAME_GET_VERSION,
  27.576 +	NULL, 0, NULL, &ulVersion, ulDataLen, &ulDataLen);
  27.577 +if (rc != 0)
  27.578 +	{
  27.579 +	joyPortClose(hGame);
  27.580 +	SDL_SetError("Could not get Joystick Driver version.");
  27.581 +	return -1;	
  27.582 +	}
  27.583 +if (ulVersion < GAME_VERSION)
  27.584 +	{
  27.585 +	joyPortClose(hGame);
  27.586 +	SDL_SetError("Driver too old. At least IBM driver version 2.0 required.");
  27.587 +	return -1;
  27.588 +	}
  27.589 +return 0;
  27.590 +}
  27.591 +
  27.592 +
  27.593 +
  27.594 +/****************************/
  27.595 +/* Close JoyPort, if opened */
  27.596 +/****************************/
  27.597 +void joyPortClose(HFILE * hGame)
  27.598 +{
  27.599 +if (*hGame != NULL) DosClose(*hGame);
  27.600 +*hGame = NULL;
  27.601 +}
  27.602 +
  27.603 +
  27.604 +
  27.605 +/***************************/
  27.606 +/* Get SDL Joystick EnvVar */
  27.607 +/***************************/
  27.608 +int joyGetEnv(struct _joycfg * joydata)
  27.609 +{
  27.610 +char *joyenv;				/* Pointer to tested character */
  27.611 +char tempnumber[5];		/* Temporary place to put numeric texts */
  27.612 +
  27.613 +joyenv = getenv("SDL_OS2_JOYSTICK");
  27.614 +if (joyenv == NULL) return 0;
  27.615 +/* Joystick Environment is defined! */
  27.616 +while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
  27.617 +/* If the string name starts with '... get if fully */
  27.618 +if (*joyenv=='\'') joyenv+=joyGetData(++joyenv,joydata->name,'\'',sizeof(joydata->name));
  27.619 +/* If not, get it until the next space */
  27.620 +else if (*joyenv=='\"') joyenv+=joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name));
  27.621 +else joyenv+=joyGetData(joyenv,joydata->name,' ',sizeof(joydata->name));
  27.622 +/* Now get the number of axes */
  27.623 +while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
  27.624 +joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
  27.625 +joydata->axes = atoi(tempnumber);
  27.626 +/* Now get the number of buttons */
  27.627 +while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
  27.628 +joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
  27.629 +joydata->buttons = atoi(tempnumber);
  27.630 +/* Now get the number of hats */
  27.631 +while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
  27.632 +joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
  27.633 +joydata->hats = atoi(tempnumber);
  27.634 +/* Now get the number of balls */
  27.635 +while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
  27.636 +joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
  27.637 +joydata->balls = atoi(tempnumber);
  27.638 +return 1;
  27.639 +}
  27.640 +
  27.641 +
  27.642 +
  27.643 +/************************************************************************/
  27.644 +/* Get a text from in the string starting in joyenv until it finds		*/
  27.645 +/* the stopchar or maxchars is reached. The result is placed in name.	*/
  27.646 +/************************************************************************/
  27.647 +int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars)
  27.648 +{
  27.649 +char *nameptr;			/* Pointer to the selected character */
  27.650 +int chcnt=0;			/* Count how many characters where copied */
  27.651 +
  27.652 +nameptr=name;
  27.653 +while (*joyenv!=stopchar && *joyenv!=0)
  27.654 +	{
  27.655 +	if (nameptr<(name+(maxchars-1)))
  27.656 +		{
  27.657 +		*nameptr = *joyenv; /* Only copy if smaller than maximum */
  27.658 +		nameptr++;
  27.659 +		}
  27.660 +	chcnt++;
  27.661 +	joyenv++;
  27.662 +	}
  27.663 +if (*joyenv==stopchar)
  27.664 +	{
  27.665 +	joyenv++; /* Jump stopchar */
  27.666 +	chcnt++;
  27.667 +	}
  27.668 +*nameptr = 0; /* Mark last byte */
  27.669 +return chcnt;
  27.670 +}
  27.671 +
  27.672 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/joystick/os2/joyos2.h	Wed Nov 23 07:29:56 2005 +0000
    28.3 @@ -0,0 +1,177 @@
    28.4 +/*****************************************************************************/
    28.5 +/*                                                                           */
    28.6 +/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
    28.7 +/*                                                                           */
    28.8 +/*    The following IBM OS/2 source code is provided to you solely for       */
    28.9 +/*    the purpose of assisting you in your development of OS/2 device        */
   28.10 +/*    drivers. You may use this code in accordance with the IBM License      */
   28.11 +/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
   28.12 +/*    Copyright statement may not be removed.                                */
   28.13 +/*                                                                           */
   28.14 +/*****************************************************************************/
   28.15 +#ifndef JOYOS2_H
   28.16 +#define JOYOS2_H
   28.17 +
   28.18 +/****** GAMEPORT.SYS joystick definitions, start *****************************/
   28.19 +#define GAME_VERSION    0x20           /* 2.0 First IBM version */
   28.20 +#define GAMEPDDNAME     "GAME$   "
   28.21 +#define IOCTL_CAT_USER	0x80
   28.22 +#define GAME_PORT_GET	0x20		/* read GAMEPORT.SYS values */
   28.23 +#define GAME_PORT_RESET 0x60		/* reset joystick mask with given value */
   28.24 +
   28.25 +#pragma pack(1)				/* pack structure size is 1 byte */
   28.26 +typedef struct {			/* GAMEPORT.SYS structure */
   28.27 +	USHORT	usJs_AxCnt;		/* Joystick_A X position */
   28.28 +	USHORT	usJs_AyCnt;		/* Joystick_A Y position */
   28.29 +	USHORT	usJs_BxCnt;		/* Joystick_B X position */
   28.30 +	USHORT	usJs_ByCnt;		/* Joystick_B Y position */
   28.31 +	USHORT	usJs_ButtonA1Cnt;	/* button A1 press count */
   28.32 +	USHORT	usJs_ButtonA2Cnt;	/* button A2 press count */
   28.33 +	USHORT	usJs_ButtonB1Cnt;	/* button B1 press count */
   28.34 +	USHORT	usJs_ButtonB2Cnt;	/* button B2 press count */
   28.35 +	UCHAR	ucJs_JoyStickMask;	/* mask of connected joystick pots */
   28.36 +	UCHAR	ucJs_ButtonStatus;	/* bits of switches down */
   28.37 +	ULONG	ulJs_Ticks;		/* joystick clock ticks */
   28.38 +} GAME_PORT_STRUCT;
   28.39 +#pragma pack()				/*reset to normal pack size */
   28.40 +/****** GAMEPORT.SYS joystick definitions, end *******************************/
   28.41 +
   28.42 +
   28.43 +/****************************************************************************/
   28.44 +#define GAME_GET_VERSION                0x01
   28.45 +#define GAME_GET_PARMS                  0x02
   28.46 +#define GAME_SET_PARMS                  0x03
   28.47 +#define GAME_GET_CALIB                  0x04
   28.48 +#define GAME_SET_CALIB                  0x05
   28.49 +#define GAME_GET_DIGSET                 0x06
   28.50 +#define GAME_SET_DIGSET                 0x07
   28.51 +#define GAME_GET_STATUS                 0x10
   28.52 +#define GAME_GET_STATUS_BUTWAIT         0x11
   28.53 +#define GAME_GET_STATUS_SAMPWAIT        0x12
   28.54 +/****************************************************************************/
   28.55 +
   28.56 +/****************************************************************************/
   28.57 +// bit masks for each axis
   28.58 +#define JOY_AX_BIT      0x01
   28.59 +#define JOY_AY_BIT      0x02
   28.60 +#define JOY_A_BITS      (JOY_AX_BIT|JOY_AY_BIT)
   28.61 +#define JOY_BX_BIT      0x04
   28.62 +#define JOY_BY_BIT      0x08
   28.63 +#define JOY_B_BITS      (JOY_BX_BIT|JOY_BY_BIT)
   28.64 +#define JOY_ALLPOS_BITS (JOY_A_BITS|JOY_B_BITS)
   28.65 +
   28.66 +// bit masks for each button
   28.67 +#define JOY_BUT1_BIT    0x10
   28.68 +#define JOY_BUT2_BIT    0x20
   28.69 +#define JOY_BUT3_BIT    0x40
   28.70 +#define JOY_BUT4_BIT    0x80
   28.71 +#define JOY_ALL_BUTS    (JOY_BUT1_BIT|JOY_BUT2_BIT|JOY_BUT3_BIT|JOY_BUT4_BIT)
   28.72 +/****************************************************************************/
   28.73 +
   28.74 +/****************************************************************************/
   28.75 +// 1-D position struct used for each axis
   28.76 +typedef SHORT   GAME_POS;       /* some data formats require signed values */
   28.77 +
   28.78 +// simple 2-D position for each joystick
   28.79 +typedef struct
   28.80 +{
   28.81 +        GAME_POS                x;
   28.82 +        GAME_POS                y;
   28.83 +}
   28.84 +GAME_2DPOS_STRUCT;
   28.85 +
   28.86 +// struct defining the instantaneous state of both sticks and all buttons
   28.87 +typedef struct
   28.88 +{
   28.89 +        GAME_2DPOS_STRUCT       A;
   28.90 +        GAME_2DPOS_STRUCT       B;
   28.91 +        USHORT                  butMask;
   28.92 +}
   28.93 +GAME_DATA_STRUCT;
   28.94 +
   28.95 +// struct to be used for calibration and digital response on each axis
   28.96 +typedef struct
   28.97 +{
   28.98 +        GAME_POS                lower;
   28.99 +        GAME_POS                centre;
  28.100 +        GAME_POS                upper;
  28.101 +}
  28.102 +GAME_3POS_STRUCT;
  28.103 +/****************************************************************************/
  28.104 +
  28.105 +/****************************************************************************/
  28.106 +// status struct returned to OS/2 applications:
  28.107 +// current data for all sticks as well as button counts since last read
  28.108 +typedef struct
  28.109 +{
  28.110 +        GAME_DATA_STRUCT        curdata;
  28.111 +        USHORT                  b1cnt;
  28.112 +        USHORT                  b2cnt;
  28.113 +        USHORT                  b3cnt;
  28.114 +        USHORT                  b4cnt;
  28.115 +}
  28.116 +GAME_STATUS_STRUCT;
  28.117 +/****************************************************************************/
  28.118 +
  28.119 +/****************************************************************************/
  28.120 +/* in use bitmasks originating in 0.2b */
  28.121 +#define GAME_USE_BOTH_OLDMASK   0x01    /* for backward compat with bool */
  28.122 +#define GAME_USE_X_NEWMASK      0x02
  28.123 +#define GAME_USE_Y_NEWMASK      0x04
  28.124 +#define GAME_USE_X_EITHERMASK   (GAME_USE_X_NEWMASK|GAME_USE_BOTH_OLDMASK)
  28.125 +#define GAME_USE_Y_EITHERMASK   (GAME_USE_Y_NEWMASK|GAME_USE_BOTH_OLDMASK)
  28.126 +#define GAME_USE_BOTH_NEWMASK   (GAME_USE_X_NEWMASK|GAME_USE_Y_NEWMASK)
  28.127 +
  28.128 +/* only timed sampling implemented in version 1.0 */
  28.129 +#define GAME_MODE_TIMED         1       /* timed sampling */
  28.130 +#define GAME_MODE_REQUEST       2       /* request driven sampling */
  28.131 +
  28.132 +/* only raw implemented in version 1.0 */
  28.133 +#define GAME_DATA_FORMAT_RAW    1       /* [l,c,r]   */
  28.134 +#define GAME_DATA_FORMAT_SIGNED 2       /* [-l,0,+r] */
  28.135 +#define GAME_DATA_FORMAT_BINARY 3       /* {-1,0,+1} */
  28.136 +#define GAME_DATA_FORMAT_SCALED 4       /* [-10,+10] */
  28.137 +
  28.138 +// parameters defining the operation of the driver
  28.139 +typedef struct
  28.140 +{
  28.141 +        USHORT                  useA;           /* new bitmasks: see above */
  28.142 +        USHORT                  useB;
  28.143 +        USHORT                  mode;           /* see consts above */
  28.144 +        USHORT                  format;         /* see consts above */
  28.145 +        USHORT                  sampDiv;        /* samp freq = 32 / n */
  28.146 +        USHORT                  scale;          /* scaling factor */
  28.147 +        USHORT                  res1;           /* must be 0 */
  28.148 +        USHORT                  res2;           /* must be 0 */
  28.149 +}
  28.150 +GAME_PARM_STRUCT;
  28.151 +/****************************************************************************/
  28.152 +
  28.153 +/****************************************************************************/
  28.154 +// calibration values for each axis:
  28.155 +//      - upper limit on value to be considered in lower range
  28.156 +//      - centre value
  28.157 +//      - lower limit on value to be considered in upper range
  28.158 +typedef struct
  28.159 +{
  28.160 +        GAME_3POS_STRUCT        Ax;
  28.161 +        GAME_3POS_STRUCT        Ay;
  28.162 +        GAME_3POS_STRUCT        Bx;
  28.163 +        GAME_3POS_STRUCT        By;
  28.164 +}
  28.165 +GAME_CALIB_STRUCT;
  28.166 +/****************************************************************************/
  28.167 +
  28.168 +/****************************************************************************/
  28.169 +// struct defining the digital response values for all axes
  28.170 +typedef struct
  28.171 +{
  28.172 +        GAME_3POS_STRUCT        Ax;
  28.173 +        GAME_3POS_STRUCT        Ay;
  28.174 +        GAME_3POS_STRUCT        Bx;
  28.175 +        GAME_3POS_STRUCT        By;
  28.176 +}
  28.177 +GAME_DIGSET_STRUCT;
  28.178 +/****************************************************************************/
  28.179 +
  28.180 +#endif
    29.1 --- a/src/loadso/macosx/SDL_loadso.c	Wed Nov 23 07:23:48 2005 +0000
    29.2 +++ b/src/loadso/macosx/SDL_loadso.c	Wed Nov 23 07:29:56 2005 +0000
    29.3 @@ -781,6 +781,7 @@
    29.4  	const char *errstr;
    29.5  	const char *file;
    29.6  	void (*init) (void);
    29.7 +
    29.8  	ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
    29.9  	switch (ofirc)
   29.10  	{
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/src/loadso/os2/SDL_loadso.c	Wed Nov 23 07:29:56 2005 +0000
    30.3 @@ -0,0 +1,82 @@
    30.4 +/*
    30.5 +    SDL - Simple DirectMedia Layer
    30.6 +    Copyright (C) 1997-2004 Sam Lantinga
    30.7 +
    30.8 +    This library is free software; you can redistribute it and/or
    30.9 +    modify it under the terms of the GNU Library General Public
   30.10 +    License as published by the Free Software Foundation; either
   30.11 +    version 2 of the License, or (at your option) any later version.
   30.12 +
   30.13 +    This library is distributed in the hope that it will be useful,
   30.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   30.16 +    Library General Public License for more details.
   30.17 +
   30.18 +    You should have received a copy of the GNU Library General Public
   30.19 +    License along with this library; if not, write to the Free
   30.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   30.21 +
   30.22 +    Sam Lantinga
   30.23 +    slouken@libsdl.org
   30.24 +*/
   30.25 +
   30.26 +#ifdef SAVE_RCSID
   30.27 +static char rcsid =
   30.28 + "@(#) $Id$";
   30.29 +#endif
   30.30 +
   30.31 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
   30.32 +/* System dependent library loading routines                           */
   30.33 +
   30.34 +#if !SDL_INTERNAL_BUILDING_LOADSO
   30.35 +#error Do not compile directly...compile src/SDL_loadso.c instead!
   30.36 +#endif
   30.37 +
   30.38 +#if !defined(__OS2__)
   30.39 +#error Compiling for the wrong platform?
   30.40 +#endif
   30.41 +
   30.42 +#include <stdio.h>
   30.43 +#define INCL_DOSERRORS
   30.44 +#define INCL_DOSMODULEMGR
   30.45 +#include <os2.h>
   30.46 +
   30.47 +#include "SDL_types.h"
   30.48 +#include "SDL_error.h"
   30.49 +#include "SDL_loadso.h"
   30.50 +
   30.51 +void *SDL_LoadObject(const char *sofile)
   30.52 +{
   30.53 +    HMODULE handle = NULL;
   30.54 +    char buf[512];
   30.55 +    APIRET ulrc = DosLoadModule(buf, sizeof (buf), (char *) sofile, &handle);
   30.56 +
   30.57 +    /* Generate an error message if all loads failed */
   30.58 +    if ((ulrc != NO_ERROR) || (handle == NULL))
   30.59 +        SDL_SetError("Failed loading %s: %s", sofile, buf);
   30.60 +
   30.61 +    return((void *) handle);
   30.62 +}
   30.63 +
   30.64 +void *SDL_LoadFunction(void *handle, const char *name)
   30.65 +{
   30.66 +    const char *loaderror = "Unknown error";
   30.67 +    void *symbol = NULL;
   30.68 +    APIRET ulrc = DosQueryProcAddr((HMODULE)handle, 0, (char *)name, &symbol);
   30.69 +    if (ulrc == ERROR_INVALID_HANDLE)
   30.70 +        loaderror = "Invalid module handle";
   30.71 +    else if (ulrc == ERROR_INVALID_NAME)
   30.72 +        loaderror = "Symbol not found";
   30.73 +
   30.74 +    if (symbol == NULL)
   30.75 +        SDL_SetError("Failed loading %s: %s", name, loaderror);
   30.76 +
   30.77 +    return(symbol);
   30.78 +}
   30.79 +
   30.80 +void SDL_UnloadObject(void *handle)
   30.81 +{
   30.82 +    if ( handle != NULL )
   30.83 +        DosFreeModule((HMODULE) handle);
   30.84 +}
   30.85 +
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/src/thread/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    31.3 @@ -0,0 +1,36 @@
    31.4 +#=============================================================================
    31.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    31.6 +#
    31.7 +# Makefile for threading
    31.8 +#=============================================================================
    31.9 +
   31.10 +object_files=SDL_thread.obj SDL_sysmutex.obj SDL_syssem.obj SDL_systhread.obj SDL_syscond.obj
   31.11 +ExtraCFlags=
   31.12 +
   31.13 +#
   31.14 +#==============================================================================
   31.15 +#
   31.16 +!include ..\..\Watcom.mif
   31.17 +
   31.18 +.before
   31.19 +    set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
   31.20 +
   31.21 +all : $(object_files)
   31.22 +
   31.23 +SDL_sysmutex.obj: .AUTODEPEND
   31.24 +    wcc386 os2\SDL_sysmutex.c $(cflags)
   31.25 +
   31.26 +SDL_syssem.obj: .AUTODEPEND
   31.27 +    wcc386 os2\SDL_syssem.c $(cflags)
   31.28 +
   31.29 +SDL_systhread.obj: .AUTODEPEND
   31.30 +    wcc386 os2\SDL_systhread.c $(cflags)
   31.31 +
   31.32 +SDL_syscond.obj: .AUTODEPEND
   31.33 +    wcc386 os2\SDL_syscond.c $(cflags)
   31.34 +
   31.35 +clean : .SYMBOLIC
   31.36 +        @if exist *.obj del *.obj
   31.37 +        @if exist *.map del *.map
   31.38 +        @if exist *.res del *.res
   31.39 +        @if exist *.lst del *.lst
    32.1 --- a/src/thread/SDL_systhread.h	Wed Nov 23 07:23:48 2005 +0000
    32.2 +++ b/src/thread/SDL_systhread.h	Wed Nov 23 07:29:56 2005 +0000
    32.3 @@ -33,7 +33,11 @@
    32.4     saves a system-dependent thread id in thread->id, and returns 0
    32.5     on success.
    32.6  */
    32.7 +#ifdef __OS2__
    32.8 +extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
    32.9 +#else
   32.10  extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args);
   32.11 +#endif
   32.12  
   32.13  /* This function does any necessary setup in the child thread */
   32.14  extern void SDL_SYS_SetupThread(void);
    33.1 --- a/src/thread/SDL_thread.c	Wed Nov 23 07:23:48 2005 +0000
    33.2 +++ b/src/thread/SDL_thread.c	Wed Nov 23 07:29:56 2005 +0000
    33.3 @@ -218,7 +218,11 @@
    33.4  	*statusloc = userfunc(userdata);
    33.5  }
    33.6  
    33.7 -SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
    33.8 +#ifdef __OS2__
    33.9 +DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread_Core(int (*fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
   33.10 +#else
   33.11 +DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (*fn)(void *), void *data)
   33.12 +#endif
   33.13  {
   33.14  	SDL_Thread *thread;
   33.15  	thread_args *args;
   33.16 @@ -254,7 +258,11 @@
   33.17  	SDL_AddThread(thread);
   33.18  
   33.19  	/* Create the thread and go! */
   33.20 +#ifdef __OS2__
   33.21 +        ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
   33.22 +#else
   33.23  	ret = SDL_SYS_CreateThread(thread, args);
   33.24 +#endif
   33.25  	if ( ret >= 0 ) {
   33.26  		/* Wait for the thread function to use arguments */
   33.27  		SDL_SemWait(args->wait);
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/src/thread/os2/SDL_syscond.c	Wed Nov 23 07:29:56 2005 +0000
    34.3 @@ -0,0 +1,223 @@
    34.4 +/*
    34.5 +    SDL - Simple DirectMedia Layer
    34.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    34.7 +
    34.8 +    This library is free software; you can redistribute it and/or
    34.9 +    modify it under the terms of the GNU Library General Public
   34.10 +    License as published by the Free Software Foundation; either
   34.11 +    version 2 of the License, or (at your option) any later version.
   34.12 +
   34.13 +    This library is distributed in the hope that it will be useful,
   34.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   34.16 +    Library General Public License for more details.
   34.17 +
   34.18 +    You should have received a copy of the GNU Library General Public
   34.19 +    License along with this library; if not, write to the Free
   34.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   34.21 +
   34.22 +    Sam Lantinga
   34.23 +    slouken@libsdl.org
   34.24 +*/
   34.25 +
   34.26 +#ifdef SAVE_RCSID
   34.27 +static char rcsid =
   34.28 + "@(#) $Id$";
   34.29 +#endif
   34.30 +
   34.31 +/* An implementation of condition variables using semaphores and mutexes */
   34.32 +/*
   34.33 +   This implementation borrows heavily from the BeOS condition variable
   34.34 +   implementation, written by Christopher Tate and Owen Smith.  Thanks!
   34.35 + */
   34.36 +
   34.37 +#include <stdio.h>
   34.38 +#include <stdlib.h>
   34.39 +
   34.40 +#include "SDL_error.h"
   34.41 +#include "SDL_thread.h"
   34.42 +
   34.43 +struct SDL_cond
   34.44 +{
   34.45 +	SDL_mutex *lock;
   34.46 +	int waiting;
   34.47 +	int signals;
   34.48 +	SDL_sem *wait_sem;
   34.49 +	SDL_sem *wait_done;
   34.50 +};
   34.51 +
   34.52 +/* Create a condition variable */
   34.53 +DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void)
   34.54 +{
   34.55 +	SDL_cond *cond;
   34.56 +
   34.57 +	cond = (SDL_cond *) malloc(sizeof(SDL_cond));
   34.58 +	if ( cond ) {
   34.59 +		cond->lock = SDL_CreateMutex();
   34.60 +		cond->wait_sem = SDL_CreateSemaphore(0);
   34.61 +		cond->wait_done = SDL_CreateSemaphore(0);
   34.62 +		cond->waiting = cond->signals = 0;
   34.63 +		if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) {
   34.64 +			SDL_DestroyCond(cond);
   34.65 +			cond = NULL;
   34.66 +		}
   34.67 +	} else {
   34.68 +		SDL_OutOfMemory();
   34.69 +	}
   34.70 +	return(cond);
   34.71 +}
   34.72 +
   34.73 +/* Destroy a condition variable */
   34.74 +DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond)
   34.75 +{
   34.76 +	if ( cond ) {
   34.77 +		if ( cond->wait_sem ) {
   34.78 +			SDL_DestroySemaphore(cond->wait_sem);
   34.79 +		}
   34.80 +		if ( cond->wait_done ) {
   34.81 +			SDL_DestroySemaphore(cond->wait_done);
   34.82 +		}
   34.83 +		if ( cond->lock ) {
   34.84 +			SDL_DestroyMutex(cond->lock);
   34.85 +		}
   34.86 +		free(cond);
   34.87 +	}
   34.88 +}
   34.89 +
   34.90 +/* Restart one of the threads that are waiting on the condition variable */
   34.91 +DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond)
   34.92 +{
   34.93 +	if ( ! cond ) {
   34.94 +		SDL_SetError("Passed a NULL condition variable");
   34.95 +		return -1;
   34.96 +	}
   34.97 +
   34.98 +	/* If there are waiting threads not already signalled, then
   34.99 +	   signal the condition and wait for the thread to respond.
  34.100 +	*/
  34.101 +	SDL_LockMutex(cond->lock);
  34.102 +	if ( cond->waiting > cond->signals ) {
  34.103 +		++cond->signals;
  34.104 +		SDL_SemPost(cond->wait_sem);
  34.105 +		SDL_UnlockMutex(cond->lock);
  34.106 +		SDL_SemWait(cond->wait_done);
  34.107 +	} else {
  34.108 +		SDL_UnlockMutex(cond->lock);
  34.109 +	}
  34.110 +
  34.111 +	return 0;
  34.112 +}
  34.113 +
  34.114 +/* Restart all threads that are waiting on the condition variable */
  34.115 +DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond)
  34.116 +{
  34.117 +	if ( ! cond ) {
  34.118 +		SDL_SetError("Passed a NULL condition variable");
  34.119 +		return -1;
  34.120 +	}
  34.121 +
  34.122 +	/* If there are waiting threads not already signalled, then
  34.123 +	   signal the condition and wait for the thread to respond.
  34.124 +	*/
  34.125 +	SDL_LockMutex(cond->lock);
  34.126 +	if ( cond->waiting > cond->signals ) {
  34.127 +		int i, num_waiting;
  34.128 +
  34.129 +		num_waiting = (cond->waiting - cond->signals);
  34.130 +		cond->signals = cond->waiting;
  34.131 +		for ( i=0; i<num_waiting; ++i ) {
  34.132 +			SDL_SemPost(cond->wait_sem);
  34.133 +		}
  34.134 +		/* Now all released threads are blocked here, waiting for us.
  34.135 +		   Collect them all (and win fabulous prizes!) :-)
  34.136 +		 */
  34.137 +		SDL_UnlockMutex(cond->lock);
  34.138 +		for ( i=0; i<num_waiting; ++i ) {
  34.139 +			SDL_SemWait(cond->wait_done);
  34.140 +		}
  34.141 +	} else {
  34.142 +		SDL_UnlockMutex(cond->lock);
  34.143 +	}
  34.144 +
  34.145 +	return 0;
  34.146 +}
  34.147 +
  34.148 +/* Wait on the condition variable for at most 'ms' milliseconds.
  34.149 +   The mutex must be locked before entering this function!
  34.150 +   The mutex is unlocked during the wait, and locked again after the wait.
  34.151 +
  34.152 +Typical use:
  34.153 +
  34.154 +Thread A:
  34.155 +	SDL_LockMutex(lock);
  34.156 +	while ( ! condition ) {
  34.157 +		SDL_CondWait(cond);
  34.158 +	}
  34.159 +	SDL_UnlockMutex(lock);
  34.160 +
  34.161 +Thread B:
  34.162 +	SDL_LockMutex(lock);
  34.163 +	...
  34.164 +	condition = true;
  34.165 +	...
  34.166 +	SDL_UnlockMutex(lock);
  34.167 + */
  34.168 +DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
  34.169 +{
  34.170 +	int retval;
  34.171 +
  34.172 +	if ( ! cond ) {
  34.173 +		SDL_SetError("Passed a NULL condition variable");
  34.174 +		return -1;
  34.175 +	}
  34.176 +
  34.177 +	/* Obtain the protection mutex, and increment the number of waiters.
  34.178 +	   This allows the signal mechanism to only perform a signal if there
  34.179 +	   are waiting threads.
  34.180 +	 */
  34.181 +	SDL_LockMutex(cond->lock);
  34.182 +	++cond->waiting;
  34.183 +	SDL_UnlockMutex(cond->lock);
  34.184 +
  34.185 +	/* Unlock the mutex, as is required by condition variable semantics */
  34.186 +	SDL_UnlockMutex(mutex);
  34.187 +
  34.188 +	/* Wait for a signal */
  34.189 +	if ( ms == SDL_MUTEX_MAXWAIT ) {
  34.190 +		retval = SDL_SemWait(cond->wait_sem);
  34.191 +	} else {
  34.192 +		retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
  34.193 +	}
  34.194 +
  34.195 +	/* Let the signaler know we have completed the wait, otherwise
  34.196 +           the signaler can race ahead and get the condition semaphore
  34.197 +           if we are stopped between the mutex unlock and semaphore wait,
  34.198 +           giving a deadlock.  See the following URL for details:
  34.199 +        http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
  34.200 +	*/
  34.201 +	SDL_LockMutex(cond->lock);
  34.202 +	if ( cond->signals > 0 ) {
  34.203 +		/* If we timed out, we need to eat a condition signal */
  34.204 +		if ( retval > 0 ) {
  34.205 +			SDL_SemWait(cond->wait_sem);
  34.206 +		}
  34.207 +		/* We always notify the signal thread that we are done */
  34.208 +		SDL_SemPost(cond->wait_done);
  34.209 +
  34.210 +		/* Signal handshake complete */
  34.211 +		--cond->signals;
  34.212 +	}
  34.213 +	--cond->waiting;
  34.214 +	SDL_UnlockMutex(cond->lock);
  34.215 +
  34.216 +	/* Lock the mutex, as is required by condition variable semantics */
  34.217 +	SDL_LockMutex(mutex);
  34.218 +
  34.219 +	return retval;
  34.220 +}
  34.221 +
  34.222 +/* Wait on the condition variable forever */
  34.223 +DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
  34.224 +{
  34.225 +	return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
  34.226 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/thread/os2/SDL_syscond_c.h	Wed Nov 23 07:29:56 2005 +0000
    35.3 @@ -0,0 +1,27 @@
    35.4 +/*
    35.5 +    SDL - Simple DirectMedia Layer
    35.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    35.7 +
    35.8 +    This library is free software; you can redistribute it and/or
    35.9 +    modify it under the terms of the GNU Library General Public
   35.10 +    License as published by the Free Software Foundation; either
   35.11 +    version 2 of the License, or (at your option) any later version.
   35.12 +
   35.13 +    This library is distributed in the hope that it will be useful,
   35.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   35.16 +    Library General Public License for more details.
   35.17 +
   35.18 +    You should have received a copy of the GNU Library General Public
   35.19 +    License along with this library; if not, write to the Free
   35.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   35.21 +
   35.22 +    Sam Lantinga
   35.23 +    slouken@libsdl.org
   35.24 +*/
   35.25 +
   35.26 +#ifdef SAVE_RCSID
   35.27 +static char rcsid =
   35.28 + "@(#) $Id$";
   35.29 +#endif
   35.30 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/src/thread/os2/SDL_sysmutex.c	Wed Nov 23 07:29:56 2005 +0000
    36.3 @@ -0,0 +1,115 @@
    36.4 +/*
    36.5 +    SDL - Simple DirectMedia Layer
    36.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    36.7 +
    36.8 +    This library is free software; you can redistribute it and/or
    36.9 +    modify it under the terms of the GNU Library General Public
   36.10 +    License as published by the Free Software Foundation; either
   36.11 +    version 2 of the License, or (at your option) any later version.
   36.12 +
   36.13 +    This library is distributed in the hope that it will be useful,
   36.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   36.16 +    Library General Public License for more details.
   36.17 +
   36.18 +    You should have received a copy of the GNU Library General Public
   36.19 +    License along with this library; if not, write to the Free
   36.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   36.21 +
   36.22 +    Sam Lantinga
   36.23 +    slouken@libsdl.org
   36.24 +*/
   36.25 +
   36.26 +#ifdef SAVE_RCSID
   36.27 +static char rcsid =
   36.28 + "@(#) $Id$";
   36.29 +#endif
   36.30 +
   36.31 +/* Mutex functions using the OS/2 API */
   36.32 +
   36.33 +#include <stdio.h>
   36.34 +#include <stdlib.h>
   36.35 +#define INCL_DOSERRORS
   36.36 +#define INCL_DOSSEMAPHORES
   36.37 +#include <os2.h>
   36.38 +
   36.39 +#include "SDL_error.h"
   36.40 +#include "SDL_mutex.h"
   36.41 +
   36.42 +
   36.43 +struct SDL_mutex {
   36.44 +	HMTX hmtxID;
   36.45 +};
   36.46 +
   36.47 +/* Create a mutex */
   36.48 +DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void)
   36.49 +{
   36.50 +  SDL_mutex *mutex;
   36.51 +  APIRET ulrc;
   36.52 +
   36.53 +  /* Allocate mutex memory */
   36.54 +  mutex = (SDL_mutex *)malloc(sizeof(*mutex));
   36.55 +  if (mutex)
   36.56 +  {
   36.57 +    /* Create the mutex, with initial value signaled */
   36.58 +    ulrc = DosCreateMutexSem(NULL,                  // Create unnamed semaphore
   36.59 +                             &(mutex->hmtxID),      // Pointer to handle
   36.60 +                             0L,                    // Flags: create it private (not shared)
   36.61 +                             FALSE);                // Initial value: unowned
   36.62 +    if (ulrc!=NO_ERROR)
   36.63 +    {
   36.64 +      SDL_SetError("Couldn't create mutex");
   36.65 +      free(mutex);
   36.66 +      mutex = NULL;
   36.67 +    }
   36.68 +  } else {
   36.69 +    SDL_OutOfMemory();
   36.70 +  }
   36.71 +  return(mutex);
   36.72 +}
   36.73 +
   36.74 +/* Free the mutex */
   36.75 +DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
   36.76 +{
   36.77 +  if ( mutex )
   36.78 +  {
   36.79 +    if ( mutex->hmtxID )
   36.80 +    {
   36.81 +      DosCloseMutexSem(mutex->hmtxID);
   36.82 +      mutex->hmtxID = 0;
   36.83 +    }
   36.84 +    free(mutex);
   36.85 +  }
   36.86 +}
   36.87 +
   36.88 +/* Lock the mutex */
   36.89 +DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex)
   36.90 +{
   36.91 +  if ( mutex == NULL )
   36.92 +  {
   36.93 +    SDL_SetError("Passed a NULL mutex");
   36.94 +    return -1;
   36.95 +  }
   36.96 +  if ( DosRequestMutexSem(mutex->hmtxID, SEM_INDEFINITE_WAIT) != NO_ERROR )
   36.97 +  {
   36.98 +    SDL_SetError("Couldn't wait on mutex");
   36.99 +    return -1;
  36.100 +  }
  36.101 +  return(0);
  36.102 +}
  36.103 +
  36.104 +/* Unlock the mutex */
  36.105 +DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex)
  36.106 +{
  36.107 +  if ( mutex == NULL )
  36.108 +  {
  36.109 +    SDL_SetError("Passed a NULL mutex");
  36.110 +    return -1;
  36.111 +  }
  36.112 +  if ( DosReleaseMutexSem(mutex->hmtxID) != NO_ERROR )
  36.113 +  {
  36.114 +    SDL_SetError("Couldn't release mutex");
  36.115 +    return -1;
  36.116 +  }
  36.117 +  return(0);
  36.118 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/src/thread/os2/SDL_syssem.c	Wed Nov 23 07:29:56 2005 +0000
    37.3 @@ -0,0 +1,199 @@
    37.4 +/*
    37.5 +    SDL - Simple DirectMedia Layer
    37.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    37.7 +
    37.8 +    This library is free software; you can redistribute it and/or
    37.9 +    modify it under the terms of the GNU Library General Public
   37.10 +    License as published by the Free Software Foundation; either
   37.11 +    version 2 of the License, or (at your option) any later version.
   37.12 +
   37.13 +    This library is distributed in the hope that it will be useful,
   37.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   37.16 +    Library General Public License for more details.
   37.17 +
   37.18 +    You should have received a copy of the GNU Library General Public
   37.19 +    License along with this library; if not, write to the Free
   37.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   37.21 +
   37.22 +    Sam Lantinga
   37.23 +    slouken@libsdl.org
   37.24 +*/
   37.25 +
   37.26 +#ifdef SAVE_RCSID
   37.27 +static char rcsid =
   37.28 + "@(#) $Id$";
   37.29 +#endif
   37.30 +
   37.31 +/* Semaphore functions using the OS/2 API */
   37.32 +
   37.33 +#include <stdio.h>
   37.34 +#include <stdlib.h>
   37.35 +#define INCL_DOS
   37.36 +#define INCL_DOSERRORS
   37.37 +#define INCL_DOSSEMAPHORES
   37.38 +#include <os2.h>
   37.39 +
   37.40 +#include "SDL_error.h"
   37.41 +#include "SDL_thread.h"
   37.42 +#include "SDL_timer.h"
   37.43 +
   37.44 +
   37.45 +struct SDL_semaphore {
   37.46 +        HMTX id;
   37.47 +        HEV  changed;
   37.48 +        Uint32 value;
   37.49 +};
   37.50 +
   37.51 +
   37.52 +/* Create a semaphore */
   37.53 +DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
   37.54 +{
   37.55 +        SDL_sem *sem;
   37.56 +        ULONG ulrc;
   37.57 +
   37.58 +        /* Allocate sem memory */
   37.59 +        sem = (SDL_sem *)malloc(sizeof(*sem));
   37.60 +        if ( sem ) {
   37.61 +                /* Create the mutex semaphore */
   37.62 +                ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE);
   37.63 +                if ( ulrc ) {
   37.64 +                        SDL_SetError("Couldn't create semaphore");
   37.65 +                        free(sem);
   37.66 +                        sem = NULL;
   37.67 +                } else
   37.68 +                {
   37.69 +                    DosCreateEventSem(NULL, &(sem->changed), 0, FALSE);
   37.70 +                    sem->value = initial_value;
   37.71 +                    DosReleaseMutexSem(sem->id);
   37.72 +                }
   37.73 +        } else {
   37.74 +                SDL_OutOfMemory();
   37.75 +        }
   37.76 +        return(sem);
   37.77 +}
   37.78 +
   37.79 +/* Free the semaphore */
   37.80 +DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
   37.81 +{
   37.82 +        if ( sem ) {
   37.83 +                if ( sem->id ) {
   37.84 +                        DosCloseEventSem(sem->changed);
   37.85 +                        DosCloseMutexSem(sem->id);
   37.86 +                        sem->id = 0;
   37.87 +                }
   37.88 +                free(sem);
   37.89 +        }
   37.90 +}
   37.91 +
   37.92 +DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
   37.93 +{
   37.94 +        ULONG ulrc;
   37.95 +
   37.96 +        if ( ! sem ) {
   37.97 +                SDL_SetError("Passed a NULL sem");
   37.98 +                return -1;
   37.99 +        }
  37.100 +
  37.101 +        if ( timeout == SDL_MUTEX_MAXWAIT ) {
  37.102 +           while (1) {
  37.103 +              ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
  37.104 +              if (ulrc) {
  37.105 +                 /* if error waiting mutex */
  37.106 +                 SDL_SetError("DosRequestMutexSem() failed");
  37.107 +                 return -1;
  37.108 +              } else if (sem->value) {
  37.109 +                        sem->value--;
  37.110 +                        DosReleaseMutexSem(sem->id);
  37.111 +                        return 0;
  37.112 +                     } else {
  37.113 +                        ULONG ulPostCount;
  37.114 +                        DosResetEventSem(sem->changed, &ulPostCount);
  37.115 +                        DosReleaseMutexSem(sem->id);
  37.116 +                        /* continue waiting until somebody posts the semaphore */
  37.117 +                        DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT);
  37.118 +                     }
  37.119 +           }
  37.120 +        } else
  37.121 +        if ( timeout == 0 )
  37.122 +        {
  37.123 +            ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
  37.124 +            if (ulrc==NO_ERROR)
  37.125 +            {
  37.126 +                if (sem->value)
  37.127 +                {
  37.128 +                    sem->value--;
  37.129 +                    DosReleaseMutexSem(sem->id);
  37.130 +                    return 0;
  37.131 +                } else
  37.132 +                {
  37.133 +                    DosReleaseMutexSem(sem->id);
  37.134 +                    return SDL_MUTEX_TIMEDOUT;
  37.135 +                }
  37.136 +            } else
  37.137 +            {
  37.138 +                SDL_SetError("DosRequestMutexSem() failed");
  37.139 +                return -1;
  37.140 +            }
  37.141 +        } else {
  37.142 +            ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
  37.143 +            if (ulrc) {
  37.144 +               /* if error waiting mutex */
  37.145 +               SDL_SetError("DosRequestMutexSem() failed");
  37.146 +               return -1;
  37.147 +            } else
  37.148 +              if (sem->value) {
  37.149 +                sem->value--;
  37.150 +                DosReleaseMutexSem(sem->id);
  37.151 +                return 0;
  37.152 +              } else {
  37.153 +                ULONG ulPostCount;
  37.154 +                DosResetEventSem(sem->changed, &ulPostCount);
  37.155 +                DosReleaseMutexSem(sem->id);
  37.156 +                /* continue waiting until somebody posts the semaphore */
  37.157 +                ulrc = DosWaitEventSem(sem->changed, timeout);
  37.158 +                if (ulrc==NO_ERROR)
  37.159 +                  return 0;
  37.160 +                else
  37.161 +                  return SDL_MUTEX_TIMEDOUT;
  37.162 +              }
  37.163 +        }
  37.164 +        /* never reached */
  37.165 +        return -1;
  37.166 +}
  37.167 +
  37.168 +DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem)
  37.169 +{
  37.170 +        return SDL_SemWaitTimeout(sem, 0);
  37.171 +}
  37.172 +
  37.173 +DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem)
  37.174 +{
  37.175 +        return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
  37.176 +}
  37.177 +
  37.178 +/* Returns the current count of the semaphore */
  37.179 +DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
  37.180 +{
  37.181 +        if ( ! sem ) {
  37.182 +                SDL_SetError("Passed a NULL sem");
  37.183 +                return 0;
  37.184 +        }
  37.185 +        return sem->value;
  37.186 +}
  37.187 +
  37.188 +DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
  37.189 +{
  37.190 +        if ( ! sem ) {
  37.191 +                SDL_SetError("Passed a NULL sem");
  37.192 +                return -1;
  37.193 +        }
  37.194 +        if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) {
  37.195 +                SDL_SetError("DosRequestMutexSem() failed");
  37.196 +                return -1;
  37.197 +        }
  37.198 +        sem->value++;
  37.199 +        DosPostEventSem(sem->changed);
  37.200 +        DosReleaseMutexSem(sem->id);
  37.201 +        return 0;
  37.202 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/src/thread/os2/SDL_systhread.c	Wed Nov 23 07:29:56 2005 +0000
    38.3 @@ -0,0 +1,114 @@
    38.4 +/*
    38.5 +    SDL - Simple DirectMedia Layer
    38.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    38.7 +
    38.8 +    This library is free software; you can redistribute it and/or
    38.9 +    modify it under the terms of the GNU Library General Public
   38.10 +    License as published by the Free Software Foundation; either
   38.11 +    version 2 of the License, or (at your option) any later version.
   38.12 +
   38.13 +    This library is distributed in the hope that it will be useful,
   38.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   38.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   38.16 +    Library General Public License for more details.
   38.17 +
   38.18 +    You should have received a copy of the GNU Library General Public
   38.19 +    License along with this library; if not, write to the Free
   38.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   38.21 +
   38.22 +    Sam Lantinga
   38.23 +    slouken@libsdl.org
   38.24 +*/
   38.25 +
   38.26 +#ifdef SAVE_RCSID
   38.27 +static char rcsid =
   38.28 + "@(#) $Id$";
   38.29 +#endif
   38.30 +
   38.31 +/* OS/2 thread management routines for SDL */
   38.32 +
   38.33 +#include <stdio.h>
   38.34 +#include <stdlib.h>
   38.35 +#include <process.h>
   38.36 +#define INCL_DOSERRORS
   38.37 +#define INCL_DOSPROCESS
   38.38 +#include <os2.h>
   38.39 +
   38.40 +#include "SDL_error.h"
   38.41 +#include "SDL_thread.h"
   38.42 +#include "SDL_systhread.h"
   38.43 +
   38.44 +typedef struct ThreadStartParms
   38.45 +{
   38.46 +  void *args;
   38.47 +  pfnSDL_CurrentEndThread pfnCurrentEndThread;
   38.48 +} tThreadStartParms, *pThreadStartParms;
   38.49 +
   38.50 +static void threadfunc(void *pparm)
   38.51 +{
   38.52 +  pThreadStartParms pThreadParms = pparm;
   38.53 +  pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
   38.54 +
   38.55 +  // Call the thread function!
   38.56 +  SDL_RunThread(pThreadParms->args);
   38.57 +
   38.58 +  // Get the current endthread we have to use!
   38.59 +  if (pThreadParms)
   38.60 +  {
   38.61 +    pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
   38.62 +    free(pThreadParms);
   38.63 +  }
   38.64 +  // Call endthread!
   38.65 +  if (pfnCurrentEndThread)
   38.66 +    (*pfnCurrentEndThread)();
   38.67 +}
   38.68 +
   38.69 +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
   38.70 +{
   38.71 +  pThreadStartParms pThreadParms = malloc(sizeof(tThreadStartParms));
   38.72 +  if (!pThreadParms)
   38.73 +  {
   38.74 +    SDL_SetError("Not enough memory to create thread");
   38.75 +    return(-1);
   38.76 +  }
   38.77 +
   38.78 +  // Save the function which we will have to call to clear the RTL of calling app!
   38.79 +  pThreadParms->pfnCurrentEndThread = pfnEndThread;
   38.80 +  // Also save the real parameters we have to pass to thread function
   38.81 +  pThreadParms->args = args;
   38.82 +  // Start the thread using the runtime library of calling app!
   38.83 +  thread->threadid = thread->handle = (*pfnBeginThread)(threadfunc, 512*1024, pThreadParms);
   38.84 +  if (thread->threadid<=0)
   38.85 +  {
   38.86 +    SDL_SetError("Not enough resources to create thread");
   38.87 +    return(-1);
   38.88 +  }
   38.89 +  return(0);
   38.90 +}
   38.91 +
   38.92 +void SDL_SYS_SetupThread(void)
   38.93 +{
   38.94 +  return;
   38.95 +}
   38.96 +
   38.97 +DECLSPEC Uint32 SDLCALL SDL_ThreadID(void)
   38.98 +{
   38.99 +  PTIB tib;
  38.100 +  DosGetInfoBlocks(&tib, NULL);
  38.101 +  return((Uint32) (tib->tib_ptib2->tib2_ultid));
  38.102 +}
  38.103 +
  38.104 +void SDL_SYS_WaitThread(SDL_Thread *thread)
  38.105 +{
  38.106 +  TID tid = thread->handle;
  38.107 +  DosWaitThread(&tid, DCWW_WAIT);
  38.108 +}
  38.109 +
  38.110 +/* WARNING: This function is really a last resort.
  38.111 + * Threads should be signaled and then exit by themselves.
  38.112 + * TerminateThread() doesn't perform stack and DLL cleanup.
  38.113 + */
  38.114 +void SDL_SYS_KillThread(SDL_Thread *thread)
  38.115 +{
  38.116 +  DosKillThread(thread->handle);
  38.117 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/src/thread/os2/SDL_systhread_c.h	Wed Nov 23 07:29:56 2005 +0000
    39.3 @@ -0,0 +1,27 @@
    39.4 +/*
    39.5 +    SDL - Simple DirectMedia Layer
    39.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    39.7 +
    39.8 +    This library is free software; you can redistribute it and/or
    39.9 +    modify it under the terms of the GNU Library General Public
   39.10 +    License as published by the Free Software Foundation; either
   39.11 +    version 2 of the License, or (at your option) any later version.
   39.12 +
   39.13 +    This library is distributed in the hope that it will be useful,
   39.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   39.16 +    Library General Public License for more details.
   39.17 +
   39.18 +    You should have received a copy of the GNU Library General Public
   39.19 +    License along with this library; if not, write to the Free
   39.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   39.21 +
   39.22 +    Sam Lantinga
   39.23 +    slouken@libsdl.org
   39.24 +*/
   39.25 +
   39.26 +#define INCL_DOSPROCESS
   39.27 +#include <os2.h>
   39.28 +
   39.29 +typedef TID SYS_ThreadHandle;
   39.30 +
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/src/timer/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    40.3 @@ -0,0 +1,27 @@
    40.4 +#=============================================================================
    40.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    40.6 +#
    40.7 +# Makefile for timers
    40.8 +#=============================================================================
    40.9 +
   40.10 +object_files=SDL_timer.obj SDL_systimer.obj
   40.11 +ExtraCFlags=
   40.12 +
   40.13 +#
   40.14 +#==============================================================================
   40.15 +#
   40.16 +!include ..\..\Watcom.mif
   40.17 +
   40.18 +.before
   40.19 +    set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
   40.20 +
   40.21 +all : $(object_files)
   40.22 +
   40.23 +SDL_systimer.obj: .AUTODEPEND
   40.24 +    wcc386 os2\SDL_systimer.c $(cflags)
   40.25 +
   40.26 +clean : .SYMBOLIC
   40.27 +        @if exist *.obj del *.obj
   40.28 +        @if exist *.map del *.map
   40.29 +        @if exist *.res del *.res
   40.30 +        @if exist *.lst del *.lst
    41.1 --- a/src/timer/SDL_timer.c	Wed Nov 23 07:23:48 2005 +0000
    41.2 +++ b/src/timer/SDL_timer.c	Wed Nov 23 07:29:56 2005 +0000
    41.3 @@ -242,7 +242,7 @@
    41.4  }
    41.5  
    41.6  /* Old style callback functions are wrapped through this */
    41.7 -static Uint32 callback_wrapper(Uint32 ms, void *param)
    41.8 +static Uint32 SDLCALL callback_wrapper(Uint32 ms, void *param)
    41.9  {
   41.10  	SDL_TimerCallback func = (SDL_TimerCallback) param;
   41.11  	return (*func)(ms);
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/src/timer/os2/SDL_systimer.c	Wed Nov 23 07:29:56 2005 +0000
    42.3 @@ -0,0 +1,230 @@
    42.4 +/*
    42.5 +    SDL - Simple DirectMedia Layer
    42.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    42.7 +
    42.8 +    This library is free software; you can redistribute it and/or
    42.9 +    modify it under the terms of the GNU Library General Public
   42.10 +    License as published by the Free Software Foundation; either
   42.11 +    version 2 of the License, or (at your option) any later version.
   42.12 +
   42.13 +    This library is distributed in the hope that it will be useful,
   42.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   42.16 +    Library General Public License for more details.
   42.17 +
   42.18 +    You should have received a copy of the GNU Library General Public
   42.19 +    License along with this library; if not, write to the Free
   42.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   42.21 +
   42.22 +    Sam Lantinga
   42.23 +    slouken@libsdl.org
   42.24 +*/
   42.25 +
   42.26 +#ifdef SAVE_RCSID
   42.27 +static char rcsid =
   42.28 + "@(#) $Id$";
   42.29 +#endif
   42.30 +
   42.31 +#define INCL_DOSMISC
   42.32 +#define INCL_DOSERRORS
   42.33 +#define INCL_DOSSEMAPHORES
   42.34 +#define INCL_DOSDATETIME
   42.35 +#define INCL_DOSPROCESS
   42.36 +#define INCL_DOSPROFILE
   42.37 +#define INCL_DOSEXCEPTIONS
   42.38 +#include <os2.h>
   42.39 +
   42.40 +#include "SDL_thread.h"
   42.41 +#include "SDL_timer.h"
   42.42 +#include "SDL_timer_c.h"
   42.43 +#include "SDL_error.h"
   42.44 +
   42.45 +
   42.46 +#define TIME_WRAP_VALUE (~(DWORD)0)
   42.47 +
   42.48 +/* The first high-resolution ticks value of the application */
   42.49 +static long long hires_start_ticks;
   42.50 +/* The number of ticks per second of the high-resolution performance counter */
   42.51 +static ULONG hires_ticks_per_second;
   42.52 +
   42.53 +void SDL_StartTicks(void)
   42.54 +{
   42.55 +        DosTmrQueryFreq(&hires_ticks_per_second);
   42.56 +        DosTmrQueryTime((PQWORD)&hires_start_ticks);
   42.57 +}
   42.58 +
   42.59 +DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
   42.60 +{
   42.61 +        long long hires_now;
   42.62 +        ULONG ticks = ticks;
   42.63 +
   42.64 +        DosTmrQueryTime((PQWORD)&hires_now);
   42.65 +/*
   42.66 +        hires_now -= hires_start_ticks;
   42.67 +        hires_now *= 1000;
   42.68 +        hires_now /= hires_ticks_per_second;
   42.69 +*/
   42.70 +        /* inline asm to avoid runtime inclusion */
   42.71 +        _asm {
   42.72 +           push edx
   42.73 +           push eax
   42.74 +           mov eax, dword ptr hires_now
   42.75 +           mov edx, dword ptr hires_now+4
   42.76 +           sub eax, dword ptr hires_start_ticks
   42.77 +           sbb edx, dword ptr hires_start_ticks+4
   42.78 +           mov ebx,1000
   42.79 +           mov ecx,edx
   42.80 +           mul ebx
   42.81 +           push eax
   42.82 +           push edx
   42.83 +           mov eax,ecx
   42.84 +           mul ebx
   42.85 +           pop eax
   42.86 +           add edx,eax
   42.87 +           pop eax
   42.88 +           mov ebx, dword ptr hires_ticks_per_second
   42.89 +           div ebx
   42.90 +           mov dword ptr ticks, eax
   42.91 +           pop edx
   42.92 +           pop eax
   42.93 +        }
   42.94 +
   42.95 +        return ticks;
   42.96 +
   42.97 +}
   42.98 +
   42.99 +/* High resolution sleep, originally made by Ilya Zakharevich */
  42.100 +DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
  42.101 +{
  42.102 +  /* This is similar to DosSleep(), but has 8ms granularity in time-critical
  42.103 +     threads even on Warp3. */
  42.104 +  HEV     hevEvent1     = 0;   /* Event semaphore handle    */
  42.105 +  HTIMER  htimerEvent1  = 0;   /* Timer handle              */
  42.106 +  APIRET  rc            = NO_ERROR;  /* Return code               */
  42.107 +  int ret = 1;
  42.108 +  ULONG priority = 0, nesting;   /* Shut down the warnings */
  42.109 +  PPIB pib;
  42.110 +  PTIB tib;
  42.111 +  char *e = NULL;
  42.112 +  APIRET badrc;
  42.113 +  int switch_priority = 50;
  42.114 +
  42.115 +  DosCreateEventSem(NULL,      /* Unnamed */
  42.116 +                    &hevEvent1,  /* Handle of semaphore returned */
  42.117 +                    DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */
  42.118 +                    FALSE);      /* Semaphore is in RESET state  */
  42.119 +
  42.120 +  if (ms >= switch_priority)
  42.121 +    switch_priority = 0;
  42.122 +  if (switch_priority)
  42.123 +  {
  42.124 +    if (DosGetInfoBlocks(&tib, &pib)!=NO_ERROR)
  42.125 +      switch_priority = 0;
  42.126 +    else
  42.127 +    {
  42.128 + /* In Warp3, to switch scheduling to 8ms step, one needs to do 
  42.129 +    DosAsyncTimer() in time-critical thread.  On laters versions,
  42.130 +    more and more cases of wait-for-something are covered.
  42.131 +
  42.132 +    It turns out that on Warp3fp42 it is the priority at the time
  42.133 +    of DosAsyncTimer() which matters.  Let's hope that this works
  42.134 +    with later versions too...  XXXX
  42.135 +  */
  42.136 +      priority = (tib->tib_ptib2->tib2_ulpri);
  42.137 +      if ((priority & 0xFF00) == 0x0300) /* already time-critical */
  42.138 +        switch_priority = 0;
  42.139 + /* Make us time-critical.  Just modifying TIB is not enough... */
  42.140 + /* tib->tib_ptib2->tib2_ulpri = 0x0300;*/
  42.141 + /* We do not want to run at high priority if a signal causes us
  42.142 +    to longjmp() out of this section... */
  42.143 +      if (DosEnterMustComplete(&nesting))
  42.144 +        switch_priority = 0;
  42.145 +      else
  42.146 +        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
  42.147 +    }
  42.148 +  }
  42.149 +
  42.150 +  if ((badrc = DosAsyncTimer(ms,
  42.151 +        (HSEM) hevEvent1, /* Semaphore to post        */
  42.152 +        &htimerEvent1))) /* Timer handler (returned) */
  42.153 +    e = "DosAsyncTimer";
  42.154 +
  42.155 +  if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300)
  42.156 +  {
  42.157 + /* Nobody switched priority while we slept...  Ignore errors... */
  42.158 + /* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */
  42.159 +    if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0)))
  42.160 +      rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0);
  42.161 +  }
  42.162 +  if (switch_priority)
  42.163 +    rc = DosExitMustComplete(&nesting); /* Ignore errors */
  42.164 +
  42.165 +  /* The actual blocking call is made with "normal" priority.  This way we
  42.166 +     should not bother with DosSleep(0) etc. to compensate for us interrupting
  42.167 +     higher-priority threads.  The goal is to prohibit the system spending too
  42.168 +     much time halt()ing, not to run us "no matter what". */
  42.169 +  if (!e)     /* Wait for AsyncTimer event */
  42.170 +    badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT);
  42.171 +
  42.172 +  if (e) ;    /* Do nothing */
  42.173 +  else if (badrc == ERROR_INTERRUPT)
  42.174 +    ret = 0;
  42.175 +  else if (badrc)
  42.176 +    e = "DosWaitEventSem";
  42.177 +  if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */
  42.178 +    e = "DosCloseEventSem";
  42.179 +    badrc = rc;
  42.180 +  }
  42.181 +  if (e)
  42.182 +  {
  42.183 +    SDL_SetError("[SDL_Delay] : Had error in %s(), rc is 0x%x\n", e, badrc);
  42.184 +  }
  42.185 +}
  42.186 +
  42.187 +/* Data to handle a single periodic alarm */
  42.188 +static int timer_alive = 0;
  42.189 +static SDL_Thread *timer = NULL;
  42.190 +
  42.191 +static int RunTimer(void *unused)
  42.192 +{
  42.193 +        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
  42.194 +        while ( timer_alive ) {
  42.195 +                if ( SDL_timer_running ) {
  42.196 +                        SDL_ThreadedTimerCheck();
  42.197 +                }
  42.198 +                SDL_Delay(10);
  42.199 +        }
  42.200 +        return(0);
  42.201 +}
  42.202 +
  42.203 +/* This is only called if the event thread is not running */
  42.204 +int SDL_SYS_TimerInit(void)
  42.205 +{
  42.206 +        timer_alive = 1;
  42.207 +        timer = SDL_CreateThread(RunTimer, NULL);
  42.208 +        if ( timer == NULL )
  42.209 +                return(-1);
  42.210 +        return(SDL_SetTimerThreaded(1));
  42.211 +}
  42.212 +
  42.213 +void SDL_SYS_TimerQuit(void)
  42.214 +{
  42.215 +        timer_alive = 0;
  42.216 +        if ( timer ) {
  42.217 +                SDL_WaitThread(timer, NULL);
  42.218 +                timer = NULL;
  42.219 +        }
  42.220 +}
  42.221 +
  42.222 +int SDL_SYS_StartTimer(void)
  42.223 +{
  42.224 +        SDL_SetError("Internal logic error: OS/2 uses threaded timer");
  42.225 +        return(-1);
  42.226 +}
  42.227 +
  42.228 +void SDL_SYS_StopTimer(void)
  42.229 +{
  42.230 +        return;
  42.231 +}
  42.232 +
  42.233 +
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/src/video/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    43.3 @@ -0,0 +1,27 @@
    43.4 +#=============================================================================
    43.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    43.6 +#
    43.7 +# Makefile for threading
    43.8 +#=============================================================================
    43.9 +
   43.10 +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
   43.11 +ExtraCFlags=-dUSE_DOSSETPRIORITY
   43.12 +
   43.13 +#
   43.14 +#==============================================================================
   43.15 +#
   43.16 +!include ..\..\Watcom.mif
   43.17 +
   43.18 +.before
   43.19 +    set include=$(%os2tk)\h;$(%include);../../include;../;./os2;../events;../hermes;$(%FSLIB);
   43.20 +
   43.21 +all : $(object_files)
   43.22 +
   43.23 +SDL_os2fslib.obj : .AUTODEPEND
   43.24 +    wcc386 os2fslib\SDL_os2fslib.c $(cflags)
   43.25 +
   43.26 +clean : .SYMBOLIC
   43.27 +        @if exist *.obj del *.obj
   43.28 +        @if exist *.map del *.map
   43.29 +        @if exist *.res del *.res
   43.30 +        @if exist *.lst del *.lst
    44.1 --- a/src/video/SDL_sysvideo.h	Wed Nov 23 07:23:48 2005 +0000
    44.2 +++ b/src/video/SDL_sysvideo.h	Wed Nov 23 07:29:56 2005 +0000
    44.3 @@ -423,6 +423,9 @@
    44.4  #ifdef ENABLE_RISCOS
    44.5  extern VideoBootStrap RISCOS_bootstrap;
    44.6  #endif
    44.7 +#ifdef __OS2__
    44.8 +extern VideoBootStrap OS2FSLib_bootstrap;
    44.9 +#endif
   44.10  /* This is the current video device */
   44.11  extern SDL_VideoDevice *current_video;
   44.12  
    45.1 --- a/src/video/SDL_video.c	Wed Nov 23 07:23:48 2005 +0000
    45.2 +++ b/src/video/SDL_video.c	Wed Nov 23 07:29:56 2005 +0000
    45.3 @@ -126,6 +126,9 @@
    45.4  #ifdef ENABLE_RISCOS
    45.5      &RISCOS_bootstrap,
    45.6  #endif
    45.7 +#ifdef __OS2__
    45.8 +	&OS2FSLib_bootstrap,
    45.9 +#endif
   45.10  #ifdef ENABLE_DUMMYVIDEO
   45.11  	&DUMMY_bootstrap,
   45.12  #endif
   45.13 @@ -664,7 +667,10 @@
   45.14  	SDL_VideoSurface = NULL;	/* In case it's freed by driver */
   45.15  	mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
   45.16  	if ( mode ) { /* Prevent resize events from mode change */
   45.17 +          /* But not on OS/2 */
   45.18 +#ifndef __OS2__
   45.19  	    SDL_PrivateResize(mode->w, mode->h);
   45.20 +#endif
   45.21  
   45.22  	    /* Sam - If we asked for OpenGL mode, and didn't get it, fail */
   45.23  	    if ( is_opengl && !(mode->flags & SDL_OPENGL) ) {
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/src/video/os2fslib/SDL_os2fslib.c	Wed Nov 23 07:29:56 2005 +0000
    46.3 @@ -0,0 +1,2787 @@
    46.4 +/*
    46.5 +    SDL - Simple DirectMedia Layer
    46.6 +    Copyright (C) 1997-2004 Sam Lantinga
    46.7 +
    46.8 +    This library is free software; you can redistribute it and/or
    46.9 +    modify it under the terms of the GNU Library General Public
   46.10 +    License as published by the Free Software Foundation; either
   46.11 +    version 2 of the License, or (at your option) any later version.
   46.12 +
   46.13 +    This library is distributed in the hope that it will be useful,
   46.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   46.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   46.16 +    Library General Public License for more details.
   46.17 +
   46.18 +    You should have received a copy of the GNU Library General Public
   46.19 +    License along with this library; if not, write to the Free
   46.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   46.21 +
   46.22 +    Sam Lantinga
   46.23 +    slouken@libsdl.org
   46.24 +*/
   46.25 +
   46.26 +#include <stdio.h>
   46.27 +#include <stdlib.h>
   46.28 +#include <string.h>
   46.29 +#include <process.h>
   46.30 +#include <time.h>
   46.31 +
   46.32 +#include "SDL.h"
   46.33 +#include "SDL_error.h"
   46.34 +#include "SDL_video.h"
   46.35 +#include "SDL_mouse.h"
   46.36 +#include "SDL_sysvideo.h"
   46.37 +#include "SDL_pixels_c.h"
   46.38 +#include "SDL_events_c.h"
   46.39 +
   46.40 +#include "SDL_os2fslib.h"
   46.41 +
   46.42 +static ULONG ulFCFToUse =
   46.43 +        FCF_TITLEBAR |
   46.44 +        FCF_SYSMENU |
   46.45 +        FCF_MINBUTTON |
   46.46 +        FCF_MAXBUTTON |
   46.47 +        FCF_NOBYTEALIGN |
   46.48 +        FCF_SIZEBORDER |
   46.49 +        FCF_TASKLIST;
   46.50 +
   46.51 +static int bMouseCaptured   = 0;
   46.52 +static int bMouseCapturable = 0;
   46.53 +static HPOINTER hptrGlobalPointer = NULL;
   46.54 +static HPOINTER hptrCurrentIcon = NULL;
   46.55 +static int iWindowSizeX = 320;
   46.56 +static int iWindowSizeY = 200;
   46.57 +static int bWindowResized = 0;
   46.58 +
   46.59 +#pragma pack(1)
   46.60 +typedef struct BMPINFO
   46.61 +{
   46.62 +   BITMAPINFO;
   46.63 +   RGB  clr;
   46.64 +} BMPINFO, *PBMPINFO;
   46.65 +#pragma pack()
   46.66 +
   46.67 +
   46.68 +// Backdoors:
   46.69 +DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF)
   46.70 +{
   46.71 +  ulFCFToUse = ulFCF;
   46.72 +}
   46.73 +
   46.74 +// Configuration defines:
   46.75 +
   46.76 +// We have to report empty alpha mask, otherwise SDL will select
   46.77 +// alpha blitters, and this will have unwanted results, as we don't
   46.78 +// support alpha channel in FSLib yet.
   46.79 +#define REPORT_EMPTY_ALPHA_MASK
   46.80 +
   46.81 +// Experimental: Move every FSLib_BitBlt() call into window message
   46.82 +// processing function.
   46.83 +// This may fix dirt left on desktop. Or not.
   46.84 +//#define BITBLT_IN_WINMESSAGEPROC
   46.85 +
   46.86 +// Experimental-2: Use WinLockWindowUpdate() in around bitblts!
   46.87 +// This is not enabled, because it seems to cause more problems
   46.88 +// than good.
   46.89 +//#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
   46.90 +
   46.91 +// Use the following to show resized image instead of black stuff
   46.92 +// even if the surface is resizable.
   46.93 +//#define RESIZE_EVEN_IF_RESIZABLE
   46.94 +
   46.95 +/* The translation table from a VK keysym to a SDL keysym */
   46.96 +static SDLKey HWScanKeyMap[256];
   46.97 +static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed);
   46.98 +static int  iShiftIsPressed;
   46.99 +
  46.100 +#ifdef BITBLT_IN_WINMESSAGEPROC
  46.101 +#define WM_UPDATERECTSREQUEST   WM_USER+50
  46.102 +#endif
  46.103 +
  46.104 +#ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
  46.105 +#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
  46.106 +    { \
  46.107 +      WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \
  46.108 +      FSLib_BitBlt(hwnd, buffer, top, left, width, height); \
  46.109 +      WinLockWindowUpdate(HWND_DESKTOP, NULL); \
  46.110 +    }
  46.111 +#else
  46.112 +#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
  46.113 +    FSLib_BitBlt(hwnd, buffer, top, left, width, height);
  46.114 +#endif
  46.115 +
  46.116 +/////////////////////////////////////////////////////////////////////
  46.117 +//
  46.118 +// SetAccessableWindowPos
  46.119 +//
  46.120 +// Same as WinSetWindowPos(), but takes care for the window to be
  46.121 +// always on the screen, the titlebar will be accessable everytime.
  46.122 +//
  46.123 +/////////////////////////////////////////////////////////////////////
  46.124 +static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind,
  46.125 +				   LONG x, LONG y,
  46.126 +				   LONG cx, LONG cy,
  46.127 +                                   ULONG fl)
  46.128 +{
  46.129 +  SWP swpDesktop, swp;
  46.130 +  // Get desktop area
  46.131 +  WinQueryWindowPos(HWND_DESKTOP, &swpDesktop);
  46.132 +
  46.133 +  if ((fl & SWP_MOVE) && (fl & SWP_SIZE))
  46.134 +  {
  46.135 +    // If both moving and sizing, then change size and pos now!!
  46.136 +    if (x+cx>swpDesktop.cx)
  46.137 +      x = swpDesktop.cx - cx;
  46.138 +    if (x<0)
  46.139 +      x = 0;
  46.140 +    if (y<0)
  46.141 +      y = 0;
  46.142 +    if (y+cy>swpDesktop.cy)
  46.143 +      y = swpDesktop.cy - cy;
  46.144 +    return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
  46.145 +  } else
  46.146 +  if (fl & SWP_MOVE)
  46.147 +  {
  46.148 +    // Just moving
  46.149 +    WinQueryWindowPos(hwnd, &swp);
  46.150 +    if (x+swp.cx>swpDesktop.cx)
  46.151 +      x = swpDesktop.cx - swp.cx;
  46.152 +    if (x<0)
  46.153 +      x = 0;
  46.154 +    if (y<0)
  46.155 +      y = 0;
  46.156 +    if (y+swp.cy>swpDesktop.cy)
  46.157 +      y = swpDesktop.cy - swp.cy;
  46.158 +    return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
  46.159 +  } else
  46.160 +  if (fl & SWP_SIZE)
  46.161 +  {
  46.162 +    // Just sizing
  46.163 +    WinQueryWindowPos(hwnd, &swp);
  46.164 +    x = swp.x;
  46.165 +    y = swp.y;
  46.166 +    if (x+cx>swpDesktop.cx)
  46.167 +      x = swpDesktop.cx - cx;
  46.168 +    if (x<0)
  46.169 +      x = 0;
  46.170 +    if (y<0)
  46.171 +      y = 0;
  46.172 +    if (y+cy>swpDesktop.cy)
  46.173 +      y = swpDesktop.cy - cy;
  46.174 +    return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE);
  46.175 +  } else
  46.176 +  return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
  46.177 +}
  46.178 +
  46.179 +/////////////////////////////////////////////////////////////////////
  46.180 +//
  46.181 +// TranslateKey
  46.182 +//
  46.183 +// This creates SDL Keycodes from VK_ and hardware scan codes
  46.184 +//
  46.185 +/////////////////////////////////////////////////////////////////////
  46.186 +static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed)
  46.187 +{
  46.188 +  keysym->scancode = (unsigned char) scancode;
  46.189 +  keysym->mod = KMOD_NONE;
  46.190 +  keysym->unicode = 0;
  46.191 +
  46.192 +  if (iPressed && SDL_TranslateUNICODE)
  46.193 +  {
  46.194 +    // TODO:
  46.195 +    // Implement real unicode conversion!
  46.196 +    if (chcode)
  46.197 +      keysym->unicode = chcode;
  46.198 +    else
  46.199 +      keysym->unicode = vkey;
  46.200 +  }
  46.201 +
  46.202 +  keysym->sym = HWScanKeyMap[scancode];
  46.203 +
  46.204 +  // Now stuffs based on state of shift key(s)!
  46.205 +  if (vkey == VK_SHIFT)
  46.206 +  {
  46.207 +    iShiftIsPressed = iPressed;
  46.208 +  }
  46.209 +
  46.210 +  if ((iShiftIsPressed) && (SDL_TranslateUNICODE))
  46.211 +  {
  46.212 +    // Change syms, if Unicode stuff is required
  46.213 +    // I think it's silly, but it's SDL...
  46.214 +    switch (keysym->sym)
  46.215 +    {
  46.216 +      case SDLK_BACKQUOTE:
  46.217 +	keysym->sym = '~';
  46.218 +	break;
  46.219 +      case SDLK_1:
  46.220 +	keysym->sym = SDLK_EXCLAIM;
  46.221 +	break;
  46.222 +      case SDLK_2:
  46.223 +	keysym->sym = SDLK_AT;
  46.224 +	break;
  46.225 +      case SDLK_3:
  46.226 +	keysym->sym = SDLK_HASH;
  46.227 +	break;
  46.228 +      case SDLK_4:
  46.229 +	keysym->sym = SDLK_DOLLAR;
  46.230 +	break;
  46.231 +      case SDLK_5:
  46.232 +	keysym->sym = '%';
  46.233 +	break;
  46.234 +      case SDLK_6:
  46.235 +	keysym->sym = SDLK_CARET;
  46.236 +	break;
  46.237 +      case SDLK_7:
  46.238 +	keysym->sym = SDLK_AMPERSAND;
  46.239 +	break;
  46.240 +      case SDLK_8:
  46.241 +	keysym->sym = SDLK_ASTERISK;
  46.242 +	break;
  46.243 +      case SDLK_9:
  46.244 +	keysym->sym = SDLK_LEFTPAREN;
  46.245 +	break;
  46.246 +      case SDLK_0:
  46.247 +	keysym->sym = SDLK_RIGHTPAREN;
  46.248 +	break;
  46.249 +      case SDLK_MINUS:
  46.250 +	keysym->sym = SDLK_UNDERSCORE;
  46.251 +	break;
  46.252 +      case SDLK_PLUS:
  46.253 +	keysym->sym = SDLK_EQUALS;
  46.254 +	break;
  46.255 +
  46.256 +      case SDLK_LEFTBRACKET:
  46.257 +	keysym->sym = '{';
  46.258 +	break;
  46.259 +      case SDLK_RIGHTBRACKET:
  46.260 +	keysym->sym = '}';
  46.261 +	break;
  46.262 +
  46.263 +      case SDLK_SEMICOLON:
  46.264 +	keysym->sym = SDLK_COLON;
  46.265 +	break;
  46.266 +      case SDLK_QUOTE:
  46.267 +	keysym->sym = SDLK_QUOTEDBL;
  46.268 +	break;
  46.269 +      case SDLK_BACKSLASH:
  46.270 +	keysym->sym = '|';
  46.271 +	break;
  46.272 +
  46.273 +      case SDLK_COMMA:
  46.274 +	keysym->sym = SDLK_LESS;
  46.275 +	break;
  46.276 +      case SDLK_PERIOD:
  46.277 +	keysym->sym = SDLK_GREATER;
  46.278 +	break;
  46.279 +      case SDLK_SLASH:
  46.280 +	keysym->sym = SDLK_QUESTION;
  46.281 +	break;
  46.282 +
  46.283 +      default:
  46.284 +	break;
  46.285 +    }
  46.286 +  }
  46.287 +  return keysym;
  46.288 +}
  46.289 +
  46.290 +#define CONVERTMOUSEPOSITION()  \
  46.291 +        /* We have to inverse the mouse position, because every non-os/2 system */                                                \
  46.292 +        /* has a coordinate system where the (0;0) is the top-left corner,      */                                                \
  46.293 +	/* while on os/2 it's the bottom left corner!                           */                                                \
  46.294 +	if (FSLib_QueryFSMode(hwnd))                                                                                              \
  46.295 +	{                                                                                                                         \
  46.296 +	  /* We're in FS mode!                                                        */                                          \
  46.297 +	  /* In FS mode our window is as big as fullscreen mode, but not necessary as */                                          \
  46.298 +	  /* big as the source buffer (can be bigger)                                 */                                          \
  46.299 +          /* So, limit mouse pos to source buffer size!                               */                                          \
  46.300 +	  if (ppts->x<0) ppts->x = 0;                                                                                             \
  46.301 +	  if (ppts->y<0) ppts->y = 0;                                                                                             \
  46.302 +	  if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1;      \
  46.303 +          if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1;      \
  46.304 +          pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */                                   \
  46.305 +          ptl.x = ppts->x; ptl.y = ppts->y;                                                                                       \
  46.306 +          WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);                                                  \
  46.307 +	  WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y);                                                                           \
  46.308 +	  /* Then convert OS/2 position to SDL position */                                                                        \
  46.309 +          ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1;                                                    \
  46.310 +	} else                                                                                                                    \
  46.311 +	{                                                                                                                         \
  46.312 +	  SWP swpClient;                                                                                                          \
  46.313 +          /* We're in windowed mode! */                                                                                           \
  46.314 +	  WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);                                                              \
  46.315 +          /* Convert OS/2 mouse position to SDL position, and also scale it! */                                                   \
  46.316 +	  (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx;                                       \
  46.317 +	  (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy;                                       \
  46.318 +	  (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y)  - 1;                                                 \
  46.319 +	}
  46.320 +
  46.321 +
  46.322 +
  46.323 +/////////////////////////////////////////////////////////////////////
  46.324 +//
  46.325 +// WndProc
  46.326 +//
  46.327 +// This is the message processing window procedure for the
  46.328 +// SDLWindowClass, which is the client window in our application.
  46.329 +// It handles switching back and away from the app (taking care of
  46.330 +// going out and back to and from fullscreen mode), sending keystrokes
  46.331 +// and mouse events to where it has to be sent, etc...
  46.332 +//
  46.333 +/////////////////////////////////////////////////////////////////////
  46.334 +static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  46.335 +{
  46.336 +  HPS ps;
  46.337 +  RECTL rcl;
  46.338 +  SDL_VideoDevice *pVideo = NULL;
  46.339 +
  46.340 +  switch (msg)
  46.341 +  {
  46.342 +    case WM_CHAR:  // Keypress notification
  46.343 +#ifdef DEBUG_BUILD
  46.344 +//      printf("WM_CHAR\n"); fflush(stdout);
  46.345 +#endif
  46.346 +      pVideo = WinQueryWindowPtr(hwnd, 0);
  46.347 +      if (pVideo)
  46.348 +      {
  46.349 +        /*
  46.350 +        // We skip repeated keys:
  46.351 +        if (CHARMSG(&msg)->cRepeat>1)
  46.352 +        {
  46.353 +#ifdef DEBUG_BUILD
  46.354 +//          printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout);
  46.355 +#endif
  46.356 +          return (MRESULT) TRUE;
  46.357 +        }
  46.358 +        */
  46.359 +
  46.360 +        // If it's not repeated, then let's see if its pressed or released!
  46.361 +	if (SHORT1FROMMP(mp1) & KC_KEYUP)
  46.362 +	{
  46.363 +	  // A key has been released
  46.364 +          SDL_keysym keysym;
  46.365 +
  46.366 +#ifdef DEBUG_BUILD
  46.367 +//          printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
  46.368 +#endif
  46.369 +
  46.370 +          // One problem is with F1, which gets only the keyup message because
  46.371 +          // it is a system key.
  46.372 +	  // So, when we get keyup message, we simulate keydown too!
  46.373 +	  // UPDATE:
  46.374 +	  //  This problem should be solved now, that the accelerator keys are
  46.375 +	  //  disabled for this window!
  46.376 +          /*
  46.377 +          if (SHORT2FROMMP(mp2)==VK_F1)
  46.378 +          {
  46.379 +            SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
  46.380 +                                                           SHORT1FROMMP(mp2), // Character code
  46.381 +                                                           CHAR4FROMMP(mp1),  // HW Scan code
  46.382 +                                                           &keysym,0));
  46.383 +	  }*/
  46.384 +
  46.385 +          SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
  46.386 +							 SHORT1FROMMP(mp2), // Character code
  46.387 +							 CHAR4FROMMP(mp1),  // HW Scan code
  46.388 +                                                         &keysym,0));
  46.389 +          
  46.390 +	} else
  46.391 +	{
  46.392 +          // A key has been pressed
  46.393 +          SDL_keysym keysym;
  46.394 +
  46.395 +#ifdef DEBUG_BUILD
  46.396 +//          printf("WM_CHAR, keydown, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
  46.397 +#endif
  46.398 +	  // Check for fastkeys: ALT+HOME to toggle FS mode
  46.399 +          //                     ALT+END to close app
  46.400 +	  if ((SHORT1FROMMP(mp1) & KC_ALT) &&
  46.401 +	      (SHORT2FROMMP(mp2) == VK_HOME))
  46.402 +	  {
  46.403 +#ifdef DEBUG_BUILD
  46.404 +	    printf(" Pressed ALT+HOME!\n"); fflush(stdout);
  46.405 +#endif
  46.406 +	    // Only switch between fullscreen and back if it's not
  46.407 +	    // a resizable mode!
  46.408 +            if (
  46.409 +                (!pVideo->hidden->pSDLSurface) ||
  46.410 +                ((pVideo->hidden->pSDLSurface)
  46.411 +                 && ((pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE)==0)
  46.412 +                )
  46.413 +               )
  46.414 +	      FSLib_ToggleFSMode(hwnd, !FSLib_QueryFSMode(hwnd));
  46.415 +#ifdef DEBUG_BUILD
  46.416 +            else
  46.417 +	      printf(" Resizable mode, so discarding ALT+HOME!\n"); fflush(stdout);
  46.418 +#endif
  46.419 +	  } else
  46.420 +	  if ((SHORT1FROMMP(mp1) & KC_ALT) &&
  46.421 +	      (SHORT2FROMMP(mp2) == VK_END))
  46.422 +          {
  46.423 +#ifdef DEBUG_BUILD
  46.424 +            printf(" Pressed ALT+END!\n"); fflush(stdout);
  46.425 +#endif
  46.426 +            // Close window, and get out of loop!
  46.427 +            // Also send event to SDL application, but we won't
  46.428 +            // wait for it to be processed!
  46.429 +            SDL_PrivateQuit();
  46.430 +            WinPostMsg(hwnd, WM_QUIT, 0, 0);
  46.431 +	  } else
  46.432 +          {
  46.433 +            
  46.434 +	    SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
  46.435 +							  SHORT1FROMMP(mp2), // Character code
  46.436 +							  CHAR4FROMMP(mp1),  // HW Scan code
  46.437 +                                                          &keysym,1));
  46.438 +            
  46.439 +	  }
  46.440 +	}
  46.441 +      }
  46.442 +      return (MRESULT) TRUE;
  46.443 +
  46.444 +    case WM_TRANSLATEACCEL:
  46.445 +      {
  46.446 +	PQMSG pqmsg;
  46.447 +	pqmsg = (PQMSG) mp1;
  46.448 +	if (mp1)
  46.449 +	{
  46.450 +	  if (pqmsg->msg == WM_CHAR)
  46.451 +	  {
  46.452 +	    // WM_CHAR message!
  46.453 +	    // Let's filter the ALT keypress and all other acceleration keys!
  46.454 +	    return (MRESULT) FALSE;
  46.455 +	  }
  46.456 +	}
  46.457 +        break; // Default processing (pass to parent until frame control)
  46.458 +      }
  46.459 +
  46.460 +    case WM_PAINT:  // Window redraw!
  46.461 +#ifdef DEBUG_BUILD
  46.462 +      printf("WM_PAINT (0x%x)\n", hwnd); fflush(stdout);
  46.463 +#endif
  46.464 +      ps = WinBeginPaint(hwnd,0,&rcl);
  46.465 +      pVideo = FSLib_GetUserParm(hwnd);
  46.466 +      if (pVideo)
  46.467 +      {
  46.468 +        if (!pVideo->hidden->pSDLSurface)
  46.469 +        {
  46.470 +          RECTL rclRect;
  46.471 +          // So, don't blit now!
  46.472 +#ifdef DEBUG_BUILD
  46.473 +          printf("WM_PAINT : Skipping blit while resizing (Pre!)!\n"); fflush(stdout);
  46.474 +#endif
  46.475 +          WinQueryWindowRect(hwnd, &rclRect);
  46.476 +          // Fill with black
  46.477 +          WinFillRect(ps, &rclRect, CLR_BLACK);
  46.478 +        } else
  46.479 +        {
  46.480 +          if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
  46.481 +          {
  46.482 +            int iTop, iLeft, iWidth, iHeight;
  46.483 +            int iXScaleError, iYScaleError;
  46.484 +            int iXScaleError2, iYScaleError2;
  46.485 +            SWP swp;
  46.486 +            
  46.487 +            // Re-blit the modified area!
  46.488 +            // For this, we have to calculate the points, scaled!
  46.489 +            WinQueryWindowPos(hwnd, &swp);
  46.490 +#ifdef DEBUG_BUILD
  46.491 +            printf("WM_PAINT : WinSize: %d %d, BufSize: %d %d\n",
  46.492 +                   swp.cx,
  46.493 +                   swp.cy,
  46.494 +                   pVideo->hidden->SrcBufferDesc.uiXResolution,
  46.495 +                   pVideo->hidden->SrcBufferDesc.uiYResolution
  46.496 +                  );
  46.497 +            fflush(stdout);
  46.498 +#endif
  46.499 +
  46.500 +#ifndef RESIZE_EVEN_IF_RESIZABLE
  46.501 +            // But only blit if the window is not resizable, or if
  46.502 +            // the window is resizable and the source buffer size is the
  46.503 +            // same as the destination buffer size!
  46.504 +            if ((!pVideo->hidden->pSDLSurface) ||
  46.505 +                ((pVideo->hidden->pSDLSurface) &&
  46.506 +                 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
  46.507 +                 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
  46.508 +                  (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
  46.509 +                 ) &&
  46.510 +                 (!FSLib_QueryFSMode(hwnd))
  46.511 +                )
  46.512 +               )
  46.513 +            {
  46.514 +              RECTL rclRect;
  46.515 +              // Resizable surface and in resizing!
  46.516 +              // So, don't blit now!
  46.517 +#ifdef DEBUG_BUILD
  46.518 +              printf("WM_PAINT : Skipping blit while resizing!\n"); fflush(stdout);
  46.519 +#endif
  46.520 +              WinQueryWindowRect(hwnd, &rclRect);
  46.521 +              // Fill with black
  46.522 +              WinFillRect(ps, &rclRect, CLR_BLACK);
  46.523 +            } else
  46.524 +#endif
  46.525 +            {
  46.526 +  
  46.527 +              iXScaleError = (pVideo->hidden->SrcBufferDesc.uiXResolution-1) / swp.cx;
  46.528 +              iYScaleError = (pVideo->hidden->SrcBufferDesc.uiYResolution-1) / swp.cy;
  46.529 +              if (iXScaleError<0) iXScaleError = 0;
  46.530 +              if (iYScaleError<0) iYScaleError = 0;
  46.531 +              iXScaleError2 = (swp.cx-1)/(pVideo->hidden->SrcBufferDesc.uiXResolution);
  46.532 +              iYScaleError2 = (swp.cy-1)/(pVideo->hidden->SrcBufferDesc.uiYResolution);
  46.533 +              if (iXScaleError2<0) iXScaleError2 = 0;
  46.534 +              if (iYScaleError2<0) iYScaleError2 = 0;
  46.535 +      
  46.536 +              iTop = (swp.cy - rcl.yTop) * pVideo->hidden->SrcBufferDesc.uiYResolution / swp.cy - iYScaleError;
  46.537 +              iLeft = rcl.xLeft * pVideo->hidden->SrcBufferDesc.uiXResolution / swp.cx - iXScaleError;
  46.538 +              iWidth = ((rcl.xRight-rcl.xLeft) * pVideo->hidden->SrcBufferDesc.uiXResolution + swp.cx-1)
  46.539 +                / swp.cx + 2*iXScaleError;
  46.540 +              iHeight = ((rcl.yTop-rcl.yBottom) * pVideo->hidden->SrcBufferDesc.uiYResolution + swp.cy-1)
  46.541 +                / swp.cy + 2*iYScaleError;
  46.542 +      
  46.543 +              iWidth+=iXScaleError2;
  46.544 +              iHeight+=iYScaleError2;
  46.545 +      
  46.546 +              if (iTop<0) iTop = 0;
  46.547 +              if (iLeft<0) iLeft = 0;
  46.548 +              if (iTop+iHeight>pVideo->hidden->SrcBufferDesc.uiYResolution) iHeight = pVideo->hidden->SrcBufferDesc.uiYResolution-iTop;
  46.549 +              if (iLeft+iWidth>pVideo->hidden->SrcBufferDesc.uiXResolution) iWidth = pVideo->hidden->SrcBufferDesc.uiXResolution-iLeft;
  46.550 +    
  46.551 +#ifdef DEBUG_BUILD
  46.552 +              printf("WM_PAINT : BitBlt: %d %d -> %d %d (Buf %d x %d)\n",
  46.553 +                     iTop, iLeft, iWidth, iHeight,
  46.554 +                     pVideo->hidden->SrcBufferDesc.uiXResolution,
  46.555 +                     pVideo->hidden->SrcBufferDesc.uiYResolution
  46.556 +                    );
  46.557 +              fflush(stdout);
  46.558 +#endif
  46.559 +                    
  46.560 +              FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, iTop, iLeft, iWidth, iHeight);
  46.561 +            }
  46.562 +  
  46.563 +            DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
  46.564 +          }
  46.565 +        }
  46.566 +      }
  46.567 +#ifdef DEBUG_BUILD
  46.568 +      else
  46.569 +      {
  46.570 +	printf("WM_PAINT : No pVideo!\n"); fflush(stdout);
  46.571 +      }
  46.572 +#endif
  46.573 +      WinEndPaint(ps);
  46.574 +#ifdef DEBUG_BUILD
  46.575 +      printf("WM_PAINT : Done.\n");
  46.576 +      fflush(stdout);
  46.577 +#endif
  46.578 +      return 0;
  46.579 +
  46.580 +    case WM_SIZE:
  46.581 +      {
  46.582 +#ifdef DEBUG_BUILD
  46.583 +	printf("WM_SIZE : (%d %d)\n",
  46.584 +	       SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); fflush(stdout);
  46.585 +#endif
  46.586 +        iWindowSizeX = SHORT1FROMMP(mp2);
  46.587 +        iWindowSizeY = SHORT2FROMMP(mp2);
  46.588 +        bWindowResized = 1;
  46.589 +
  46.590 +	// Make sure the window will be redrawn
  46.591 +        WinInvalidateRegion(hwnd, NULL, TRUE);
  46.592 +      }
  46.593 +      break;
  46.594 +
  46.595 +    case WM_FSLIBNOTIFICATION:
  46.596 +#ifdef DEBUG_BUILD
  46.597 +        printf("WM_FSLIBNOTIFICATION\n"); fflush(stdout);
  46.598 +#endif
  46.599 +      if ((int)mp1 == FSLN_TOGGLEFSMODE)
  46.600 +      {
  46.601 +	// FS mode changed, reblit image!
  46.602 +	pVideo = FSLib_GetUserParm(hwnd);
  46.603 +	if (pVideo)
  46.604 +        {
  46.605 +          if (!pVideo->hidden->pSDLSurface)
  46.606 +          {
  46.607 +            // Resizable surface and in resizing!
  46.608 +            // So, don't blit now!
  46.609 +#ifdef DEBUG_BUILD
  46.610 +            printf("WM_FSLIBNOTIFICATION : Can not blit if there is no surface, doing nothing.\n"); fflush(stdout);
  46.611 +#endif
  46.612 +          } else
  46.613 +          {
  46.614 +            if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
  46.615 +            {
  46.616 +              if (pVideo->hidden->pSDLSurface)
  46.617 +              {
  46.618 +#ifndef RESIZE_EVEN_IF_RESIZABLE
  46.619 +                SWP swp;
  46.620 +
  46.621 +                // But only blit if the window is not resizable, or if
  46.622 +                // the window is resizable and the source buffer size is the
  46.623 +                // same as the destination buffer size!
  46.624 +                WinQueryWindowPos(hwnd, &swp);
  46.625 +                if ((!pVideo->hidden->pSDLSurface) ||
  46.626 +                    (
  46.627 +                     (pVideo->hidden->pSDLSurface) &&
  46.628 +                     (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
  46.629 +                     ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
  46.630 +                      (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
  46.631 +                     ) &&
  46.632 +                     (!FSLib_QueryFSMode(hwnd))
  46.633 +                    )
  46.634 +                   )
  46.635 +                {
  46.636 +                  // Resizable surface and in resizing!
  46.637 +                  // So, don't blit now!
  46.638 +#ifdef DEBUG_BUILD
  46.639 +                  printf("WM_FSLIBNOTIFICATION : Cannot blit while resizing, doing nothing.\n"); fflush(stdout);
  46.640 +#endif
  46.641 +                } else
  46.642 +#endif
  46.643 +                {
  46.644 +#ifdef DEBUG_BUILD
  46.645 +                  printf("WM_FSLIBNOTIFICATION : Blitting!\n"); fflush(stdout);
  46.646 +#endif
  46.647 +                  FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
  46.648 +                               0, 0,
  46.649 +                               pVideo->hidden->SrcBufferDesc.uiXResolution,
  46.650 +                               pVideo->hidden->SrcBufferDesc.uiYResolution);
  46.651 +                }
  46.652 +              }
  46.653 +#ifdef DEBUG_BUILD
  46.654 +              else
  46.655 +                printf("WM_FSLIBNOTIFICATION : No public surface!\n"); fflush(stdout);
  46.656 +#endif
  46.657 +  
  46.658 +              DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
  46.659 +            }
  46.660 +          }
  46.661 +	}
  46.662 +      }
  46.663 +      return (MPARAM) 1;
  46.664 +
  46.665 +    case WM_ACTIVATE:
  46.666 +#ifdef DEBUG_BUILD
  46.667 +      printf("WM_ACTIVATE\n"); fflush(stdout);
  46.668 +#endif
  46.669 +
  46.670 +      pVideo = FSLib_GetUserParm(hwnd);
  46.671 +      if (pVideo)
  46.672 +      {
  46.673 +        pVideo->hidden->fInFocus = (int) mp1;
  46.674 +        if (pVideo->hidden->fInFocus)
  46.675 +        {
  46.676 +          // Went into focus
  46.677 +          if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
  46.678 +            WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
  46.679 +          else
  46.680 +	    WinSetPointer(HWND_DESKTOP, NULL);
  46.681 +
  46.682 +	  if (bMouseCapturable)
  46.683 +	  {
  46.684 +            // Re-capture the mouse, if we captured it before!
  46.685 +	    WinSetCapture(HWND_DESKTOP, hwnd);
  46.686 +            bMouseCaptured = 1;
  46.687 +            {
  46.688 +              SWP swpClient;
  46.689 +              POINTL ptl;
  46.690 +              // Center the mouse to the middle of the window!
  46.691 +              WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
  46.692 +              ptl.x = 0; ptl.y = 0;
  46.693 +              WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
  46.694 +              pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */
  46.695 +              WinSetPointerPos(HWND_DESKTOP,
  46.696 +                               ptl.x + swpClient.cx/2,
  46.697 +                               ptl.y + swpClient.cy/2);
  46.698 +            }
  46.699 +	  }
  46.700 +        } else
  46.701 +        {
  46.702 +          // Went out of focus
  46.703 +	  WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
  46.704 +
  46.705 +	  if (bMouseCaptured)
  46.706 +	  {
  46.707 +            // Release the mouse
  46.708 +	    WinSetCapture(HWND_DESKTOP, hwnd);
  46.709 +            bMouseCaptured = 0;
  46.710 +	  }
  46.711 +        }
  46.712 +      }
  46.713 +#ifdef DEBUG_BUILD
  46.714 +      printf("WM_ACTIVATE done\n"); fflush(stdout);
  46.715 +#endif
  46.716 +
  46.717 +      break;
  46.718 +
  46.719 +    case WM_BUTTON1DOWN:
  46.720 +#ifdef DEBUG_BUILD
  46.721 +      printf("WM_BUTTON1DOWN\n"); fflush(stdout);
  46.722 +#endif
  46.723 +
  46.724 +      pVideo = FSLib_GetUserParm(hwnd);
  46.725 +      if (pVideo)
  46.726 +      {
  46.727 +	SDL_PrivateMouseButton(SDL_PRESSED,
  46.728 +                               SDL_BUTTON_LEFT,
  46.729 +                               0, 0); // Don't report mouse movement!
  46.730 +
  46.731 +	if (bMouseCapturable)
  46.732 +	{
  46.733 +	  // We should capture the mouse!
  46.734 +	  if (!bMouseCaptured)
  46.735 +	  {
  46.736 +	    WinSetCapture(HWND_DESKTOP, hwnd);
  46.737 +            WinSetPointer(HWND_DESKTOP, NULL);
  46.738 +            bMouseCaptured = 1;
  46.739 +            {
  46.740 +              SWP swpClient;
  46.741 +              POINTL ptl;
  46.742 +              // Center the mouse to the middle of the window!
  46.743 +              WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
  46.744 +              ptl.x = 0; ptl.y = 0;
  46.745 +              WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
  46.746 +              pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */
  46.747 +              WinSetPointerPos(HWND_DESKTOP,
  46.748 +                               ptl.x + swpClient.cx/2,
  46.749 +                               ptl.y + swpClient.cy/2);
  46.750 +            }
  46.751 +	  }
  46.752 +	}
  46.753 +      }
  46.754 +      break;
  46.755 +    case WM_BUTTON1UP:
  46.756 +#ifdef DEBUG_BUILD
  46.757 +      printf("WM_BUTTON1UP\n"); fflush(stdout);
  46.758 +#endif
  46.759 +      SDL_PrivateMouseButton(SDL_RELEASED,
  46.760 +                             SDL_BUTTON_LEFT,
  46.761 +                             0, 0); // Don't report mouse movement!
  46.762 +      break;
  46.763 +    case WM_BUTTON2DOWN:
  46.764 +#ifdef DEBUG_BUILD
  46.765 +      printf("WM_BUTTON2DOWN\n"); fflush(stdout);
  46.766 +#endif
  46.767 +
  46.768 +      pVideo = FSLib_GetUserParm(hwnd);
  46.769 +      if (pVideo)
  46.770 +      {
  46.771 +	SDL_PrivateMouseButton(SDL_PRESSED,
  46.772 +                               SDL_BUTTON_RIGHT,
  46.773 +                               0, 0); // Don't report mouse movement!
  46.774 +
  46.775 +	if (bMouseCapturable)
  46.776 +	{
  46.777 +	  // We should capture the mouse!
  46.778 +	  if (!bMouseCaptured)
  46.779 +	  {
  46.780 +	    WinSetCapture(HWND_DESKTOP, hwnd);
  46.781 +            WinSetPointer(HWND_DESKTOP, NULL);
  46.782 +            bMouseCaptured = 1;
  46.783 +            {
  46.784 +              SWP swpClient;
  46.785 +              POINTL ptl;
  46.786 +              // Center the mouse to the middle of the window!
  46.787 +              WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
  46.788 +              ptl.x = 0; ptl.y = 0;
  46.789 +              WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
  46.790 +              pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */
  46.791 +              WinSetPointerPos(HWND_DESKTOP,
  46.792 +                               ptl.x + swpClient.cx/2,
  46.793 +                               ptl.y + swpClient.cy/2);
  46.794 +            }
  46.795 +	  }
  46.796 +	}
  46.797 +
  46.798 +      }
  46.799 +      break;
  46.800 +    case WM_BUTTON2UP:
  46.801 +#ifdef DEBUG_BUILD
  46.802 +      printf("WM_BUTTON2UP\n"); fflush(stdout);
  46.803 +#endif
  46.804 +      SDL_PrivateMouseButton(SDL_RELEASED,
  46.805 +                             SDL_BUTTON_RIGHT,
  46.806 +                             0, 0); // Don't report mouse movement!
  46.807 +      break;
  46.808 +    case WM_BUTTON3DOWN:
  46.809 +#ifdef DEBUG_BUILD
  46.810 +      printf("WM_BUTTON3DOWN\n"); fflush(stdout);
  46.811 +#endif
  46.812 +
  46.813 +      pVideo = FSLib_GetUserParm(hwnd);
  46.814 +      if (pVideo)
  46.815 +      {
  46.816 +        SDL_PrivateMouseButton(SDL_PRESSED,
  46.817 +                               SDL_BUTTON_MIDDLE,
  46.818 +                               0, 0); // Don't report mouse movement!
  46.819 +        
  46.820 +	if (bMouseCapturable)
  46.821 +	{
  46.822 +	  // We should capture the mouse!
  46.823 +	  if (!bMouseCaptured)
  46.824 +	  {
  46.825 +	    WinSetCapture(HWND_DESKTOP, hwnd);
  46.826 +            WinSetPointer(HWND_DESKTOP, NULL);
  46.827 +            bMouseCaptured = 1;
  46.828 +            {
  46.829 +              SWP swpClient;
  46.830 +              POINTL ptl;
  46.831 +              // Center the mouse to the middle of the window!
  46.832 +              WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
  46.833 +              ptl.x = 0; ptl.y = 0;
  46.834 +              WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
  46.835 +              pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */
  46.836 +              WinSetPointerPos(HWND_DESKTOP,
  46.837 +                               ptl.x + swpClient.cx/2,
  46.838 +                               ptl.y + swpClient.cy/2);
  46.839 +            }
  46.840 +	  }
  46.841 +	}
  46.842 +      }
  46.843 +      break;
  46.844 +    case WM_BUTTON3UP:
  46.845 +#ifdef DEBUG_BUILD
  46.846 +      printf("WM_BUTTON3UP\n"); fflush(stdout);
  46.847 +#endif
  46.848 +      SDL_PrivateMouseButton(SDL_RELEASED,
  46.849 +                             SDL_BUTTON_MIDDLE,
  46.850 +                             0, 0); // Don't report mouse movement!
  46.851 +      break;
  46.852 +    case WM_MOUSEMOVE:
  46.853 +#ifdef DEBUG_BUILD
  46.854 +//      printf("WM_MOUSEMOVE\n"); fflush(stdout);
  46.855 +#endif
  46.856 +
  46.857 +      pVideo = FSLib_GetUserParm(hwnd);
  46.858 +      if (pVideo)
  46.859 +      {
  46.860 +        if (pVideo->hidden->iSkipWMMOUSEMOVE)
  46.861 +        {
  46.862 +          pVideo->hidden->iSkipWMMOUSEMOVE--;
  46.863 +        } else
  46.864 +        {
  46.865 +          POINTS *ppts = (POINTS *) (&mp1);
  46.866 +          POINTL ptl;
  46.867 +
  46.868 +          CONVERTMOUSEPOSITION();
  46.869 +
  46.870 +          if (bMouseCaptured)
  46.871 +          {
  46.872 +            SWP swpClient;
  46.873 +            // Send relative mouse position, and re-center the mouse
  46.874 +            // Reposition the mouse to the center of the screen/window
  46.875 +            SDL_PrivateMouseMotion(0, // Buttons not changed
  46.876 +                                   1, // Relative position
  46.877 +                                   ppts->x - (pVideo->hidden->SrcBufferDesc.uiXResolution/2),
  46.878 +                                   ppts->y+1 - (pVideo->hidden->SrcBufferDesc.uiYResolution/2));
  46.879 +
  46.880 +            WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
  46.881 +            ptl.x = 0; ptl.y = 0;
  46.882 +            WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
  46.883 +            pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */
  46.884 +            // Center the mouse to the middle of the window!
  46.885 +            WinSetPointerPos(HWND_DESKTOP,
  46.886 +                             ptl.x + swpClient.cx/2,
  46.887 +                             ptl.y + swpClient.cy/2);
  46.888 +          } else
  46.889 +          {
  46.890 +            // Send absolute mouse position
  46.891 +            SDL_PrivateMouseMotion(0, // Buttons not changed
  46.892 +                                   0, // Absolute position
  46.893 +                                   ppts->x,
  46.894 +                                   ppts->y);
  46.895 +          }
  46.896 +        }
  46.897 +        if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
  46.898 +        {
  46.899 +#ifdef DEBUG_BUILD
  46.900 +//          printf("WM_MOUSEMOVE : ptr = %p\n", hptrGlobalPointer); fflush(stdout);
  46.901 +#endif
  46.902 +
  46.903 +          if (hptrGlobalPointer)
  46.904 +            WinSetPointer(HWND_DESKTOP, hptrGlobalPointer);
  46.905 +          else
  46.906 +            WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
  46.907 +        }
  46.908 +        else
  46.909 +        {
  46.910 +          WinSetPointer(HWND_DESKTOP, NULL);
  46.911 +        }
  46.912 +      }
  46.913 +#ifdef DEBUG_BUILD
  46.914 +//      printf("WM_MOUSEMOVE done\n"); fflush(stdout);
  46.915 +#endif
  46.916 +
  46.917 +      return (MRESULT) FALSE;
  46.918 +    case WM_CLOSE: // Window close
  46.919 +#ifdef DEBUG_BUILD
  46.920 +      printf("WM_CLOSE\n"); fflush(stdout);
  46.921 +#endif
  46.922 +
  46.923 +      pVideo = FSLib_GetUserParm(hwnd);
  46.924 +      if (pVideo)
  46.925 +      {
  46.926 +        // Send Quit message to the SDL application!
  46.927 +        SDL_PrivateQuit();
  46.928 +        return 0;
  46.929 +      }
  46.930 +      break;
  46.931 +
  46.932 +#ifdef BITBLT_IN_WINMESSAGEPROC
  46.933 +    case WM_UPDATERECTSREQUEST:
  46.934 +      pVideo = FSLib_GetUserParm(hwnd);
  46.935 +      if ((pVideo) && (pVideo->hidden->pSDLSurface))
  46.936 +      {
  46.937 +        if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
  46.938 +        {
  46.939 +          int numrects;
  46.940 +          SDL_Rect *rects;
  46.941 +          int i;
  46.942 +          SWP swp;
  46.943 +
  46.944 +          numrects = (int) mp1;
  46.945 +          rects = (SDL_Rect *) mp2;
  46.946 +
  46.947 +          WinQueryWindowPos(hwnd, &swp);
  46.948 +#ifndef RESIZE_EVEN_IF_RESIZABLE
  46.949 +          if ((!pVideo->hidden->pSDLSurface) ||
  46.950 +              (
  46.951 +               (pVideo->hidden->pSDLSurface) &&
  46.952 +               (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
  46.953 +               ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
  46.954 +                (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
  46.955 +               ) &&
  46.956 +               (!FSLib_QueryFSMode(hwnd))
  46.957 +              )
  46.958 +             )
  46.959 +          {
  46.960 +            // Resizable surface and in resizing!
  46.961 +            // So, don't blit now!
  46.962 +#ifdef DEBUG_BUILD
  46.963 +            printf("[WM_UPDATERECTSREQUEST] : Skipping blit while resizing!\n"); fflush(stdout);
  46.964 +#endif
  46.965 +          } else
  46.966 +#endif
  46.967 +          {
  46.968 +#ifdef DEBUG_BUILD
  46.969 +            printf("[WM_UPDATERECTSREQUEST] : Blitting!\n"); fflush(stdout);
  46.970 +#endif
  46.971 +          
  46.972 +            // Blit the changed areas
  46.973 +            for (i=0; i<numrects; i++)
  46.974 +              FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
  46.975 +                           rects[i].y, rects[i].x, rects[i].w, rects[i].h);
  46.976 +          }
  46.977 +          DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
  46.978 +        }
  46.979 +      }
  46.980 +      return 0;
  46.981 +#endif
  46.982 +
  46.983 +    default:
  46.984 +#ifdef DEBUG_BUILD
  46.985 +      printf("Unhandled: %x\n", msg); fflush(stdout);
  46.986 +#endif
  46.987 +
  46.988 +      break;
  46.989 +  }
  46.990 +  // Run the default window procedure for unhandled stuffs
  46.991 +  return WinDefWindowProc(hwnd, msg, mp1, mp2);
  46.992 +}
  46.993 +
  46.994 +/////////////////////////////////////////////////////////////////////
  46.995 +//
  46.996 +// PMThreadFunc
  46.997 +//
  46.998 +// This function implements the PM-Thread, which initializes the
  46.999 +// application window itself, the DIVE, and start message processing.
 46.1000 +//
 46.1001 +/////////////////////////////////////////////////////////////////////
 46.1002 +int iNumOfPMThreadInstances = 0; // Global!
 46.1003 +static void PMThreadFunc(void *pParm)
 46.1004 +{
 46.1005 +  SDL_VideoDevice *pVideo = pParm;
 46.1006 +  HAB hab;
 46.1007 +  HMQ hmq;
 46.1008 +  QMSG msg;
 46.1009 +  ULONG fcf;
 46.1010 +
 46.1011 +#ifdef DEBUG_BUILD
 46.1012 +  printf("[PMThreadFunc] : Starting\n"); fflush(stdout);
 46.1013 +#endif
 46.1014 +
 46.1015 +  iNumOfPMThreadInstances++;
 46.1016 +
 46.1017 +  // Initialize PM, create a message queue.
 46.1018 +
 46.1019 +  hab=WinInitialize(0);
 46.1020 +  hmq=WinCreateMsgQueue(hab,0);
 46.1021 +  if (hmq==0)
 46.1022 +  {
 46.1023 +#ifdef DEBUG_BUILD
 46.1024 +    printf("[PMThreadFunc] : Could not create message queue!\n");
 46.1025 +    printf("                 It might be that the application using SDL is not a PM app!\n");
 46.1026 +    fflush(stdout);
 46.1027 +#endif
 46.1028 +    pVideo->hidden->iPMThreadStatus = 2;
 46.1029 +  } else
 46.1030 +  {
 46.1031 +    int rc;
 46.1032 +    RECTL rectl;
 46.1033 +
 46.1034 +    fcf = ulFCFToUse; // Get from global setting
 46.1035 +
 46.1036 +#ifdef DEBUG_BUILD
 46.1037 +    printf("[PMThreadFunc] : FSLib_CreateWindow()!\n");
 46.1038 +    fflush(stdout);
 46.1039 +#endif
 46.1040 +
 46.1041 +    rc = FSLib_CreateWindow(HWND_DESKTOP, 0, &fcf,
 46.1042 +                            "SDL Application",
 46.1043 +                            NULLHANDLE, 0,
 46.1044 +                            &(pVideo->hidden->SrcBufferDesc),
 46.1045 +                            WndProc,
 46.1046 +                            &(pVideo->hidden->hwndClient),
 46.1047 +			    &(pVideo->hidden->hwndFrame));
 46.1048 +
 46.1049 +#ifdef DEBUG_BUILD
 46.1050 +    printf("[PMThreadFunc] : FSLib_CreateWindow() rc = %d\n", rc);
 46.1051 +    fflush(stdout);
 46.1052 +#endif
 46.1053 +
 46.1054 +    if (!rc)
 46.1055 +    {
 46.1056 +#ifdef DEBUG_BUILD
 46.1057 +      printf("[PMThreadFunc] : Could not create FSLib window!\n");
 46.1058 +      fflush(stdout);
 46.1059 +#endif
 46.1060 +      pVideo->hidden->iPMThreadStatus = 3;
 46.1061 +    } else
 46.1062 +    {
 46.1063 +#ifdef DEBUG_BUILD
 46.1064 +      printf("[PMThreadFunc] : FSLib_AddUserParm()!\n");
 46.1065 +      fflush(stdout);
 46.1066 +#endif
 46.1067 +
 46.1068 +      // Store pVideo pointer in window data for client window, so
 46.1069 +      // it will know the instance to which it belongs to.
 46.1070 +      FSLib_AddUserParm(pVideo->hidden->hwndClient, pVideo);
 46.1071 +
 46.1072 +      // Now set default image width height and fourcc!
 46.1073 +#ifdef DEBUG_BUILD
 46.1074 +      printf("[PMThreadFunc] : SetWindowPos()!\n");
 46.1075 +      fflush(stdout);
 46.1076 +#endif
 46.1077 +
 46.1078 +      // Set the position and size of the main window,
 46.1079 +      // and make it visible!
 46.1080 +      // Calculate frame window size from client window size
 46.1081 +      rectl.xLeft = 0;
 46.1082 +      rectl.yBottom = 0;
 46.1083 +      rectl.xRight = pVideo->hidden->SrcBufferDesc.uiXResolution; // Noninclusive
 46.1084 +      rectl.yTop = pVideo->hidden->SrcBufferDesc.uiYResolution; // Noninclusive
 46.1085 +      WinCalcFrameRect(pVideo->hidden->hwndFrame, &rectl, FALSE);
 46.1086 +
 46.1087 +      SetAccessableWindowPos(pVideo->hidden->hwndFrame,
 46.1088 +                             HWND_TOP,
 46.1089 +                             (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - (rectl.xRight-rectl.xLeft)) / 2,
 46.1090 +                             (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - (rectl.yTop-rectl.yBottom)) / 2,
 46.1091 +                             (rectl.xRight-rectl.xLeft),
 46.1092 +                             (rectl.yTop-rectl.yBottom),
 46.1093 +                             SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE);
 46.1094 +
 46.1095 +#ifdef DEBUG_BUILD
 46.1096 +      printf("[PMThreadFunc] : Entering message loop\n"); fflush(stdout);
 46.1097 +#endif
 46.1098 +      pVideo->hidden->iPMThreadStatus = 1;
 46.1099 +  
 46.1100 +      while (WinGetMsg(hab, (PQMSG)&msg, 0, 0, 0))
 46.1101 +        WinDispatchMsg(hab, (PQMSG) &msg);
 46.1102 +
 46.1103 +#ifdef DEBUG_BUILD
 46.1104 +      printf("[PMThreadFunc] : Leaving message loop\n"); fflush(stdout);
 46.1105 +#endif
 46.1106 +      // We should release the captured the mouse!
 46.1107 +      if (bMouseCaptured)
 46.1108 +      {
 46.1109 +        WinSetCapture(HWND_DESKTOP, NULLHANDLE);
 46.1110 +        bMouseCaptured = 0;
 46.1111 +      }
 46.1112 +      // Destroy our window
 46.1113 +      WinDestroyWindow(pVideo->hidden->hwndFrame); pVideo->hidden->hwndFrame=NULL;
 46.1114 +      // Show pointer to make sure it will not be left hidden.
 46.1115 +      WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
 46.1116 +      WinShowPointer(HWND_DESKTOP, TRUE);
 46.1117 +    }
 46.1118 +    // Uninitialize PM
 46.1119 +    WinDestroyMsgQueue(hmq);
 46.1120 +    // All done!
 46.1121 +    pVideo->hidden->iPMThreadStatus = 0;
 46.1122 +  }
 46.1123 +  WinTerminate(hab);
 46.1124 +  /* Commented out, should not be needed anymore, because we send it
 46.1125 +     from WM_CLOSE.
 46.1126 +  // Notify SDL that it should really die now...
 46.1127 +  SDL_PrivateQuit(); SDL_PrivateQuit(); SDL_PrivateQuit(); //... :))
 46.1128 +  */
 46.1129 +#ifdef DEBUG_BUILD
 46.1130 +  printf("[PMThreadFunc] : End, status is %d!\n", pVideo->hidden->iPMThreadStatus); fflush(stdout);
 46.1131 +#endif
 46.1132 +
 46.1133 +  iNumOfPMThreadInstances--;
 46.1134 +
 46.1135 +  // HACK to prevent zombie and hanging SDL applications, which does not take
 46.1136 +  // care of closing the window for some reason:
 46.1137 +  // There are some apps which do not process messages, so do a lot of things
 46.1138 +  // without noticing that the application should close. To close these,
 46.1139 +  // I've thought about the following:
 46.1140 +  // If the window is closed (the execution came here), I wait a bit to
 46.1141 +  // give time to the app to finish its execution. If it does not, I kill it
 46.1142 +  // using DosExit(). Brute force, but should work.
 46.1143 +  if (pVideo->hidden->iPMThreadStatus==0)
 46.1144 +  {
 46.1145 +    DosSleep(5000); // Wait 5 secs
 46.1146 +    // If a new PM thread has been spawned (reinitializing video mode), then all right.
 46.1147 +    // Otherwise, we have a problem, the app doesn't want to stop. Kill!
 46.1148 +    if (iNumOfPMThreadInstances==0)
 46.1149 +    {
 46.1150 +#ifdef DEBUG_BUILD
 46.1151 +      printf("[PMThreadFunc] : It seems that the application haven't terminated itself\n"); fflush(stdout);
 46.1152 +      printf("[PMThreadFunc] : in the last 5 seconds, so we go berserk.\n"); fflush(stdout);
 46.1153 +      printf("[PMThreadFunc] : Brute force mode. :) Killing process! Dieeeee...\n"); fflush(stdout);
 46.1154 +#endif
 46.1155 +      DosExit(EXIT_PROCESS, -1);
 46.1156 +    }
 46.1157 +  }
 46.1158 +  _endthread();
 46.1159 +}
 46.1160 +
 46.1161 +struct WMcursor
 46.1162 +{
 46.1163 +  HBITMAP hbm;
 46.1164 +  HPOINTER hptr;
 46.1165 +  char *pchData;
 46.1166 +};
 46.1167 +
 46.1168 +/* Free a window manager cursor */
 46.1169 +void os2fslib_FreeWMCursor(_THIS, WMcursor *cursor)
 46.1170 +{
 46.1171 +  if (cursor)
 46.1172 +  {
 46.1173 +    GpiDeleteBitmap(cursor->hbm);
 46.1174 +    WinDestroyPointer(cursor->hptr);
 46.1175 +    free(cursor->pchData);
 46.1176 +    free(cursor);
 46.1177 +  }
 46.1178 +}
 46.1179 +
 46.1180 +/* Local functions to convert the SDL cursor mask into OS/2 format */
 46.1181 +static void memnot(Uint8 *dst, Uint8 *src, int len)
 46.1182 +{
 46.1183 +  while ( len-- > 0 )
 46.1184 +    *dst++ = ~*src++;
 46.1185 +}
 46.1186 +static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
 46.1187 +{
 46.1188 +  while ( len-- > 0 )
 46.1189 +    *dst++ = (*src1++)^(*src2++);
 46.1190 +}
 46.1191 +
 46.1192 +/* Create a black/white window manager cursor */
 46.1193 +WMcursor *os2fslib_CreateWMCursor_Win(_THIS, Uint8 *data, Uint8 *mask,
 46.1194 +                                      int w, int h, int hot_x, int hot_y)
 46.1195 +{
 46.1196 +  HPOINTER hptr;
 46.1197 +  HBITMAP hbm;
 46.1198 +  BITMAPINFOHEADER bmih;
 46.1199 +  BMPINFO          bmi;
 46.1200 +  HPS              hps;
 46.1201 +  char *pchTemp;
 46.1202 +  char *xptr, *aptr;
 46.1203 +  int maxx, maxy;
 46.1204 +  int i, run, pad;
 46.1205 +  WMcursor *pResult;
 46.1206 +
 46.1207 +  maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXPOINTER);
 46.1208 +  maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER);
 46.1209 +
 46.1210 +  // Check for max size!
 46.1211 +  if ((w>maxx) || (h>maxy))
 46.1212 +    return (WMcursor *) NULL;
 46.1213 +
 46.1214 +  pResult = (WMcursor *) malloc(sizeof(WMcursor));
 46.1215 +  if (!pResult) return (WMcursor *) NULL;
 46.1216 +
 46.1217 +  pchTemp = (char *) malloc((maxx + 7)/8 * maxy*2);
 46.1218 +  if (!pchTemp)
 46.1219 +  {
 46.1220 +    free(pResult);
 46.1221 +    return (WMcursor *) NULL;
 46.1222 +  }
 46.1223 +
 46.1224 +  memset(pchTemp, 0, (maxx + 7)/8 * maxy*2);
 46.1225 +
 46.1226 +  hps = WinGetPS(_this->hidden->hwndClient);
 46.1227 +
 46.1228 +  bmi.cbFix = sizeof(BITMAPINFOHEADER);
 46.1229 +  bmi.cx = maxx;
 46.1230 +  bmi.cy = 2*maxy;
 46.1231 +  bmi.cPlanes = 1;
 46.1232 +  bmi.cBitCount = 1;
 46.1233 +  bmi.argbColor[0].bBlue = 0x00;
 46.1234 +  bmi.argbColor[0].bGreen = 0x00;
 46.1235 +  bmi.argbColor[0].bRed = 0x00;
 46.1236 +  bmi.argbColor[1].bBlue = 0x00;
 46.1237 +  bmi.argbColor[1].bGreen = 0x00;
 46.1238 +  bmi.argbColor[1].bRed = 0xff;
 46.1239 +
 46.1240 +  memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
 46.1241 +  bmih.cbFix = sizeof(BITMAPINFOHEADER);
 46.1242 +  bmih.cx = maxx;
 46.1243 +  bmih.cy = 2*maxy;
 46.1244 +  bmih.cPlanes = 1;
 46.1245 +  bmih.cBitCount = 1;
 46.1246 +
 46.1247 +  run = (w+7)/8;
 46.1248 +  pad = (maxx+7)/8 - run;
 46.1249 +
 46.1250 +  for (i=0; i<h; i++)
 46.1251 +  {
 46.1252 +    xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
 46.1253 +    aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
 46.1254 +    memxor(xptr, data, mask, run);
 46.1255 +    xptr += run;
 46.1256 +    data += run;
 46.1257 +    memnot(aptr, mask, run);
 46.1258 +    mask += run;
 46.1259 +    aptr += run;
 46.1260 +    memset(xptr,  0, pad);
 46.1261 +    xptr += pad;
 46.1262 +    memset(aptr, ~0, pad);
 46.1263 +    aptr += pad;
 46.1264 +  }
 46.1265 +  pad += run;
 46.1266 +  for (i=h ; i<maxy; i++ )
 46.1267 +  {
 46.1268 +    xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
 46.1269 +    aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
 46.1270 +
 46.1271 +    memset(xptr,  0, (maxx+7)/8);
 46.1272 +    xptr += (maxx+7)/8;
 46.1273 +    memset(aptr, ~0, (maxx+7)/8);
 46.1274 +    aptr += (maxx+7)/8;
 46.1275 +  }
 46.1276 +
 46.1277 +  hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
 46.1278 +  hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, hot_x, maxy - hot_y - 1);
 46.1279 +
 46.1280 +#ifdef DEBUG_BUILD
 46.1281 +  printf("HotSpot          : %d ; %d\n", hot_x, hot_y);
 46.1282 +  printf("HPS returned     : %x\n", (ULONG)hps);
 46.1283 +  printf("HBITMAP returned : %x\n", (ULONG)hbm);
 46.1284 +  printf("HPOINTER returned: %x\n", (ULONG)hptr);
 46.1285 +#endif
 46.1286 +
 46.1287 +  WinReleasePS(hps);
 46.1288 +
 46.1289 +#ifdef DEBUG_BUILD
 46.1290 +  printf("[CreateWMCursor] : ptr = %p\n", hptr); fflush(stdout);
 46.1291 +#endif
 46.1292 +
 46.1293 +  pResult->hptr = hptr;
 46.1294 +  pResult->hbm = hbm;
 46.1295 +  pResult->pchData = pchTemp;
 46.1296 +
 46.1297 +#ifdef DEBUG_BUILD
 46.1298 +  printf("[CreateWMCursor] : ptr = %p return.\n", hptr); fflush(stdout);
 46.1299 +#endif
 46.1300 +
 46.1301 +  return (WMcursor *) pResult;
 46.1302 +}
 46.1303 +
 46.1304 +WMcursor *os2fslib_CreateWMCursor_FS(_THIS, Uint8 *data, Uint8 *mask,
 46.1305 +                                     int w, int h, int hot_x, int hot_y)
 46.1306 +{
 46.1307 +#ifdef DEBUG_BUILD
 46.1308 +  printf("[CreateWMCursor_FS] : returning pointer NULL\n"); fflush(stdout);
 46.1309 +#endif
 46.1310 +
 46.1311 +  // In FS mode we'll use software cursor
 46.1312 +  return (WMcursor *) NULL;
 46.1313 +}
 46.1314 +
 46.1315 +/* Show the specified cursor, or hide if cursor is NULL */
 46.1316 +int os2fslib_ShowWMCursor(_THIS, WMcursor *cursor)
 46.1317 +{
 46.1318 +#ifdef DEBUG_BUILD
 46.1319 +  printf("[ShowWMCursor] : ptr = %p\n", cursor); fflush(stdout);
 46.1320 +#endif
 46.1321 +
 46.1322 +  if (cursor)
 46.1323 +  {
 46.1324 +    WinSetPointer(HWND_DESKTOP, cursor->hptr);
 46.1325 +    hptrGlobalPointer = cursor->hptr;
 46.1326 +    _this->hidden->iMouseVisible = 1;
 46.1327 +  }
 46.1328 +  else
 46.1329 +  {
 46.1330 +    WinSetPointer(HWND_DESKTOP, FALSE);
 46.1331 +    hptrGlobalPointer = NULL;
 46.1332 +    _this->hidden->iMouseVisible = 0;
 46.1333 +  }
 46.1334 +
 46.1335 +#ifdef DEBUG_BUILD
 46.1336 +  printf("[ShowWMCursor] : ptr = %p, DONE\n", cursor); fflush(stdout);
 46.1337 +#endif
 46.1338 +
 46.1339 +  return 1;
 46.1340 +}
 46.1341 +
 46.1342 +/* Warp the window manager cursor to (x,y)
 46.1343 + If NULL, a mouse motion event is posted internally.
 46.1344 + */
 46.1345 +void os2fslib_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
 46.1346 +{
 46.1347 +  LONG lx, ly;
 46.1348 +  SWP swpClient;
 46.1349 +  POINTL ptlPoints;
 46.1350 +  WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
 46.1351 +  ptlPoints.x = swpClient.x;
 46.1352 +  ptlPoints.y = swpClient.y;
 46.1353 +  WinMapWindowPoints(_this->hidden->hwndFrame, HWND_DESKTOP, &ptlPoints, 1);
 46.1354 +  lx = ptlPoints.x + (x*swpClient.cx) / _this->hidden->SrcBufferDesc.uiXResolution;
 46.1355 +  ly = ptlPoints.y + swpClient.cy - ((y*swpClient.cy) / _this->hidden->SrcBufferDesc.uiYResolution) - 1;
 46.1356 +
 46.1357 +  SDL_PrivateMouseMotion(0, // Buttons not changed
 46.1358 +                         0, // Absolute position
 46.1359 +                         x,
 46.1360 +                         y);
 46.1361 +
 46.1362 +  WinSetPointerPos(HWND_DESKTOP, lx, ly);
 46.1363 +
 46.1364 +}
 46.1365 +
 46.1366 +/* If not NULL, this is called when a mouse motion event occurs */
 46.1367 +void os2fslib_MoveWMCursor(_THIS, int x, int y)
 46.1368 +{
 46.1369 +  /*
 46.1370 +  SDL_Rect rect;
 46.1371 +
 46.1372 +#ifdef DEBUG_BUILD
 46.1373 +  printf("[MoveWMCursor] : at %d ; %d\n", x, y); fflush(stdout);
 46.1374 +#endif
 46.1375 +
 46.1376 +  rect.x = x;
 46.1377 +  rect.y = y;
 46.1378 +  rect.w = 32;
 46.1379 +  rect.h = 32;
 46.1380 +  os2fslib_UpdateRects(_this, 1, &rect);
 46.1381 +  // TODO!
 46.1382 +  */
 46.1383 +}
 46.1384 +
 46.1385 +/* Determine whether the mouse should be in relative mode or not.
 46.1386 + This function is called when the input grab state or cursor
 46.1387 + visibility state changes.
 46.1388 + If the cursor is not visible, and the input is grabbed, the
 46.1389 + driver can place the mouse in relative mode, which may result
 46.1390 + in higher accuracy sampling of the pointer motion.
 46.1391 + */
 46.1392 +void os2fslib_CheckMouseMode(_THIS)
 46.1393 +{
 46.1394 +}
 46.1395 +
 46.1396 +static void os2fslib_PumpEvents(_THIS)
 46.1397 +{
 46.1398 +  // Notify SDL that if window has been resized!
 46.1399 +  if (
 46.1400 +      (_this->hidden->pSDLSurface) &&
 46.1401 +      (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
 46.1402 +      (
 46.1403 +       (_this->hidden->SrcBufferDesc.uiXResolution!=iWindowSizeX) ||
 46.1404 +       (_this->hidden->SrcBufferDesc.uiYResolution!=iWindowSizeY)
 46.1405 +      ) &&
 46.1406 +      (iWindowSizeX>0) &&
 46.1407 +      (iWindowSizeY>0)
 46.1408 +     )
 46.1409 +  {
 46.1410 +    static time_t prev_time;
 46.1411 +    time_t curr_time;
 46.1412 +
 46.1413 +    curr_time = time(NULL);
 46.1414 +    if ((difftime(curr_time, prev_time)>=0.25) ||
 46.1415 +        (bWindowResized))
 46.1416 +    {
 46.1417 +      // Make sure we won't flood the event queue with resize events,
 46.1418 +      // only send them at 250 msecs!
 46.1419 +      // (or when the window is resized)
 46.1420 +#ifdef DEBUG_BUILD
 46.1421 +      printf("[os2fslib_PumpEvents] : Calling PrivateResize (%d %d).\n",
 46.1422 +             iWindowSizeX, iWindowSizeY);
 46.1423 +      fflush(stdout);
 46.1424 +#endif
 46.1425 +      // Tell SDL the new size
 46.1426 +      SDL_PrivateResize(iWindowSizeX, iWindowSizeY);
 46.1427 +      prev_time = curr_time;
 46.1428 +      bWindowResized = 0;
 46.1429 +    }
 46.1430 +  }
 46.1431 +}
 46.1432 +
 46.1433 +/* We don't actually allow hardware surfaces other than the main one */
 46.1434 +static int os2fslib_AllocHWSurface(_THIS, SDL_Surface *surface)
 46.1435 +{
 46.1436 +  return(-1);
 46.1437 +}
 46.1438 +static void os2fslib_FreeHWSurface(_THIS, SDL_Surface *surface)
 46.1439 +{
 46.1440 +  return;
 46.1441 +}
 46.1442 +
 46.1443 +/* We need to wait for vertical retrace on page flipped displays */
 46.1444 +static int os2fslib_LockHWSurface(_THIS, SDL_Surface *surface)
 46.1445 +{
 46.1446 +  return(0);
 46.1447 +}
 46.1448 +
 46.1449 +static void os2fslib_UnlockHWSurface(_THIS, SDL_Surface *surface)
 46.1450 +{
 46.1451 +  return;
 46.1452 +}
 46.1453 +
 46.1454 +static int os2fslib_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
 46.1455 +{
 46.1456 +  printf("[os2fslib_SetColors] : TODO!\n"); fflush(stdout);
 46.1457 +  // TODO: Implement paletted modes
 46.1458 +  return(1);
 46.1459 +}
 46.1460 +
 46.1461 +static void os2fslib_DestroyIcon(HWND hwndFrame)
 46.1462 +{
 46.1463 +  if (hptrCurrentIcon)
 46.1464 +  {
 46.1465 +    WinDestroyPointer(hptrCurrentIcon);
 46.1466 +    hptrCurrentIcon = NULL;
 46.1467 +
 46.1468 +    WinSendMsg(hwndFrame,
 46.1469 +               WM_SETICON,
 46.1470 +               NULL,
 46.1471 +               NULL);
 46.1472 +  }
 46.1473 +
 46.1474 +}
 46.1475 +
 46.1476 +/* Set the window icon image */
 46.1477 +void os2fslib_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
 46.1478 +{
 46.1479 +  HWND hwndFrame;
 46.1480 +  SDL_Surface *icon_rgb;
 46.1481 +  HPOINTER hptrIcon;
 46.1482 +  HBITMAP hbm;
 46.1483 +  BITMAPINFOHEADER bmih;
 46.1484 +  BMPINFO          bmi;
 46.1485 +  HPS              hps;
 46.1486 +  char *pchTemp;
 46.1487 +  char *pptr, *mptr, *dptr, *dmptr;
 46.1488 +  int maxx, maxy, w, h, x, y;
 46.1489 +  SDL_Rect bounds;
 46.1490 +
 46.1491 +#ifdef DEBUG_BUILD
 46.1492 +  printf("[os2fslib_SetIcon] : Creating and setting new icon\n"); fflush(stdout);
 46.1493 +#endif
 46.1494 +
 46.1495 +  hwndFrame = WinQueryWindow(_this->hidden->hwndClient, QW_PARENT);
 46.1496 +
 46.1497 +  // Make sure the old icon resource will be free'd!
 46.1498 +  os2fslib_DestroyIcon(hwndFrame);
 46.1499 +
 46.1500 +  if ((!icon) || (!mask))
 46.1501 +    return;
 46.1502 +
 46.1503 +  w = icon->w;
 46.1504 +  h = icon->h;
 46.1505 +
 46.1506 +  maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
 46.1507 +  maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
 46.1508 +
 46.1509 +  // Check for max size!
 46.1510 +  if ((w>maxx) || (h>maxy))
 46.1511 +    return;
 46.1512 +
 46.1513 +  pchTemp = (char *) malloc(w * h*2 * 4);
 46.1514 +  if (!pchTemp)
 46.1515 +    return;
 46.1516 +
 46.1517 +  memset(pchTemp, 0, w * h*2 * 4);
 46.1518 +
 46.1519 +  // Convert surface to RGB, if it's not RGB yet!
 46.1520 +  icon_rgb = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
 46.1521 +                                  32, 0, 0, 0, 0);
 46.1522 +  if ( icon_rgb == NULL )
 46.1523 +  {
 46.1524 +    free(pchTemp);
 46.1525 +    return;
 46.1526 +  }
 46.1527 +  bounds.x = 0;
 46.1528 +  bounds.y = 0;
 46.1529 +  bounds.w = icon->w;
 46.1530 +  bounds.h = icon->h;
 46.1531 +  if ( SDL_LowerBlit(icon, &bounds, icon_rgb, &bounds) < 0 )
 46.1532 +  {
 46.1533 +    SDL_FreeSurface(icon_rgb);
 46.1534 +    free(pchTemp);
 46.1535 +    return;
 46.1536 +  }
 46.1537 +
 46.1538 +  /* Copy pixels upside-down from RGB surface into BMP, masked with the icon mask */
 46.1539 +
 46.1540 +  // Pixels
 46.1541 +  pptr = (char *) (icon_rgb->pixels);
 46.1542 +  // Mask
 46.1543 +  mptr = mask;
 46.1544 +
 46.1545 +  for (y=0; y<h; y++)
 46.1546 +  {
 46.1547 +    unsigned char uchMaskByte;
 46.1548 +
 46.1549 +    // Destination
 46.1550 +    dptr = pchTemp + w*4 * (h-y-1);
 46.1551 +    // Destination mask
 46.1552 +    dmptr = pchTemp + w*h*4 + w*4 * (h-y-1);
 46.1553 +
 46.1554 +    for (x=0; x<w; x++)
 46.1555 +    {
 46.1556 +      if (x%8==0)
 46.1557 +      {
 46.1558 +        uchMaskByte = (unsigned char) (*mptr);
 46.1559 +        mptr++;
 46.1560 +      } else
 46.1561 +        uchMaskByte <<= 1;
 46.1562 +
 46.1563 +      if (uchMaskByte & 0x80)
 46.1564 +      {
 46.1565 +        // Copy RGB
 46.1566 +        *dptr++ = *pptr++;
 46.1567 +        *dptr++ = *pptr++;
 46.1568 +        *dptr++ = *pptr++;
 46.1569 +        *dptr++ = *pptr++;
 46.1570 +
 46.1571 +        *dmptr++ = 0;
 46.1572 +        *dmptr++ = 0;
 46.1573 +        *dmptr++ = 0;
 46.1574 +        *dmptr++ = 0;
 46.1575 +      } else
 46.1576 +      {
 46.1577 +        // Set pixels to fully transparent
 46.1578 +        *dptr++ = 0; pptr++;
 46.1579 +        *dptr++ = 0; pptr++;
 46.1580 +        *dptr++ = 0; pptr++;
 46.1581 +        *dptr++ = 0; pptr++;
 46.1582 +
 46.1583 +        *dmptr++ = 255;
 46.1584 +        *dmptr++ = 255;
 46.1585 +        *dmptr++ = 255;
 46.1586 +        *dmptr++ = 255;
 46.1587 +      }
 46.1588 +    }
 46.1589 +  }
 46.1590 +
 46.1591 +  // There is no more need for the RGB surface
 46.1592 +  SDL_FreeSurface(icon_rgb);
 46.1593 +
 46.1594 +  hps = WinGetPS(_this->hidden->hwndClient);
 46.1595 +
 46.1596 +  bmi.cbFix = sizeof(BITMAPINFOHEADER);
 46.1597 +  bmi.cx = w;
 46.1598 +  bmi.cy = 2*h;
 46.1599 +  bmi.cPlanes = 1;
 46.1600 +  bmi.cBitCount = 32;
 46.1601 +
 46.1602 +  memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
 46.1603 +  bmih.cbFix = sizeof(BITMAPINFOHEADER);
 46.1604 +  bmih.cx = w;
 46.1605 +  bmih.cy = 2*h;
 46.1606 +  bmih.cPlanes = 1;
 46.1607 +  bmih.cBitCount = 32;
 46.1608 +
 46.1609 +  hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
 46.1610 +  hptrIcon = WinCreatePointer(HWND_DESKTOP, hbm, FALSE, 0, 0);
 46.1611 +
 46.1612 +  WinReleasePS(hps);
 46.1613 +
 46.1614 +  // Free pixel array
 46.1615 +  free(pchTemp);
 46.1616 +
 46.1617 +  // Change icon in frame window
 46.1618 +  WinSendMsg(hwndFrame,
 46.1619 +             WM_SETICON,
 46.1620 +             (MPARAM) hptrIcon,
 46.1621 +             NULL);
 46.1622 +
 46.1623 +  /*
 46.1624 +  // Change icon in switchlist
 46.1625 +  // Seems like it's not needed, the WM_SETICON already does it.
 46.1626 +  {
 46.1627 +    PID pidFrame;
 46.1628 +    HSWITCH hswitchFrame;
 46.1629 +    SWCNTRL swctl;
 46.1630 +
 46.1631 +    WinQueryWindowProcess(hwndFrame, &pidFrame, NULL);
 46.1632 +    hswitchFrame = WinQuerySwitchHandle(hwndFrame, pidFrame);
 46.1633 +    WinQuerySwitchEntry(hswitchFrame, &swctl);
 46.1634 +
 46.1635 +    swctl.hwndIcon = hptrIcon;
 46.1636 +
 46.1637 +    WinChangeSwitchEntry(hswitchFrame, &swctl);
 46.1638 +  }
 46.1639 +  */
 46.1640 +
 46.1641 +  // Store icon handle in global variable
 46.1642 +  hptrCurrentIcon = hptrIcon;
 46.1643 +}
 46.1644 +
 46.1645 +// ------------------------ REAL FUNCTIONS -----------------
 46.1646 +
 46.1647 +
 46.1648 +static void os2fslib_SetCursorManagementFunctions(_THIS, int iForWindowedMode)
 46.1649 +{
 46.1650 +  if (iForWindowedMode)
 46.1651 +  {
 46.1652 +    _this->FreeWMCursor = os2fslib_FreeWMCursor;
 46.1653 +    _this->CreateWMCursor = os2fslib_CreateWMCursor_Win;
 46.1654 +    _this->ShowWMCursor = os2fslib_ShowWMCursor;
 46.1655 +    _this->WarpWMCursor = os2fslib_WarpWMCursor;
 46.1656 +    _this->MoveWMCursor = os2fslib_MoveWMCursor;
 46.1657 +    _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
 46.1658 +  } else
 46.1659 +  {
 46.1660 +    // We'll have software mouse cursor in FS mode!
 46.1661 +    _this->FreeWMCursor = os2fslib_FreeWMCursor;
 46.1662 +    _this->CreateWMCursor = os2fslib_CreateWMCursor_FS;
 46.1663 +    _this->ShowWMCursor = os2fslib_ShowWMCursor;
 46.1664 +    _this->WarpWMCursor = os2fslib_WarpWMCursor;
 46.1665 +    _this->MoveWMCursor = os2fslib_MoveWMCursor;
 46.1666 +    _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
 46.1667 +  }
 46.1668 +}
 46.1669 +
 46.1670 +static void os2fslib_InitOSKeymap(_THIS)
 46.1671 +{
 46.1672 +  int i;
 46.1673 +
 46.1674 +  iShiftIsPressed = 0;
 46.1675 +
 46.1676 +  /* Map the VK and CH keysyms */
 46.1677 +  for ( i=0; i<=255; ++i )
 46.1678 +    HWScanKeyMap[i] = SDLK_UNKNOWN;
 46.1679 +
 46.1680 +  // First line of keyboard:
 46.1681 +  HWScanKeyMap[0x1] = SDLK_ESCAPE;
 46.1682 +  HWScanKeyMap[0x3b] = SDLK_F1;
 46.1683 +  HWScanKeyMap[0x3c] = SDLK_F2;
 46.1684 +  HWScanKeyMap[0x3d] = SDLK_F3;
 46.1685 +  HWScanKeyMap[0x3e] = SDLK_F4;
 46.1686 +  HWScanKeyMap[0x3f] = SDLK_F5;
 46.1687 +  HWScanKeyMap[0x40] = SDLK_F6;
 46.1688 +  HWScanKeyMap[0x41] = SDLK_F7;
 46.1689 +  HWScanKeyMap[0x42] = SDLK_F8;
 46.1690 +  HWScanKeyMap[0x43] = SDLK_F9;
 46.1691 +  HWScanKeyMap[0x44] = SDLK_F10;
 46.1692 +  HWScanKeyMap[0x57] = SDLK_F11;
 46.1693 +  HWScanKeyMap[0x58] = SDLK_F12;
 46.1694 +  HWScanKeyMap[0x5d] = SDLK_PRINT;
 46.1695 +  HWScanKeyMap[0x46] = SDLK_SCROLLOCK;
 46.1696 +  HWScanKeyMap[0x5f] = SDLK_PAUSE;
 46.1697 +
 46.1698 +  // Second line of keyboard:
 46.1699 +  HWScanKeyMap[0x29] = SDLK_BACKQUOTE;
 46.1700 +  HWScanKeyMap[0x2] = SDLK_1;
 46.1701 +  HWScanKeyMap[0x3] = SDLK_2;
 46.1702 +  HWScanKeyMap[0x4] = SDLK_3;
 46.1703 +  HWScanKeyMap[0x5] = SDLK_4;
 46.1704 +  HWScanKeyMap[0x6] = SDLK_5;
 46.1705 +  HWScanKeyMap[0x7] = SDLK_6;
 46.1706 +  HWScanKeyMap[0x8] = SDLK_7;
 46.1707 +  HWScanKeyMap[0x9] = SDLK_8;
 46.1708 +  HWScanKeyMap[0xa] = SDLK_9;
 46.1709 +  HWScanKeyMap[0xb] = SDLK_0;
 46.1710 +  HWScanKeyMap[0xc] = SDLK_MINUS;
 46.1711 +  HWScanKeyMap[0xd] = SDLK_EQUALS;
 46.1712 +  HWScanKeyMap[0xe] = SDLK_BACKSPACE;
 46.1713 +  HWScanKeyMap[0x68] = SDLK_INSERT;
 46.1714 +  HWScanKeyMap[0x60] = SDLK_HOME;
 46.1715 +  HWScanKeyMap[0x62] = SDLK_PAGEUP;
 46.1716 +  HWScanKeyMap[0x45] = SDLK_NUMLOCK;
 46.1717 +  HWScanKeyMap[0x5c] = SDLK_KP_DIVIDE;
 46.1718 +  HWScanKeyMap[0x37] = SDLK_KP_MULTIPLY;
 46.1719 +  HWScanKeyMap[0x4a] = SDLK_KP_MINUS;
 46.1720 +
 46.1721 +  // Third line of keyboard:
 46.1722 +  HWScanKeyMap[0xf] = SDLK_TAB;
 46.1723 +  HWScanKeyMap[0x10] = SDLK_q;
 46.1724 +  HWScanKeyMap[0x11] = SDLK_w;
 46.1725 +  HWScanKeyMap[0x12] = SDLK_e;
 46.1726 +  HWScanKeyMap[0x13] = SDLK_r;
 46.1727 +  HWScanKeyMap[0x14] = SDLK_t;
 46.1728 +  HWScanKeyMap[0x15] = SDLK_y;
 46.1729 +  HWScanKeyMap[0x16] = SDLK_u;
 46.1730 +  HWScanKeyMap[0x17] = SDLK_i;
 46.1731 +  HWScanKeyMap[0x18] = SDLK_o;
 46.1732 +  HWScanKeyMap[0x19] = SDLK_p;
 46.1733 +  HWScanKeyMap[0x1a] = SDLK_LEFTBRACKET;
 46.1734 +  HWScanKeyMap[0x1b] = SDLK_RIGHTBRACKET;
 46.1735 +  HWScanKeyMap[0x1c] = SDLK_RETURN;
 46.1736 +  HWScanKeyMap[0x69] = SDLK_DELETE;
 46.1737 +  HWScanKeyMap[0x65] = SDLK_END;
 46.1738 +  HWScanKeyMap[0x67] = SDLK_PAGEDOWN;
 46.1739 +  HWScanKeyMap[0x47] = SDLK_KP7;
 46.1740 +  HWScanKeyMap[0x48] = SDLK_KP8;
 46.1741 +  HWScanKeyMap[0x49] = SDLK_KP9;
 46.1742 +  HWScanKeyMap[0x4e] = SDLK_KP_PLUS;
 46.1743 +
 46.1744 +  // Fourth line of keyboard:
 46.1745 +  HWScanKeyMap[0x3a] = SDLK_CAPSLOCK;
 46.1746 +  HWScanKeyMap[0x1e] = SDLK_a;
 46.1747 +  HWScanKeyMap[0x1f] = SDLK_s;
 46.1748 +  HWScanKeyMap[0x20] = SDLK_d;
 46.1749 +  HWScanKeyMap[0x21] = SDLK_f;
 46.1750 +  HWScanKeyMap[0x22] = SDLK_g;
 46.1751 +  HWScanKeyMap[0x23] = SDLK_h;
 46.1752 +  HWScanKeyMap[0x24] = SDLK_j;
 46.1753 +  HWScanKeyMap[0x25] = SDLK_k;
 46.1754 +  HWScanKeyMap[0x26] = SDLK_l;
 46.1755 +  HWScanKeyMap[0x27] = SDLK_SEMICOLON;
 46.1756 +  HWScanKeyMap[0x28] = SDLK_QUOTE;
 46.1757 +  HWScanKeyMap[0x2b] = SDLK_BACKSLASH;
 46.1758 +  HWScanKeyMap[0x4b] = SDLK_KP4;
 46.1759 +  HWScanKeyMap[0x4c] = SDLK_KP5;
 46.1760 +  HWScanKeyMap[0x4d] = SDLK_KP6;
 46.1761 +
 46.1762 +  // Fifth line of keyboard:
 46.1763 +  HWScanKeyMap[0x2a] = SDLK_LSHIFT;
 46.1764 +  HWScanKeyMap[0x56] = SDLK_WORLD_1; // Code 161, letter i' on hungarian keyboard
 46.1765 +  HWScanKeyMap[0x2c] = SDLK_z;
 46.1766 +  HWScanKeyMap[0x2d] = SDLK_x;
 46.1767 +  HWScanKeyMap[0x2e] = SDLK_c;
 46.1768 +  HWScanKeyMap[0x2f] = SDLK_v;
 46.1769 +  HWScanKeyMap[0x30] = SDLK_b;
 46.1770 +  HWScanKeyMap[0x31] = SDLK_n;
 46.1771 +  HWScanKeyMap[0x32] = SDLK_m;
 46.1772 +  HWScanKeyMap[0x33] = SDLK_COMMA;
 46.1773 +  HWScanKeyMap[0x34] = SDLK_PERIOD;
 46.1774 +  HWScanKeyMap[0x35] = SDLK_SLASH;
 46.1775 +  HWScanKeyMap[0x36] = SDLK_RSHIFT;
 46.1776 +  HWScanKeyMap[0x61] = SDLK_UP;
 46.1777 +  HWScanKeyMap[0x4f] = SDLK_KP1;
 46.1778 +  HWScanKeyMap[0x50] = SDLK_KP2;
 46.1779 +  HWScanKeyMap[0x51] = SDLK_KP3;
 46.1780 +  HWScanKeyMap[0x5a] = SDLK_KP_ENTER;
 46.1781 +
 46.1782 +  // Sixth line of keyboard:
 46.1783 +  HWScanKeyMap[0x1d] = SDLK_LCTRL;
 46.1784 +  HWScanKeyMap[0x7e] = SDLK_LSUPER; // Windows key
 46.1785 +  HWScanKeyMap[0x38] = SDLK_LALT;
 46.1786 +  HWScanKeyMap[0x39] = SDLK_SPACE;
 46.1787 +  HWScanKeyMap[0x5e] = SDLK_RALT;// Actually, altgr on my keyboard...
 46.1788 +  HWScanKeyMap[0x7f] = SDLK_RSUPER;
 46.1789 +  HWScanKeyMap[0x7c] = SDLK_MENU;
 46.1790 +  HWScanKeyMap[0x5b] = SDLK_RCTRL;
 46.1791 +  HWScanKeyMap[0x63] = SDLK_LEFT;
 46.1792 +  HWScanKeyMap[0x66] = SDLK_DOWN;
 46.1793 +  HWScanKeyMap[0x64] = SDLK_RIGHT;
 46.1794 +  HWScanKeyMap[0x52] = SDLK_KP0;
 46.1795 +  HWScanKeyMap[0x53] = SDLK_KP_PERIOD;
 46.1796 +}
 46.1797 +
 46.1798 +
 46.1799 +/* Iconify the window.
 46.1800 + This function returns 1 if there is a window manager and the
 46.1801 + window was actually iconified, it returns 0 otherwise.
 46.1802 + */
 46.1803 +int os2fslib_IconifyWindow(_THIS)
 46.1804 +{
 46.1805 +  HAB hab;
 46.1806 +  HMQ hmq;
 46.1807 +  ERRORID hmqerror;
 46.1808 +
 46.1809 +  // If there is no more window, nothing we can do!
 46.1810 +  if (_this->hidden->iPMThreadStatus!=1) return 0;
 46.1811 +
 46.1812 +  // Cannot do anything in fullscreen mode!
 46.1813 +  if (FSLib_QueryFSMode(_this->hidden->hwndClient))
 46.1814 +    return 0;
 46.1815 +
 46.1816 +  // Make sure this thread is prepared for using the Presentation Manager!
 46.1817 +  hab = WinInitialize(0);
 46.1818 +  hmq = WinCreateMsgQueue(hab,0);
 46.1819 +  // Remember if there was an error at WinCreateMsgQueue(), because we don't
 46.1820 +  // want to destroy somebody else's queue later. :)
 46.1821 +  hmqerror = WinGetLastError(hab);
 46.1822 +
 46.1823 +  WinSetWindowPos(_this->hidden->hwndFrame, HWND_TOP,
 46.1824 +		 0, 0, 0, 0, SWP_MINIMIZE);
 46.1825 +
 46.1826 +  // Now destroy the message queue, if we've created it!
 46.1827 +  if (ERRORIDERROR(hmqerror)==0)
 46.1828 +    WinDestroyMsgQueue(hmq);
 46.1829 +
 46.1830 +  return 1;
 46.1831 +}
 46.1832 +
 46.1833 +static SDL_GrabMode os2fslib_GrabInput(_THIS, SDL_GrabMode mode)
 46.1834 +{
 46.1835 +  HAB hab;
 46.1836 +  HMQ hmq;
 46.1837 +  ERRORID hmqerror;
 46.1838 +
 46.1839 +
 46.1840 +  // If there is no more window, nothing we can do!
 46.1841 +  if (_this->hidden->iPMThreadStatus!=1)
 46.1842 +    return SDL_GRAB_OFF;
 46.1843 +
 46.1844 +  // Make sure this thread is prepared for using the Presentation Manager!
 46.1845 +  hab = WinInitialize(0);
 46.1846 +  hmq = WinCreateMsgQueue(hab,0);
 46.1847 +  // Remember if there was an error at WinCreateMsgQueue(), because we don't
 46.1848 +  // want to destroy somebody else's queue later. :)
 46.1849 +  hmqerror = WinGetLastError(hab);
 46.1850 +
 46.1851 +
 46.1852 +  if (mode == SDL_GRAB_OFF)
 46.1853 +  {
 46.1854 +#ifdef DEBUG_BUILD
 46.1855 +    printf("[os2fslib_GrabInput] : Releasing mouse\n"); fflush(stdout);
 46.1856 +#endif
 46.1857 +
 46.1858 +    // Release the mouse
 46.1859 +    bMouseCapturable = 0;
 46.1860 +    if (bMouseCaptured)
 46.1861 +    {
 46.1862 +      WinSetCapture(HWND_DESKTOP, NULLHANDLE);
 46.1863 +      bMouseCaptured = 0;
 46.1864 +    }
 46.1865 +  } else
 46.1866 +  {
 46.1867 +#ifdef DEBUG_BUILD
 46.1868 +    printf("[os2fslib_GrabInput] : Capturing mouse\n"); fflush(stdout);
 46.1869 +#endif
 46.1870 +
 46.1871 +    // Capture the mouse
 46.1872 +    bMouseCapturable = 1;
 46.1873 +    if (WinQueryFocus(HWND_DESKTOP) == _this->hidden->hwndClient)
 46.1874 +    {
 46.1875 +      WinSetCapture(HWND_DESKTOP, _this->hidden->hwndClient);
 46.1876 +      bMouseCaptured = 1;
 46.1877 +      {
 46.1878 +        SWP swpClient;
 46.1879 +        POINTL ptl;
 46.1880 +        // Center the mouse to the middle of the window!
 46.1881 +        WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
 46.1882 +        ptl.x = 0; ptl.y = 0;
 46.1883 +        WinMapWindowPoints(_this->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
 46.1884 +        _this->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account!  */
 46.1885 +        WinSetPointerPos(HWND_DESKTOP,
 46.1886 +                         ptl.x + swpClient.cx/2,
 46.1887 +                         ptl.y + swpClient.cy/2);
 46.1888 +      }
 46.1889 +    }
 46.1890 +  }
 46.1891 +
 46.1892 +  // Now destroy the message queue, if we've created it!
 46.1893 +  if (ERRORIDERROR(hmqerror)==0)
 46.1894 +    WinDestroyMsgQueue(hmq);
 46.1895 +
 46.1896 +  return mode;
 46.1897 +}
 46.1898 +
 46.1899 +/* Set the title and icon text */
 46.1900 +static void os2fslib_SetCaption(_THIS, const char *title, const char *icon)
 46.1901 +{
 46.1902 +  HAB hab;
 46.1903 +  HMQ hmq;
 46.1904 +  ERRORID hmqerror;
 46.1905 +
 46.1906 +  // If there is no more window, nothing we can do!
 46.1907 +  if (_this->hidden->iPMThreadStatus!=1) return;
 46.1908 +
 46.1909 +  // Make sure this thread is prepared for using the Presentation Manager!
 46.1910 +  hab = WinInitialize(0);
 46.1911 +  hmq = WinCreateMsgQueue(hab,0);
 46.1912 +  // Remember if there was an error at WinCreateMsgQueue(), because we don't
 46.1913 +  // want to destroy somebody else's queue later. :)
 46.1914 +  hmqerror = WinGetLastError(hab);
 46.1915 +
 46.1916 +  WinSetWindowText(_this->hidden->hwndFrame, (char *) title);
 46.1917 +
 46.1918 +  // Now destroy the message queue, if we've created it!
 46.1919 +  if (ERRORIDERROR(hmqerror)==0)
 46.1920 +    WinDestroyMsgQueue(hmq);
 46.1921 +}
 46.1922 +
 46.1923 +static int os2fslib_ToggleFullScreen(_THIS, int on)
 46.1924 +{
 46.1925 +#ifdef DEBUG_BUILD
 46.1926 +  printf("[os2fslib_ToggleFullScreen] : %d\n", on); fflush(stdout);
 46.1927 +#endif
 46.1928 +  // If there is no more window, nothing we can do!
 46.1929 +  if (_this->hidden->iPMThreadStatus!=1) return 0;
 46.1930 +
 46.1931 +  FSLib_ToggleFSMode(_this->hidden->hwndClient, on);
 46.1932 +  /* Cursor manager functions to Windowed/FS mode*/
 46.1933 +  os2fslib_SetCursorManagementFunctions(_this, !on);
 46.1934 +  return 1;
 46.1935 +}
 46.1936 +
 46.1937 +/* This is called after the video mode has been set, to get the
 46.1938 + initial mouse state.  It should queue events as necessary to
 46.1939 + properly represent the current mouse focus and position.
 46.1940 + */
 46.1941 +static void os2fslib_UpdateMouse(_THIS)
 46.1942 +{
 46.1943 +  POINTL ptl;
 46.1944 +  HAB hab;
 46.1945 +  HMQ hmq;
 46.1946 +  ERRORID hmqerror;
 46.1947 +  SWP swpClient;
 46.1948 +
 46.1949 +  // If there is no more window, nothing we can do!
 46.1950 +  if (_this->hidden->iPMThreadStatus!=1) return;
 46.1951 +
 46.1952 +
 46.1953 +  // Make sure this thread is prepared for using the Presentation Manager!
 46.1954 +  hab = WinInitialize(0);
 46.1955 +  hmq = WinCreateMsgQueue(hab,0);
 46.1956 +  // Remember if there was an error at WinCreateMsgQueue(), because we don't
 46.1957 +  // want to destroy somebody else's queue later. :)
 46.1958 +  hmqerror = WinGetLastError(hab);
 46.1959 +
 46.1960 +  
 46.1961 +
 46.1962 +  if (_this->hidden->fInFocus)
 46.1963 +  {
 46.1964 +    // If our app is in focus
 46.1965 +    SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
 46.1966 +    SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
 46.1967 +    SDL_PrivateAppActive(1, SDL_APPACTIVE);
 46.1968 +    WinQueryPointerPos(HWND_DESKTOP, &ptl);
 46.1969 +    WinMapWindowPoints(HWND_DESKTOP, _this->hidden->hwndClient, &ptl, 1);
 46.1970 +    WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
 46.1971 +    // Convert OS/2 mouse position to SDL position, and also scale it!
 46.1972 +    ptl.x = ptl.x * _this->hidden->SrcBufferDesc.uiXResolution / swpClient.cx;
 46.1973 +    ptl.y = ptl.y * _this->hidden->SrcBufferDesc.uiYResolution / swpClient.cy;
 46.1974 +    ptl.y = _this->hidden->SrcBufferDesc.uiYResolution - ptl.y - 1;
 46.1975 +    SDL_PrivateMouseMotion(0, 0, (Sint16) (ptl.x), (Sint16) (ptl.y));
 46.1976 +  } else
 46.1977 +  {
 46.1978 +    // If we're not in focus
 46.1979 +    SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
 46.1980 +    SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
 46.1981 +    SDL_PrivateAppActive(0, SDL_APPACTIVE);
 46.1982 +    SDL_PrivateMouseMotion(0, 0, (Sint16) -1, (Sint16) -1);
 46.1983 +  }
 46.1984 +
 46.1985 +  // Now destroy the message queue, if we've created it!
 46.1986 +  if (ERRORIDERROR(hmqerror)==0)
 46.1987 +    WinDestroyMsgQueue(hmq);
 46.1988 +
 46.1989 +}
 46.1990 +
 46.1991 +/* This pointer should exist in the native video subsystem and should
 46.1992 + point to an appropriate update function for the current video mode
 46.1993 + */
 46.1994 +static void os2fslib_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
 46.1995 +{
 46.1996 +  // If there is no more window, nothing we can do!
 46.1997 +  if (_this->hidden->iPMThreadStatus!=1) return;
 46.1998 +
 46.1999 +#ifdef BITBLT_IN_WINMESSAGEPROC
 46.2000 +  WinSendMsg(_this->hidden->hwndClient,
 46.2001 +                 WM_UPDATERECTSREQUEST,
 46.2002 +                 (MPARAM) numrects,
 46.2003 +                 (MPARAM) rects);
 46.2004 +#else
 46.2005 +  if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
 46.2006 +  {
 46.2007 +    int i;
 46.2008 +
 46.2009 +    if (_this->hidden->pSDLSurface)
 46.2010 +    {
 46.2011 +#ifndef RESIZE_EVEN_IF_RESIZABLE
 46.2012 +      SWP swp;
 46.2013 +      // But only blit if the window is not resizable, or if
 46.2014 +      // the window is resizable and the source buffer size is the
 46.2015 +      // same as the destination buffer size!
 46.2016 +      WinQueryWindowPos(_this->hidden->hwndClient, &swp);
 46.2017 +      if ((_this->hidden->pSDLSurface) &&
 46.2018 +          (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
 46.2019 +          ((swp.cx != _this->hidden->SrcBufferDesc.uiXResolution) ||
 46.2020 +           (swp.cy != _this->hidden->SrcBufferDesc.uiYResolution)
 46.2021 +          ) &&
 46.2022 +          (!FSLib_QueryFSMode(_this->hidden->hwndClient))
 46.2023 +         )
 46.2024 +      {
 46.2025 +        // Resizable surface and in resizing!
 46.2026 +        // So, don't blit now!
 46.2027 +#ifdef DEBUG_BUILD
 46.2028 +        printf("[UpdateRects] : Skipping blit while resizing!\n"); fflush(stdout);
 46.2029 +#endif
 46.2030 +      } else
 46.2031 +#endif
 46.2032 +      {
 46.2033 +      /*
 46.2034 +        // Blit the whole window
 46.2035 +        FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
 46.2036 +                     0, 0,
 46.2037 +                     _this->hidden->SrcBufferDesc.uiXResolution,
 46.2038 +                     _this->hidden->SrcBufferDesc.uiYResolution);
 46.2039 +                     */
 46.2040 +#ifdef DEBUG_BUILD
 46.2041 +          printf("[os2fslib_UpdateRects] : Blitting!\n"); fflush(stdout);
 46.2042 +#endif
 46.2043 +  
 46.2044 +        // Blit the changed areas
 46.2045 +        for (i=0; i<numrects; i++)
 46.2046 +          FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
 46.2047 +                       rects[i].y, rects[i].x, rects[i].w, rects[i].h);
 46.2048 +      }
 46.2049 +    }
 46.2050 +#ifdef DEBUG_BUILD
 46.2051 +     else
 46.2052 +       printf("[os2fslib_UpdateRects] : No public surface!\n"); fflush(stdout);
 46.2053 +#endif
 46.2054 +    DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
 46.2055 +  }
 46.2056 +#ifdef DEBUG_BUILD
 46.2057 +  else
 46.2058 +    printf("[os2fslib_UpdateRects] : Error in mutex!\n"); fflush(stdout);
 46.2059 +#endif
 46.2060 +#endif
 46.2061 +}
 46.2062 +
 46.2063 +
 46.2064 +/* Reverse the effects VideoInit() -- called if VideoInit() fails
 46.2065 + or if the application is shutting down the video subsystem.
 46.2066 + */
 46.2067 +static void os2fslib_VideoQuit(_THIS)
 46.2068 +{
 46.2069 +#ifdef DEBUG_BUILD
 46.2070 +  printf("[os2fslib_VideoQuit]\n"); fflush(stdout);
 46.2071 +#endif
 46.2072 +  // Close PM stuff if running!
 46.2073 +  if (_this->hidden->iPMThreadStatus == 1)
 46.2074 +  {
 46.2075 +    int iTimeout;
 46.2076 +    WinPostMsg(_this->hidden->hwndFrame, WM_QUIT, (MPARAM) 0, (MPARAM) 0);
 46.2077 +    // HACK: We had this line before:
 46.2078 +    //DosWaitThread((TID *) &(_this->hidden->tidPMThread), DCWW_WAIT);
 46.2079 +    // We don't use it, because the PMThread will never stop, or if it stops,
 46.2080 +    // it will kill the whole process as a emergency fallback.
 46.2081 +    // So, we only check for the iPMThreadStatus stuff!
 46.2082 +#ifdef DEBUG_BUILD
 46.2083 +    printf("[os2fslib_VideoQuit] : Waiting for PM thread to die\n"); fflush(stdout);
 46.2084 +#endif
 46.2085 +
 46.2086 +    iTimeout=0;
 46.2087 +    while ((_this->hidden->iPMThreadStatus == 1) && (iTimeout<100))
 46.2088 +    {
 46.2089 +      iTimeout++;
 46.2090 +      DosSleep(64);
 46.2091 +    }
 46.2092 +
 46.2093 +#ifdef DEBUG_BUILD
 46.2094 +    printf("[os2fslib_VideoQuit] : End of wait.\n"); fflush(stdout);
 46.2095 +#endif
 46.2096 +
 46.2097 +    if (_this->hidden->iPMThreadStatus == 1)
 46.2098 +    {
 46.2099 +#ifdef DEBUG_BUILD
 46.2100 +      printf("[os2fslib_VideoQuit] : Killing PM thread!\n"); fflush(stdout);
 46.2101 +#endif
 46.2102 +      
 46.2103 +      _this->hidden->iPMThreadStatus = 0;
 46.2104 +      DosKillThread(_this->hidden->tidPMThread);
 46.2105 +
 46.2106 +      if (_this->hidden->hwndFrame)
 46.2107 +      {
 46.2108 +#ifdef DEBUG_BUILD
 46.2109 +        printf("[os2fslib_VideoQuit] : Destroying PM window!\n"); fflush(stdout);
 46.2110 +#endif
 46.2111 +
 46.2112 +        WinDestroyWindow(_this->hidden->hwndFrame); _this->hidden->hwndFrame=NULL;
 46.2113 +      }
 46.2114 +    }
 46.2115 +
 46.2116 +  }
 46.2117 +
 46.2118 +  // Free result of an old ListModes() call, because there is
 46.2119 +  // no FreeListModes() call in SDL!
 46.2120 +  if (_this->hidden->pListModesResult)
 46.2121 +  {
 46.2122 +    free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
 46.2123 +  }
 46.2124 +
 46.2125 +  // Free list of available fullscreen modes
 46.2126 +  if (_this->hidden->pAvailableFSLibVideoModes)
 46.2127 +  {
 46.2128 +    FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
 46.2129 +    _this->hidden->pAvailableFSLibVideoModes = NULL;
 46.2130 +  }
 46.2131 +
 46.2132 +  // Free application icon if we had one
 46.2133 +  if (hptrCurrentIcon)
 46.2134 +  {
 46.2135 +    WinDestroyPointer(hptrCurrentIcon);
 46.2136 +    hptrCurrentIcon = NULL;
 46.2137 +  }
 46.2138 +}
 46.2139 +
 46.2140 +/* Set the requested video mode, returning a surface which will be
 46.2141 + set to the SDL_VideoSurface.  The width and height will already
 46.2142 + be verified by ListModes(), and the video subsystem is free to
 46.2143 + set the mode to a supported bit depth different from the one
 46.2144 + specified -- the desired bpp will be emulated with a shadow
 46.2145 + surface if necessary.  If a new mode is returned, this function
 46.2146 + should take care of cleaning up the current mode.
 46.2147 + */
 46.2148 +static SDL_Surface *os2fslib_SetVideoMode(_THIS, SDL_Surface *current,
 46.2149 +					  int width, int height, int bpp, Uint32 flags)
 46.2150 +{
 46.2151 +  static int bFirstCall = 1;
 46.2152 +  FSLib_VideoMode_p pModeInfo, pModeInfoFound;
 46.2153 +  FSLib_VideoMode TempModeInfo;
 46.2154 +  HAB hab;
 46.2155 +  HMQ hmq;
 46.2156 +  ERRORID hmqerror;
 46.2157 +  RECTL rectl;
 46.2158 +  SDL_Surface *pResult;
 46.2159 +
 46.2160 +  // If there is no more window, nothing we can do!
 46.2161 +  if (_this->hidden->iPMThreadStatus!=1) return NULL;
 46.2162 +
 46.2163 +#ifdef DEBUG_BUILD
 46.2164 +  printf("[os2fslib_SetVideoMode] : Request for %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
 46.2165 +#endif
 46.2166 +
 46.2167 +  // We don't support palette modes!
 46.2168 +  if (bpp==8) bpp=32;
 46.2169 +
 46.2170 +  // Also, we don't support resizable modes in fullscreen mode.
 46.2171 +  if (flags & SDL_RESIZABLE)
 46.2172 +    flags &= ~SDL_FULLSCREEN;
 46.2173 +
 46.2174 +  // No double buffered mode
 46.2175 +  if (flags & SDL_DOUBLEBUF)
 46.2176 +    flags &= ~SDL_DOUBLEBUF;
 46.2177 +
 46.2178 +  // And, we don't support HWSURFACE yet.
 46.2179 +  if (flags & SDL_HWSURFACE)
 46.2180 +  {
 46.2181 +    flags &= ~SDL_HWSURFACE;
 46.2182 +    flags |= SDL_SWSURFACE;
 46.2183 +  }
 46.2184 +
 46.2185 +#ifdef DEBUG_BUILD
 46.2186 +  printf("[os2fslib_SetVideoMode] : Changed request to %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
 46.2187 +#endif
 46.2188 +
 46.2189 +  // First check if there is such a video mode they want!
 46.2190 +  pModeInfoFound = NULL;
 46.2191 +
 46.2192 +  // For fullscreen mode we don't support every resolution!
 46.2193 +  // So, go through the video modes, and check for such a resolution!
 46.2194 +  pModeInfoFound = NULL;
 46.2195 +  pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
 46.2196 +
 46.2197 +  while (pModeInfo)
 46.2198 +  {
 46.2199 +    // Check all available fullscreen modes for this resolution
 46.2200 +    if ((pModeInfo->uiXResolution == width) &&
 46.2201 +        (pModeInfo->uiYResolution == height) &&
 46.2202 +        (pModeInfo->uiBPP!=8)) // palettized modes not yet supported
 46.2203 +    {
 46.2204 +      // If good resolution, try to find the exact BPP, or at least
 46.2205 +      // something similar...
 46.2206 +      if (!pModeInfoFound)
 46.2207 +        pModeInfoFound = pModeInfo;
 46.2208 +      else
 46.2209 +      if ((pModeInfoFound->uiBPP!=bpp) &&
 46.2210 +          (pModeInfoFound->uiBPP<pModeInfo->uiBPP))
 46.2211 +        pModeInfoFound = pModeInfo;
 46.2212 +    }
 46.2213 +    pModeInfo = pModeInfo->pNext;
 46.2214 +  }
 46.2215 +
 46.2216 +  // If we did not find a good fullscreen mode, then try a similar
 46.2217 +  if (!pModeInfoFound)
 46.2218 +  {
 46.2219 +#ifdef DEBUG_BUILD
 46.2220 +    printf("[os2fslib_SetVideoMode] : Requested video mode not found, looking for a similar one!\n"); fflush(stdout);
 46.2221 +#endif
 46.2222 +    // Go through the video modes again, and find a similar resolution!
 46.2223 +    pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
 46.2224 +    while (pModeInfo)
 46.2225 +    {
 46.2226 +      // Check all available fullscreen modes for this resolution
 46.2227 +      if ((pModeInfo->uiXResolution >= width) &&
 46.2228 +          (pModeInfo->uiYResolution >= height) &&
 46.2229 +          (pModeInfo->uiBPP == bpp))
 46.2230 +      {
 46.2231 +        if (!pModeInfoFound)
 46.2232 +          pModeInfoFound = pModeInfo;
 46.2233 +        else
 46.2234 +        if (((pModeInfoFound->uiXResolution-width)*(pModeInfoFound->uiYResolution-height))>
 46.2235 +            ((pModeInfo->uiXResolution-width)*(pModeInfo->uiYResolution-height)))
 46.2236 +        {
 46.2237 +          // Found a mode which is closer than the current one
 46.2238 +          pModeInfoFound = pModeInfo;
 46.2239 +        }
 46.2240 +      }
 46.2241 +      pModeInfo = pModeInfo->pNext;
 46.2242 +    }
 46.2243 +  }
 46.2244 +
 46.2245 +  // If we did not find a good fullscreen mode, then return NULL
 46.2246 +  if (!pModeInfoFound)
 46.2247 +  {
 46.2248 +#ifdef DEBUG_BUILD
 46.2249 +    printf("[os2fslib_SetVideoMode] : Requested video mode not found!\n"); fflush(stdout);
 46.2250 +#endif
 46.2251 +    return NULL;
 46.2252 +  }
 46.2253 +
 46.2254 +#ifdef DEBUG_BUILD
 46.2255 +  printf("[os2fslib_SetVideoMode] : Found mode!\n"); fflush(stdout);
 46.2256 +#endif
 46.2257 +
 46.2258 +  // We'll possibly adjust the structure, so copy out the values
 46.2259 +  // into TempModeInfo!
 46.2260 +  memcpy(&TempModeInfo, pModeInfoFound, sizeof(TempModeInfo));
 46.2261 +  pModeInfoFound = &TempModeInfo;
 46.2262 +
 46.2263 +  if (flags & SDL_RESIZABLE)
 46.2264 +  {
 46.2265 +#ifdef DEBUG_BUILD
 46.2266 +    printf("[os2fslib_SetVideoMode] : Requested mode is resizable, changing width/height\n"); fflush(stdout);
 46.2267 +#endif
 46.2268 +    // Change width and height to requested one!
 46.2269 +    TempModeInfo.uiXResolution = width;
 46.2270 +    TempModeInfo.uiYResolution = height;
 46.2271 +    TempModeInfo.uiScanLineSize = width * ((TempModeInfo.uiBPP+7)/8);
 46.2272 +  }
 46.2273 +
 46.2274 +  // We can try create new surface!
 46.2275 +
 46.2276 +  // Make sure this thread is prepared for using the Presentation Manager!
 46.2277 +  hab = WinInitialize(0);
 46.2278 +  hmq = WinCreateMsgQueue(hab,0);
 46.2279 +  // Remember if there was an error at WinCreateMsgQueue(), because we don't
 46.2280 +  // want to destroy somebody else's queue later. :)
 46.2281 +  hmqerror = WinGetLastError(hab);
 46.2282 +
 46.2283 +  
 46.2284 +
 46.2285 +  if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
 46.2286 +  {
 46.2287 +#ifdef DEBUG_BUILD
 46.2288 +    printf("[os2fslib_SetVideoMode] : Creating new SW surface\n"); fflush(stdout);
 46.2289 +#endif
 46.2290 +
 46.2291 +    // Create new software surface!
 46.2292 +    pResult = SDL_CreateRGBSurface(SDL_SWSURFACE,
 46.2293 +                                   pModeInfoFound->uiXResolution,
 46.2294 +                                   pModeInfoFound->uiYResolution,
 46.2295 +                                   pModeInfoFound->uiBPP,
 46.2296 +                                   ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition,
 46.2297 +                                   ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition,
 46.2298 +                                   ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition,
 46.2299 +                                   ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition);
 46.2300 +
 46.2301 +    if (pResult == NULL)
 46.2302 +    {
 46.2303 +      DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
 46.2304 +      SDL_OutOfMemory();
 46.2305 +      return NULL;
 46.2306 +    }
 46.2307 +
 46.2308 +#ifdef DEBUG_BUILD
 46.2309 +    printf("[os2fslib_SetVideoMode] : Adjusting pixel format\n"); fflush(stdout);
 46.2310 +#endif
 46.2311 +
 46.2312 +    // Adjust pixel format mask!
 46.2313 +    pResult->format->Rmask = ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition;
 46.2314 +    pResult->format->Rshift = pModeInfoFound->PixelFormat.ucRedPosition;
 46.2315 +    pResult->format->Rloss = pModeInfoFound->PixelFormat.ucRedAdjust;
 46.2316 +    pResult->format->Gmask = ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition;
 46.2317 +    pResult->format->Gshift = pModeInfoFound->PixelFormat.ucGreenPosition;
 46.2318 +    pResult->format->Gloss = pModeInfoFound->PixelFormat.ucGreenAdjust;
 46.2319 +    pResult->format->Bmask = ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition;
 46.2320 +    pResult->format->Bshift = pModeInfoFound->PixelFormat.ucBluePosition;
 46.2321 +    pResult->format->Bloss = pModeInfoFound->PixelFormat.ucBlueAdjust;
 46.2322 +    pResult->format->Amask = ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition;
 46.2323 +    pResult->format->Ashift = pModeInfoFound->PixelFormat.ucAlphaPosition;
 46.2324 +    pResult->format->Aloss = pModeInfoFound->PixelFormat.ucAlphaAdjust;
 46.2325 +
 46.2326 +#ifdef REPORT_EMPTY_ALPHA_MASK
 46.2327 +    pResult->format->Amask =
 46.2328 +        pResult->format->Ashift =
 46.2329 +        pResult->format->Aloss = 0;
 46.2330 +#endif
 46.2331 +
 46.2332 +    // Adjust surface flags
 46.2333 +    pResult->flags |= (flags & SDL_FULLSCREEN);
 46.2334 +    pResult->flags |= (flags & SDL_RESIZABLE);
 46.2335 +
 46.2336 +    // It might be that the software surface pitch is not the same as
 46.2337 +    // the pitch we have, so adjust that!
 46.2338 +    pModeInfoFound->uiScanLineSize = pResult->pitch;
 46.2339 +
 46.2340 +    // Store new source buffer parameters!
 46.2341 +    memcpy(&(_this->hidden->SrcBufferDesc), pModeInfoFound, sizeof(*pModeInfoFound));
 46.2342 +    _this->hidden->pchSrcBuffer = pResult->pixels;
 46.2343 +
 46.2344 +#ifdef DEBUG_BUILD
 46.2345 +    printf("[os2fslib_SetVideoMode] : Telling FSLib the stuffs\n"); fflush(stdout);
 46.2346 +#endif
 46.2347 +
 46.2348 +    // Tell the FSLib window the new source image format
 46.2349 +    FSLib_SetSrcBufferDesc(_this->hidden->hwndClient, &(_this->hidden->SrcBufferDesc));
 46.2350 +
 46.2351 +    if (
 46.2352 +        ((flags & SDL_RESIZABLE)==0) ||
 46.2353 +        (bFirstCall)
 46.2354 +       )
 46.2355 +    {
 46.2356 +      bFirstCall = 0;
 46.2357 +#ifdef DEBUG_BUILD
 46.2358 +      printf("[os2fslib_SetVideoMode] : Modifying window size\n"); fflush(stdout);
 46.2359 +#endif
 46.2360 +
 46.2361 +      // Calculate frame window size from client window size
 46.2362 +      rectl.xLeft = 0;
 46.2363 +      rectl.yBottom = 0;
 46.2364 +      rectl.xRight = pModeInfoFound->uiXResolution; // Noninclusive
 46.2365 +      rectl.yTop = pModeInfoFound->uiYResolution; // Noninclusive
 46.2366 +      WinCalcFrameRect(_this->hidden->hwndFrame, &rectl, FALSE);
 46.2367 +
 46.2368 +      // Set the new size of the main window
 46.2369 +      SetAccessableWindowPos(_this->hidden->hwndFrame,
 46.2370 +                             HWND_TOP,
 46.2371 +                             0, 0,
 46.2372 +                             (rectl.xRight-rectl.xLeft),
 46.2373 +                             (rectl.yTop-rectl.yBottom),
 46.2374 +                             SWP_SIZE | SWP_ACTIVATE | SWP_SHOW);
 46.2375 +    }
 46.2376 +
 46.2377 +    // Set fullscreen mode flag, and switch to fullscreen if needed!
 46.2378 +    if (flags & SDL_FULLSCREEN)
 46.2379 +    {
 46.2380 +#ifdef DEBUG_BUILD
 46.2381 +      printf("[os2fslib_SetVideoMode] : Also trying to switch to fullscreen\n");
 46.2382 +      fflush(stdout);
 46.2383 +#endif
 46.2384 +      FSLib_ToggleFSMode(_this->hidden->hwndClient, 1);
 46.2385 +      /* Cursor manager functions to FS mode*/
 46.2386 +      os2fslib_SetCursorManagementFunctions(_this, 0);
 46.2387 +    } else
 46.2388 +    {
 46.2389 +#ifdef DEBUG_BUILD
 46.2390 +      printf("[os2fslib_SetVideoMode] : Also trying to switch to desktop mode\n");
 46.2391 +      fflush(stdout);
 46.2392 +#endif
 46.2393 +      FSLib_ToggleFSMode(_this->hidden->hwndClient, 0);
 46.2394 +      /* Cursor manager functions to Windowed mode*/
 46.2395 +      os2fslib_SetCursorManagementFunctions(_this, 1);
 46.2396 +    }
 46.2397 +
 46.2398 +    _this->hidden->pSDLSurface = pResult;
 46.2399 +
 46.2400 +    DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
 46.2401 +  } else
 46.2402 +  {
 46.2403 +#ifdef DEBUG_BUILD
 46.2404 +    printf("[os2fslib_SetVideoMode] : Could not get hmtxUseSrcBuffer!\n"); fflush(stdout);
 46.2405 +#endif
 46.2406 +    
 46.2407 +    pResult = NULL;
 46.2408 +  }
 46.2409 +
 46.2410 +  // As we have the new surface, we don't need the current one anymore!
 46.2411 +  if ((pResult) && (current))
 46.2412 +  {
 46.2413 +#ifdef DEBUG_BUILD
 46.2414 +    printf("[os2fslib_SetVideoMode] : Freeing old surface\n"); fflush(stdout);
 46.2415 +#endif
 46.2416 +    SDL_FreeSurface(current);
 46.2417 +  }
 46.2418 +
 46.2419 +  // Redraw window
 46.2420 +  WinInvalidateRegion(_this->hidden->hwndClient, NULL, TRUE);
 46.2421 +
 46.2422 +  // Now destroy the message queue, if we've created it!
 46.2423 +  if (ERRORIDERROR(hmqerror)==0)
 46.2424 +  {
 46.2425 +#ifdef DEBUG_BUILD
 46.2426 +    printf("[os2fslib_SetVideoMode] : Destroying message queue\n"); fflush(stdout);
 46.2427 +#endif
 46.2428 +    WinDestroyMsgQueue(hmq);
 46.2429 +  }
 46.2430 +
 46.2431 +#ifdef DEBUG_BUILD
 46.2432 +  printf("[os2fslib_SetVideoMode] : Done\n"); fflush(stdout);
 46.2433 +#endif
 46.2434 +
 46.2435 +  /* We're done */
 46.2436 +
 46.2437 +  // Return with the new surface!
 46.2438 +  return pResult;
 46.2439 +}
 46.2440 +
 46.2441 +/* List the available video modes for the given pixel format, sorted
 46.2442 + from largest to smallest.
 46.2443 + */
 46.2444 +static SDL_Rect **os2fslib_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
 46.2445 +{
 46.2446 +#ifdef DEBUG_BUILD
 46.2447 +  printf("[os2fslib_ListModes] : ListModes of %d Bpp\n", format->BitsPerPixel);
 46.2448 +#endif
 46.2449 +  // Destroy result of previous call, if there is any
 46.2450 +  if (_this->hidden->pListModesResult)
 46.2451 +  {
 46.2452 +    free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
 46.2453 +  }
 46.2454 +
 46.2455 +  // For resizable and windowed mode we support every resolution!
 46.2456 +  if ((flags & SDL_RESIZABLE) && ((flags & SDL_FULLSCREEN) == 0))
 46.2457 +    return (SDL_Rect **)-1;
 46.2458 +
 46.2459 +  // Check if they need fullscreen or non-fullscreen video modes!
 46.2460 +  if ((flags & SDL_FULLSCREEN) == 0)
 46.2461 +
 46.2462 +  {
 46.2463 +    // For windowed mode we support every resolution!
 46.2464 +    return (SDL_Rect **)-1;
 46.2465 +  } else
 46.2466 +  {
 46.2467 +    FSLib_VideoMode_p pFSMode;
 46.2468 +    // For fullscreen mode we don't support every resolution!
 46.2469 +    // Now create a new list
 46.2470 +    pFSMode = _this->hidden->pAvailableFSLibVideoModes;
 46.2471 +    while (pFSMode)
 46.2472 +    {
 46.2473 +      if (pFSMode->uiBPP == format->BitsPerPixel)
 46.2474 +      {
 46.2475 +        SDL_Rect *pRect = (SDL_Rect *) malloc(sizeof(SDL_Rect));
 46.2476 +        if (pRect)
 46.2477 +        {
 46.2478 +          // Fill description
 46.2479 +          pRect->x = 0;
 46.2480 +          pRect->y = 0;
 46.2481 +          pRect->w = pFSMode->uiXResolution;
 46.2482 +          pRect->h = pFSMode->uiYResolution;
 46.2483 +#ifdef DEBUG_BUILD
 46.2484 +//          printf("!!! Seems to be good!\n");
 46.2485 +//	  printf("F: %dx%d\n", pRect->w, pRect->h);
 46.2486 +#endif
 46.2487 +          // And insert into list of pRects
 46.2488 +          if (!(_this->hidden->pListModesResult))
 46.2489 +          {
 46.2490 +#ifdef DEBUG_BUILD
 46.2491 +//            printf("!!! Inserting to beginning\n");
 46.2492 +#endif
 46.2493 +
 46.2494 +            // We're the first one to be inserted!
 46.2495 +            _this->hidden->pListModesResult = (SDL_Rect**) malloc(2*sizeof(SDL_Rect*));
 46.2496 +            if (_this->hidden->pListModesResult)
 46.2497 +            {
 46.2498 +              _this->hidden->pListModesResult[0] = pRect;
 46.2499 +	      _this->hidden->pListModesResult[1] = NULL;
 46.2500 +            } else
 46.2501 +            {
 46.2502 +              free(pRect);
 46.2503 +            }
 46.2504 +          } else
 46.2505 +          {
 46.2506 +            // We're not the first ones, so find the place where we
 46.2507 +            // have to insert ourselves
 46.2508 +            SDL_Rect **pNewList;
 46.2509 +            int iPlace, iNumOfSlots, i;
 46.2510 +
 46.2511 +#ifdef DEBUG_BUILD
 46.2512 +//            printf("!!! Searching where to insert\n");
 46.2513 +#endif
 46.2514 +
 46.2515 +            iPlace = -1; iNumOfSlots = 1; // Count the last NULL too!
 46.2516 +            for (i=0; _this->hidden->pListModesResult[i]; i++)
 46.2517 +            {
 46.2518 +              iNumOfSlots++;
 46.2519 +              if (iPlace==-1)
 46.2520 +              {
 46.2521 +                if ((_this->hidden->pListModesResult[i]->w*_this->hidden->pListModesResult[i]->h)<
 46.2522 +                    (pRect->w*pRect->h))
 46.2523 +                {
 46.2524 +                  iPlace = i;
 46.2525 +                }
 46.2526 +              }
 46.2527 +            }
 46.2528 +            if (iPlace==-1) iPlace = iNumOfSlots-1;
 46.2529 +
 46.2530 +#ifdef DEBUG_BUILD
 46.2531 +//            printf("!!! From %d slots, it will be at %d\n", iNumOfSlots, iPlace);
 46.2532 +#endif
 46.2533 +
 46.2534 +            pNewList = (SDL_Rect**) realloc(_this->hidden->pListModesResult, (iNumOfSlots+1)*sizeof(SDL_Rect*));
 46.2535 +            if (pNewList)
 46.2536 +            {
 46.2537 +              for (i=iNumOfSlots;i>iPlace;i--)
 46.2538 +                pNewList[i] = pNewList[i-1];
 46.2539 +              pNewList[iPlace] = pRect;
 46.2540 +              _this->hidden->pListModesResult = pNewList;
 46.2541 +            } else
 46.2542 +            {
 46.2543 +              free(pRect);
 46.2544 +            }
 46.2545 +          }
 46.2546 +        }
 46.2547 +      }
 46.2548 +      pFSMode = pFSMode->pNext;
 46.2549 +    }
 46.2550 +  }
 46.2551 +#ifdef DEBUG_BUILD
 46.2552 +//  printf("Returning list\n");
 46.2553 +#endif
 46.2554 +  return _this->hidden->pListModesResult;
 46.2555 +}
 46.2556 +
 46.2557 +/* Initialize the native video subsystem, filling 'vformat' with the
 46.2558 + "best" display pixel format, returning 0 or -1 if there's an error.
 46.2559 + */
 46.2560 +static int os2fslib_VideoInit(_THIS, SDL_PixelFormat *vformat)
 46.2561 +{
 46.2562 +  FSLib_VideoMode_p pDesktopMode;
 46.2563 +
 46.2564 +#ifdef DEBUG_BUILD
 46.2565 +  printf("[os2fslib_VideoInit] : Enter\n"); fflush(stdout);
 46.2566 +#endif
 46.2567 +
 46.2568 +  // Report the best pixel format. For this,
 46.2569 +  // we'll use the current desktop format.
 46.2570 +  pDesktopMode = FSLib_GetDesktopVideoMode();
 46.2571 +  if (!pDesktopMode)
 46.2572 +  {
 46.2573 +    SDL_SetError("Could not query desktop video mode!");
 46.2574 +#ifdef DEBUG_BUILD
 46.2575 +    printf("[os2fslib_VideoInit] : Could not query desktop video mode!\n");
 46.2576 +#endif
 46.2577 +    return -1;
 46.2578 +  }
 46.2579 +
 46.2580 +  /* Determine the screen depth */
 46.2581 +  vformat->BitsPerPixel = pDesktopMode->uiBPP;
 46.2582 +  vformat->BytesPerPixel = (vformat->BitsPerPixel+7)/8;
 46.2583 +
 46.2584 +  vformat->Rmask = ((unsigned int) pDesktopMode->PixelFormat.ucRedMask) << pDesktopMode->PixelFormat.ucRedPosition;
 46.2585 +  vformat->Rshift = pDesktopMode->PixelFormat.ucRedPosition;
 46.2586 +  vformat->Rloss = pDesktopMode->PixelFormat.ucRedAdjust;
 46.2587 +  vformat->Gmask = ((unsigned int) pDesktopMode->PixelFormat.ucGreenMask) << pDesktopMode->PixelFormat.ucGreenPosition;
 46.2588 +  vformat->Gshift = pDesktopMode->PixelFormat.ucGreenPosition;
 46.2589 +  vformat->Gloss = pDesktopMode->PixelFormat.ucGreenAdjust;
 46.2590 +  vformat->Bmask = ((unsigned int) pDesktopMode->PixelFormat.ucBlueMask) << pDesktopMode->PixelFormat.ucBluePosition;
 46.2591 +  vformat->Bshift = pDesktopMode->PixelFormat.ucBluePosition;
 46.2592 +  vformat->Bloss = pDesktopMode->PixelFormat.ucBlueAdjust;
 46.2593 +  vformat->Amask = ((unsigned int) pDesktopMode->PixelFormat.ucAlphaMask) << pDesktopMode->PixelFormat.ucAlphaPosition;
 46.2594 +  vformat->Ashift = pDesktopMode->PixelFormat.ucAlphaPosition;
 46.2595 +  vformat->Aloss = pDesktopMode->PixelFormat.ucAlphaAdjust;
 46.2596 +
 46.2597 +#ifdef REPORT_EMPTY_ALPHA_MASK
 46.2598 +  vformat->Amask =
 46.2599 +      vformat->Ashift =
 46.2600 +      vformat->Aloss = 0;
 46.2601 +#endif
 46.2602 +
 46.2603 +  // Fill in some window manager capabilities
 46.2604 +  _this->info.wm_available = 1;
 46.2605 +
 46.2606 +  // Initialize some internal variables
 46.2607 +  _this->hidden->pListModesResult = NULL;
 46.2608 +  _this->hidden->fInFocus = 0;
 46.2609 +  _this->hidden->iSkipWMMOUSEMOVE = 0;
 46.2610 +  _this->hidden->iMouseVisible = 1;
 46.2611 +  DosCreateMutexSem(NULL, &(_this->hidden->hmtxUseSrcBuffer), 0, FALSE);
 46.2612 +
 46.2613 +  // Now create our window with a default size
 46.2614 +
 46.2615 +  // For this, we select the first available fullscreen mode as
 46.2616 +  // current window size!
 46.2617 +  memcpy(&(_this->hidden->SrcBufferDesc), _this->hidden->pAvailableFSLibVideoModes, sizeof(_this->hidden->SrcBufferDesc));
 46.2618 +  // Allocate new video buffer!
 46.2619 +  _this->hidden->pchSrcBuffer = (char *) malloc(_this->hidden->pAvailableFSLibVideoModes->uiScanLineSize * _this->hidden->pAvailableFSLibVideoModes->uiYResolution);
 46.2620 +  if (!_this->hidden->pchSrcBuffer)
 46.2621 +  {
 46.2622 +#ifdef DEBUG_BUILD
 46.2623 +    printf("[os2fslib_VideoInit] : Yikes, not enough memory for new video buffer!\n"); fflush(stdout);
 46.2624 +#endif
 46.2625 +    SDL_SetError("Not enough memory for new video buffer!\n");
 46.2626 +    return -1;
 46.2627 +  }
 46.2628 +
 46.2629 +  // For this, we need a message processing thread.
 46.2630 +  // We'll create a new thread for this, which will do everything
 46.2631 +  // what is related to PM
 46.2632 +  _this->hidden->iPMThreadStatus = 0;
 46.2633 +  _this->hidden->tidPMThread = _beginthread(PMThreadFunc, NULL, 65536, (void *) _this);
 46.2634 +  if (_this->hidden->tidPMThread <= 0)
 46.2635 +  {
 46.2636 +#ifdef DEBUG_BUILD
 46.2637 +    printf("[os2fslib_VideoInit] : Could not create PM thread!\n");
 46.2638 +#endif
 46.2639 +    SDL_SetError("Could not create PM thread");
 46.2640 +    return -1;
 46.2641 +  }
 46.2642 +#ifdef USE_DOSSETPRIORITY
 46.2643 +  // Burst the priority of PM Thread!
 46.2644 +  DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, _this->hidden->tidPMThread);
 46.2645 +#endif
 46.2646 +  // Wait for the PM thread to initialize!
 46.2647 +  while (_this->hidden->iPMThreadStatus==0)
 46.2648 +    DosSleep(32);
 46.2649 +  // If the PM thread could not set up everything, then
 46.2650 +  // report an error!
 46.2651 +  if (_this->hidden->iPMThreadStatus!=1)
 46.2652 +  {
 46.2653 +#ifdef DEBUG_BUILD
 46.2654 +    printf("[os2fslib_VideoInit] : PMThread reported an error : %d\n", _this->hidden->iPMThreadStatus);
 46.2655 +#endif
 46.2656 +    SDL_SetError("Error initializing PM thread");
 46.2657 +    return -1;
 46.2658 +  }
 46.2659 +
 46.2660 +  return 0;
 46.2661 +}
 46.2662 +
 46.2663 +
 46.2664 +static void os2fslib_DeleteDevice(_THIS)
 46.2665 +{
 46.2666 +#ifdef DEBUG_BUILD
 46.2667 +  printf("[os2fslib_DeleteDevice]\n"); fflush(stdout);
 46.2668 +#endif
 46.2669 +  // Free used memory
 46.2670 +  FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
 46.2671 +  if (_this->hidden->pListModesResult)
 46.2672 +    free(_this->hidden->pListModesResult);
 46.2673 +  if (_this->hidden->pchSrcBuffer)
 46.2674 +    free(_this->hidden->pchSrcBuffer);
 46.2675 +  DosCloseMutexSem(_this->hidden->hmtxUseSrcBuffer);
 46.2676 +  free(_this->hidden);
 46.2677 +  free(_this);
 46.2678 +  FSLib_Uninitialize();
 46.2679 +}
 46.2680 +
 46.2681 +static int os2fslib_Available(void)
 46.2682 +{
 46.2683 +
 46.2684 +  // If we can run, it means that we could load FSLib,
 46.2685 +  // so we assume that it's available then!
 46.2686 +  return 1;
 46.2687 +}
 46.2688 +
 46.2689 +static void os2fslib_MorphToPM()
 46.2690 +{
 46.2691 +  PPIB pib;
 46.2692 +  PTIB tib;
 46.2693 +
 46.2694 +  DosGetInfoBlocks(&tib, &pib);
 46.2695 +
 46.2696 +  // Change flag from VIO to PM:
 46.2697 +  if (pib->pib_ultype==2) pib->pib_ultype = 3;
 46.2698 +}
 46.2699 +
 46.2700 +static SDL_VideoDevice *os2fslib_CreateDevice(int devindex)
 46.2701 +{
 46.2702 +  SDL_VideoDevice *device;
 46.2703 +
 46.2704 +#ifdef DEBUG_BUILD
 46.2705 +  printf("[os2fslib_CreateDevice] : Enter\n"); fflush(stdout);
 46.2706 +#endif
 46.2707 +
 46.2708 +  /* Initialize all variables that we clean on shutdown */
 46.2709 +  device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
 46.2710 +  if ( device )
 46.2711 +  {
 46.2712 +    memset(device, 0, (sizeof *device));
 46.2713 +    // Also allocate memory for private data
 46.2714 +    device->hidden = (struct SDL_PrivateVideoData *) malloc((sizeof(struct SDL_PrivateVideoData)));
 46.2715 +  }
 46.2716 +  if ( (device == NULL) || (device->hidden == NULL) )
 46.2717 +  {
 46.2718 +    SDL_OutOfMemory();
 46.2719 +    if ( device )
 46.2720 +      free(device);
 46.2721 +    return NULL;
 46.2722 +  }
 46.2723 +  memset(device->hidden, 0, (sizeof *device->hidden));
 46.2724 +
 46.2725 +  /* Set the function pointers */
 46.2726 +#ifdef DEBUG_BUILD
 46.2727 +  printf("[os2fslib_CreateDevice] : VideoInit is %p\n", os2fslib_VideoInit); fflush(stdout);
 46.2728 +#endif
 46.2729 +
 46.2730 +  /* Initialization/Query functions */
 46.2731 +  device->VideoInit = os2fslib_VideoInit;
 46.2732 +  device->ListModes = os2fslib_ListModes;
 46.2733 +  device->SetVideoMode = os2fslib_SetVideoMode;
 46.2734 +  device->ToggleFullScreen = os2fslib_ToggleFullScreen;
 46.2735 +  device->UpdateMouse = os2fslib_UpdateMouse;
 46.2736 +  device->CreateYUVOverlay = NULL;
 46.2737 +  device->SetColors = os2fslib_SetColors;
 46.2738 +  device->UpdateRects = os2fslib_UpdateRects;
 46.2739 +  device->VideoQuit = os2fslib_VideoQuit;
 46.2740 +  /* Hardware acceleration functions */
 46.2741 +  device->AllocHWSurface = os2fslib_AllocHWSurface;
 46.2742 +  device->CheckHWBlit = NULL;
 46.2743 +  device->FillHWRect = NULL;
 46.2744 +  device->SetHWColorKey = NULL;
 46.2745 +  device->SetHWAlpha = NULL;
 46.2746 +  device->LockHWSurface = os2fslib_LockHWSurface;
 46.2747 +  device->UnlockHWSurface = os2fslib_UnlockHWSurface;
 46.2748 +  device->FlipHWSurface = NULL;
 46.2749 +  device->FreeHWSurface = os2fslib_FreeHWSurface;
 46.2750 +  /* Window manager functions */
 46.2751 +  device->SetCaption = os2fslib_SetCaption;
 46.2752 +  device->SetIcon = os2fslib_SetIcon;
 46.2753 +  device->IconifyWindow = os2fslib_IconifyWindow;
 46.2754 +  device->GrabInput = os2fslib_GrabInput;
 46.2755 +  device->GetWMInfo = NULL;
 46.2756 +  /* Cursor manager functions to Windowed mode*/
 46.2757 +  os2fslib_SetCursorManagementFunctions(device, 1);
 46.2758 +  /* Event manager functions */
 46.2759 +  device->InitOSKeymap = os2fslib_InitOSKeymap;
 46.2760 +  device->PumpEvents = os2fslib_PumpEvents;
 46.2761 +  /* The function used to dispose of this structure */
 46.2762 +  device->free = os2fslib_DeleteDevice;
 46.2763 +
 46.2764 +  // Make sure we'll be able to use Win* API even if the application
 46.2765 +  // was linked to be a VIO application!
 46.2766 +  os2fslib_MorphToPM();
 46.2767 +
 46.2768 +  // Now initialize FSLib, and query available video modes!
 46.2769 +  if (!FSLib_Initialize())
 46.2770 +  {
 46.2771 +    // Could not initialize FSLib!
 46.2772 +#ifdef DEBUG_BUILD
 46.2773 +    printf("[os2fslib_CreateDevice] : Could not initialize FSLib!\n");
 46.2774 +#endif
 46.2775 +    SDL_SetError("Could not initialize FSLib!");
 46.2776 +    free(device->hidden);
 46.2777 +    free(device);
 46.2778 +    return NULL;
 46.2779 +  }
 46.2780 +  device->hidden->pAvailableFSLibVideoModes =
 46.2781 +    FSLib_GetVideoModeList();
 46.2782 +
 46.2783 +  return device;
 46.2784 +}
 46.2785 +
 46.2786 +VideoBootStrap OS2FSLib_bootstrap = {
 46.2787 +  	"os2fslib", "OS/2 Video Output using FSLib",
 46.2788 +	os2fslib_Available, os2fslib_CreateDevice
 46.2789 +};
 46.2790 +
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/src/video/os2fslib/SDL_os2fslib.h	Wed Nov 23 07:29:56 2005 +0000
    47.3 @@ -0,0 +1,63 @@
    47.4 +/*
    47.5 +    SDL - Simple DirectMedia Layer
    47.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    47.7 +
    47.8 +    This library is free software; you can redistribute it and/or
    47.9 +    modify it under the terms of the GNU Library General Public
   47.10 +    License as published by the Free Software Foundation; either
   47.11 +    version 2 of the License, or (at your option) any later version.
   47.12 +
   47.13 +    This library is distributed in the hope that it will be useful,
   47.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   47.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   47.16 +    Library General Public License for more details.
   47.17 +
   47.18 +    You should have received a copy of the GNU Library General Public
   47.19 +    License along with this library; if not, write to the Free
   47.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   47.21 +
   47.22 +    Sam Lantinga
   47.23 +    slouken@libsdl.org
   47.24 +*/
   47.25 +
   47.26 +#ifndef _SDL_os2fslib_h
   47.27 +#define _SDL_os2fslib_h
   47.28 +
   47.29 +
   47.30 +// OS2 specific includes
   47.31 +#define INCL_TYPES
   47.32 +#define INCL_DOS
   47.33 +#define INCL_DOSERRORS
   47.34 +#define INCL_DOSPROCESS
   47.35 +#define INCL_WIN
   47.36 +#define INCL_GPI
   47.37 +#include <os2.h>
   47.38 +
   47.39 +#include <FSLib.h>
   47.40 +
   47.41 +/* Hidden "this" pointer for the video functions */
   47.42 +#define _THIS	SDL_VideoDevice *_this
   47.43 +
   47.44 +/* Private display data */
   47.45 +struct SDL_PrivateVideoData
   47.46 +{
   47.47 +  FSLib_VideoMode_p   pAvailableFSLibVideoModes;
   47.48 +  SDL_Rect          **pListModesResult; // Allocated memory to return list of modes for os2fslib_ListModes() API
   47.49 +
   47.50 +  FSLib_VideoMode     SrcBufferDesc;    // Description of current source image buffer
   47.51 +  char               *pchSrcBuffer;     // The source image buffer itself
   47.52 +  SDL_Surface        *pSDLSurface;      // The SDL surface describing the buffer
   47.53 +  HMTX                hmtxUseSrcBuffer; // Mutex semaphore to manipulate src buffer
   47.54 +  HWND                hwndFrame, hwndClient;  // Window handle of frame and client
   47.55 +  int                 iPMThreadStatus;  // 0: Not running
   47.56 +                                        // 1: Running
   47.57 +                                        // Other: Not running, had an error
   47.58 +  int                 tidPMThread;      // Thread ID of PM Thread
   47.59 +  int                 fInFocus;         // True if we're in focus!
   47.60 +  int                 iSkipWMMOUSEMOVE; // Number of WM_MOUSEMOVE messages to skip!
   47.61 +  int                 iMouseVisible;    //
   47.62 +};
   47.63 +
   47.64 +extern DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF);
   47.65 +
   47.66 +#endif /* _SDL_os2fslib_h */
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/src/video/os2fslib/SDL_vkeys.h	Wed Nov 23 07:29:56 2005 +0000
    48.3 @@ -0,0 +1,79 @@
    48.4 +/*
    48.5 +    SDL - Simple DirectMedia Layer
    48.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
    48.7 +
    48.8 +    This library is free software; you can redistribute it and/or
    48.9 +    modify it under the terms of the GNU Library General Public
   48.10 +    License as published by the Free Software Foundation; either
   48.11 +    version 2 of the License, or (at your option) any later version.
   48.12 +
   48.13 +    This library is distributed in the hope that it will be useful,
   48.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   48.16 +    Library General Public License for more details.
   48.17 +
   48.18 +    You should have received a copy of the GNU Library General Public
   48.19 +    License along with this library; if not, write to the Free
   48.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   48.21 +
   48.22 +    Sam Lantinga
   48.23 +    slouken@libsdl.org
   48.24 +*/
   48.25 +
   48.26 +#ifdef SAVE_RCSID
   48.27 +static char rcsid =
   48.28 + "@(#) $Id$";
   48.29 +#endif
   48.30 +
   48.31 +#ifndef VK_0
   48.32 +#define VK_0	'0'
   48.33 +#define VK_1	'1'
   48.34 +#define VK_2	'2'
   48.35 +#define VK_3	'3'
   48.36 +#define VK_4	'4'
   48.37 +#define VK_5	'5'
   48.38 +#define VK_6	'6'
   48.39 +#define VK_7	'7'
   48.40 +#define VK_8	'8'
   48.41 +#define VK_9	'9'
   48.42 +#define VK_A	'A'
   48.43 +#define VK_B	'B'
   48.44 +#define VK_C	'C'
   48.45 +#define VK_D	'D'
   48.46 +#define VK_E	'E'
   48.47 +#define VK_F	'F'
   48.48 +#define VK_G	'G'
   48.49 +#define VK_H	'H'
   48.50 +#define VK_I	'I'
   48.51 +#define VK_J	'J'
   48.52 +#define VK_K	'K'
   48.53 +#define VK_L	'L'
   48.54 +#define VK_M	'M'
   48.55 +#define VK_N	'N'
   48.56 +#define VK_O	'O'
   48.57 +#define VK_P	'P'
   48.58 +#define VK_Q	'Q'
   48.59 +#define VK_R	'R'
   48.60 +#define VK_S	'S'
   48.61 +#define VK_T	'T'
   48.62 +#define VK_U	'U'
   48.63 +#define VK_V	'V'
   48.64 +#define VK_W	'W'
   48.65 +#define VK_X	'X'
   48.66 +#define VK_Y	'Y'
   48.67 +#define VK_Z	'Z'
   48.68 +#endif /* VK_0 */
   48.69 +
   48.70 +/* These keys haven't been defined, but were experimentally determined */
   48.71 +#define VK_SEMICOLON	0xBA
   48.72 +#define VK_EQUALS	0xBB
   48.73 +#define VK_COMMA	0xBC
   48.74 +#define VK_MINUS	0xBD
   48.75 +#define VK_PERIOD	0xBE
   48.76 +#define VK_SLASH	0xBF
   48.77 +#define VK_GRAVE	0xC0
   48.78 +#define VK_LBRACKET	0xDB
   48.79 +#define VK_BACKSLASH	0xDC
   48.80 +#define VK_RBRACKET	0xDD
   48.81 +#define VK_APOSTROPHE	0xDE
   48.82 +#define VK_BACKTICK	0xDF
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/test/Makefile.wat	Wed Nov 23 07:29:56 2005 +0000
    49.3 @@ -0,0 +1,52 @@
    49.4 +#=============================================================================
    49.5 +#          This is a Watcom makefile to build SDL.DLL for OS/2
    49.6 +#
    49.7 +# Makefile for test applications
    49.8 +#=============================================================================
    49.9 +
   49.10 +# Create debug build or not?
   49.11 +debug_build=defined
   49.12 +
   49.13 +#-----------------------------------------------------------------------------
   49.14 +# The next part is somewhat general, for creation of EXE files.
   49.15 +#-----------------------------------------------------------------------------
   49.16 +
   49.17 +cflags = $(debugflags) -bm -bt=OS2 -5 -fpi -sg -otexan -wx -ei
   49.18 +
   49.19 +.before
   49.20 +    set include=$(%os2tk)\h;$(%include);../include
   49.21 +
   49.22 +.extensions:
   49.23 +.extensions: .exe .obj .c
   49.24 +
   49.25 +all :   testalpha.exe     &
   49.26 +        testbitmap.exe    &
   49.27 +        testcdrom.exe     &
   49.28 +        testcpuinfo.exe   &
   49.29 +        testjoystick.exe  &
   49.30 +        testkeys.exe      &
   49.31 +        testlock.exe      &
   49.32 +        testsem.exe       &
   49.33 +        testsprite.exe    &
   49.34 +        testtimer.exe     &
   49.35 +        testtypes.exe     &
   49.36 +        testver.exe       &
   49.37 +        testvidinfo.exe   &
   49.38 +        testwin.exe       &
   49.39 +        testwm.exe        &
   49.40 +        threadwin.exe     &
   49.41 +        torturethread.exe &
   49.42 +        checkkeys.exe
   49.43 +
   49.44 +.c.obj : .AUTODEPEND
   49.45 +    wcc386 -zq -bm -5s -ei -oteaxan -wx $[* $(cflags)
   49.46 +
   49.47 +.obj.exe : .AUTODEPEND
   49.48 +    wlink system os2v2 F $* L ..\src\sdl.lib name $@ op quiet
   49.49 +
   49.50 +clean : .SYMBOLIC
   49.51 +        @if exist *.exe del *.exe
   49.52 +        @if exist *.obj del *.obj
   49.53 +        @if exist *.map del *.map
   49.54 +        @if exist *.res del *.res
   49.55 +        @if exist *.lst del *.lst