OS/2 port!
This was mostly, if not entirely, written by "Doodle" and "Caetano": doodle@scenergy.dfmk.hu daniel@caetano.eng.br --ryan. --HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401193
This commit is contained in:
parent
c154edb92f
commit
b08452cb40
49 changed files with 6571 additions and 8 deletions
133
README.OS2
Normal file
133
README.OS2
Normal file
|
@ -0,0 +1,133 @@
|
|||
|
||||
===========
|
||||
SDL on OS/2
|
||||
===========
|
||||
|
||||
Last updated on Oct 02, 2005.
|
||||
|
||||
|
||||
1. How to compile?
|
||||
------------------
|
||||
|
||||
To compile this, you'll need the followings installed:
|
||||
- The OS/2 Developer's Toolkit
|
||||
- The OpenWatcom compiler
|
||||
(http://www.openwatcom.org)
|
||||
- The FSLib library
|
||||
(ftp://ftp.netlabs.org/pub/SDL)
|
||||
|
||||
Please edit the second, fourth and fifth lines of setvars.cmd file
|
||||
to set the folders where the toolkit, the OW compiler and the FSLib are.
|
||||
You won't need NASM yet (The Netwide Assembler), you can leave that line.
|
||||
Run setvars.cmd, and you should get a shell in which you can
|
||||
compile SDL.
|
||||
|
||||
Check the "Watcom.mif" file. This is the file which is included by all the
|
||||
Watcom makefiles, so changes here will affect the whole build process.
|
||||
There is a line in there which determines if the resulting SDL.DLL will be
|
||||
a 'debug' or a 'release' build. The 'debug' version is full of printf()'s,
|
||||
so if something goes wrong, its output can help a lot for debugging.
|
||||
|
||||
Then go to the 'src' folder, and run "wmake -f makefile.wat".
|
||||
This should create the SDL.DLL and the corresponding SDL.LIB file there.
|
||||
|
||||
To test applications, it's a good idea to use the 'debug' build of SDL, and
|
||||
redirect the standard output and standard error output to files, to see what
|
||||
happens internally in SDL.
|
||||
(like: testsprite >stdout.txt 2>stderr.txt)
|
||||
|
||||
To rebuild SDL, use the following commands in 'src' folder:
|
||||
wmake -f makefile.wat clean
|
||||
wmake -f makefile.wat
|
||||
|
||||
|
||||
|
||||
2. How to compile the testapps?
|
||||
-------------------------------
|
||||
|
||||
Once you have SDL.DLL compiled, navigate into the 'test' folder, copy in there
|
||||
the newly built SDL.DLL, and copy in there FSLib.DLL.
|
||||
|
||||
Then run "wmake -f makefile.wat" in there to compile some of the testapps.
|
||||
|
||||
|
||||
|
||||
3. What is missing?
|
||||
-------------------
|
||||
|
||||
The following things are missing from this SDL implementation:
|
||||
- MMX, SSE and 3DNOW! optimized video blitters?
|
||||
- HW Video surfaces
|
||||
- OpenGL support
|
||||
|
||||
|
||||
|
||||
4. Special Keys / Full-Screen support
|
||||
-------------------------------------
|
||||
|
||||
There are two special hot-keys implemented:
|
||||
- Alt+Home switches between fullscreen and windowed mode
|
||||
- Alt+End simulates closing the window (can be used as a Panic key)
|
||||
Only the LEFT Alt key will work.
|
||||
|
||||
|
||||
|
||||
5. Joysticks on SDL/2
|
||||
---------------------
|
||||
|
||||
The Joystick detection only works for standard joysticks (2 buttons, 2 axes
|
||||
and the like). Therefore, if you use a non-standard joystick, you should
|
||||
specify its features in the SDL_OS2_JOYSTICK environment variable in a batch
|
||||
file or CONFIG.SYS, so SDL applications can provide full capability to your
|
||||
device. The syntax is:
|
||||
|
||||
SET SDL_OS2_JOYSTICK=[JOYSTICK_NAME] [AXES] [BUTTONS] [HATS] [BALLS]
|
||||
|
||||
So, it you have a Gravis GamePad with 4 axes, 2 buttons, 2 hats and 0 balls,
|
||||
the line should be:
|
||||
|
||||
SET SDL_OS2_JOYSTICK=Gravis_GamePad 4 2 2 0
|
||||
|
||||
If you want to add spaces in your joystick name, just surround it with
|
||||
quotes or double-quotes:
|
||||
|
||||
SET SDL_OS2_JOYSTICK='Gravis GamePad' 4 2 2 0
|
||||
|
||||
or
|
||||
|
||||
SET SDL_OS2_JOYSTICK="Gravis GamePad" 4 2 2 0
|
||||
|
||||
Notive However that Balls and Hats are not supported under OS/2, and the
|
||||
value will be ignored... but it is wise to define these correctly because
|
||||
in the future those can be supported.
|
||||
Also the number of buttons is limited to 2 when using two joysticks,
|
||||
4 when using one joystick with 4 axes, 6 when using a joystick with 3 axes
|
||||
and 8 when using a joystick with 2 axes. Notice however these are limitations
|
||||
of the Joystick Port hardware, not OS/2.
|
||||
|
||||
|
||||
|
||||
6. Next steps...
|
||||
----------------
|
||||
|
||||
Things to do:
|
||||
- Implement missing stuffs (look for 'TODO' string in source code!)
|
||||
- Finish video driver (the 'wincommon' can be a good example for missing
|
||||
things like application icon and so on...)
|
||||
- Enable MMX/SSE/SSE2 acceleration functions
|
||||
- Rewrite CDROM support using DOS Ioctl for better support.
|
||||
|
||||
|
||||
|
||||
7. Contacts
|
||||
-----------
|
||||
|
||||
You can contact the developers for bugs:
|
||||
|
||||
Area Developer email
|
||||
General (Audio/Video/System) Doodle doodle@scenergy.dfmk.hu
|
||||
CDROM and Joystick Caetano daniel@caetano.eng.br
|
||||
|
||||
Notice however that SDL/2 is 'in development' stage so ... if you want to help,
|
||||
please, be our guest and contact us!
|
||||
|
33
Watcom.mif
Normal file
33
Watcom.mif
Normal file
|
@ -0,0 +1,33 @@
|
|||
#=============================================================================
|
||||
# This file contains the common includes for the
|
||||
# Watcom makefiles to build SDL.DLL for OS/2
|
||||
#
|
||||
#
|
||||
#=============================================================================
|
||||
|
||||
# Create debug build or not?
|
||||
#debug_build=defined
|
||||
|
||||
# Special flags for building SDL
|
||||
SDLCFlags = -dBUILD_SDL -dCHECK_LEAKS
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
|
||||
!ifdef debug_build
|
||||
debugflags = -d2 -dDEBUG_BUILD
|
||||
!else
|
||||
debugflags =
|
||||
!endif
|
||||
|
||||
cflags = -zq $(debugflags) -bd -bm -bt=OS2 -5s -fpi -sg -otexan -wx -ei $(SDLCFlags) $(ExtraCFlags)
|
||||
|
||||
.extensions:
|
||||
.extensions: .lib .dll .obj .c .asm
|
||||
|
||||
.c.obj : .AUTODEPEND
|
||||
wcc386 $[* $(cflags)
|
||||
|
||||
.asm.obj : .AUTODEPEND
|
||||
nasm -t -O2 -f obj -I$(%include) $[*.asm
|
|
@ -55,9 +55,8 @@ static char rcsid =
|
|||
(defined(__arm__) || defined(__thumb__)) || \
|
||||
(defined(__sh__) || defined(__sh64__)) || \
|
||||
(defined(__mips__) && defined(__MIPSEL__)) || \
|
||||
defined(__SYMBIAN32__) || \
|
||||
defined(__x86_64__) || \
|
||||
defined(__LITTLE_ENDIAN__)
|
||||
defined(__SYMBIAN32__) || defined(__x86_64__) || \
|
||||
defined(__OS2__) || defined(__LITTLE_ENDIAN__)
|
||||
#define SDL_BYTEORDER SDL_LIL_ENDIAN
|
||||
#else
|
||||
#define SDL_BYTEORDER SDL_BIG_ENDIAN
|
||||
|
|
|
@ -50,7 +50,50 @@ struct SDL_Thread;
|
|||
typedef struct SDL_Thread SDL_Thread;
|
||||
|
||||
/* Create a thread */
|
||||
#ifdef __OS2__
|
||||
/*
|
||||
We compile SDL into a DLL on OS/2. This means, that it's the DLL which
|
||||
creates a new thread for the calling process with the SDL_CreateThread()
|
||||
API. There is a problem with this, that only the RTL of the SDL.DLL will
|
||||
be initialized for those threads, and not the RTL of the calling application!
|
||||
To solve this, we make a little hack here.
|
||||
We'll always use the caller's _beginthread() and _endthread() APIs to
|
||||
start a new thread. This way, it it's the SDL.DLL which uses this API,
|
||||
then the RTL of SDL.DLL will be used to create the new thread, and if it's
|
||||
the application, then the RTL of the application will be used.
|
||||
So, in short:
|
||||
Always use the _beginthread() and _endthread() of the calling runtime library!
|
||||
*/
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
#include <process.h> // This has _beginthread() and _endthread() defined!
|
||||
#endif
|
||||
#ifdef __EMX__
|
||||
#include <stdlib.h> // This has _beginthread() and _endthread() defined, if -Zmt flag is used!
|
||||
#endif
|
||||
|
||||
typedef Uint32 SDLCALL (*pfnSDL_CurrentBeginThread)(void (*pfnThreadFn)(void *), Uint32 uiStackSize, void *pParam);
|
||||
typedef void SDLCALL (*pfnSDL_CurrentEndThread)(void);
|
||||
|
||||
extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread_Core(int (*fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
|
||||
|
||||
// Disable warnings about unreferenced symbol!
|
||||
#pragma disable_message (202)
|
||||
static Uint32 SDLCALL SDL_CurrentBeginThread(void (*pfnThreadFn)(void *), Uint32 uiStackSize, void *pParam)
|
||||
{
|
||||
return _beginthread(pfnThreadFn, NULL, uiStackSize, pParam);
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_CurrentEndThread(void)
|
||||
{
|
||||
_endthread();
|
||||
}
|
||||
|
||||
#define SDL_CreateThread(fn, data) SDL_CreateThread_Core(fn, data, SDL_CurrentBeginThread, SDL_CurrentEndThread)
|
||||
|
||||
#else
|
||||
extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data);
|
||||
#endif
|
||||
|
||||
/* Get the 32-bit thread identifier for the current thread */
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_ThreadID(void);
|
||||
|
|
|
@ -57,7 +57,7 @@ typedef signed int Sint32;
|
|||
#if !defined(__STRICT_ANSI__)
|
||||
#ifdef __osf__ /* Tru64 */
|
||||
#define SDL_HAS_64BIT_TYPE long
|
||||
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DECC)
|
||||
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DECC) || defined(__WATCOMC__)
|
||||
#define SDL_HAS_64BIT_TYPE long long
|
||||
#elif defined(_MSC_VER) /* VC++ */
|
||||
#define SDL_HAS_64BIT_TYPE __int64
|
||||
|
|
|
@ -56,8 +56,20 @@
|
|||
# define DECLSPEC __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef __OS2__
|
||||
# ifdef __WATCOMC__
|
||||
# ifdef BUILD_SDL
|
||||
# define DECLSPEC __declspec(dllexport)
|
||||
# else
|
||||
# define DECLSPEC
|
||||
# endif
|
||||
# else
|
||||
# define DECLSPEC
|
||||
# endif
|
||||
# else
|
||||
# define DECLSPEC
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -66,8 +78,14 @@
|
|||
#if defined(WIN32) && !defined(__GNUC__)
|
||||
#define SDLCALL __cdecl
|
||||
#else
|
||||
#ifdef __OS2__
|
||||
/* But on OS/2, we use the _System calling convention */
|
||||
/* to be compatible with every compiler */
|
||||
#define SDLCALL _System
|
||||
#else
|
||||
#define SDLCALL
|
||||
#endif
|
||||
#endif
|
||||
#endif /* SDLCALL */
|
||||
|
||||
/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */
|
||||
|
|
16
setvars.cmd
Normal file
16
setvars.cmd
Normal file
|
@ -0,0 +1,16 @@
|
|||
@ECHO OFF
|
||||
SET WATCOM=d:\watcom
|
||||
SET NASM=d:\nasm
|
||||
SET OS2TK=d:\os2tk45
|
||||
SET FSLIB=d:\watcom\projects\FSLib
|
||||
|
||||
SET PATH=%WATCOM%\BINP;%WATCOM%\BINW;%os2tk%\bin;%NASM%;%PATH%
|
||||
SET INCLUDE=%WATCOM%\H;%WATCOM%\H\OS2
|
||||
SET FINCLUDE=%WATCOM%\SRC\FORTRAN
|
||||
SET EDPATH=%WATCOM%\EDDAT
|
||||
SET HELP=%WATCOM%\BINP\HELP;%HELP%
|
||||
SET BOOKSHELF=%WATCOM%\BINP\HELP;%BOOKSHELF%
|
||||
SET BEGINLIBPATH=%WATCOM%\BINP\DLL
|
||||
|
||||
cmd
|
||||
|
132
src/Makefile.wat
Normal file
132
src/Makefile.wat
Normal file
|
@ -0,0 +1,132 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
#
|
||||
#=============================================================================
|
||||
|
||||
dllname=SDL
|
||||
|
||||
audioobjs = audio\SDL_audio.obj audio\SDL_audiocvt.obj audio\SDL_audiomem.obj &
|
||||
audio\SDL_mixer.obj audio\SDL_mixer_MMX_VC.obj audio\SDL_wave.obj &
|
||||
audio\SDL_dart.obj
|
||||
cdromobjs = cdrom\SDL_cdrom.obj cdrom\SDL_syscdrom.obj
|
||||
cpuinfoobjs = cpuinfo\SDL_cpuinfo.obj
|
||||
endianobjs = endian\SDL_endian.obj
|
||||
eventsobjs = events\SDL_active.obj events\SDL_events.obj events\SDL_expose.obj &
|
||||
events\SDL_keyboard.obj events\SDL_mouse.obj events\SDL_quit.obj &
|
||||
events\SDL_resize.obj
|
||||
fileobjs = file\SDL_rwops.obj
|
||||
hermesobjs = hermes\mmx_main.obj hermes\mmxp2_32.obj hermes\x86_main.obj &
|
||||
hermes\x86p_16.obj hermes\x86p_32.obj
|
||||
joystickobjs = joystick\SDL_joystick.obj joystick\SDL_sysjoystick.obj
|
||||
threadobjs = thread\SDL_thread.obj thread\SDL_sysmutex.obj &
|
||||
thread\SDL_syssem.obj thread\SDL_systhread.obj &
|
||||
thread\SDL_syscond.obj
|
||||
timerobjs = timer\SDL_timer.obj timer\SDL_systimer.obj
|
||||
videoobjs = video\SDL_blit.obj video\SDL_blit_0.obj video\SDL_blit_1.obj &
|
||||
video\SDL_blit_A.obj video\SDL_blit_N.obj video\SDL_bmp.obj &
|
||||
video\SDL_cursor.obj video\SDL_gamma.obj video\SDL_pixels.obj &
|
||||
video\SDL_RLEaccel.obj video\SDL_stretch.obj video\SDL_surface.obj &
|
||||
video\SDL_video.obj video\SDL_yuv.obj video\SDL_yuv_mmx.obj &
|
||||
video\SDL_yuv_sw.obj video\SDL_os2fslib.obj
|
||||
|
||||
object_files= SDL.obj SDL_error.obj SDL_fatal.obj SDL_getenv.obj &
|
||||
SDL_loadso.obj $(audioobjs) $(cpuinfoobjs) $(endianobjs) &
|
||||
$(eventsobjs) $(fileobjs) $(joystickobjs) &
|
||||
$(threadobjs) $(timerobjs) $(videoobjs) $(cdromobjs)
|
||||
|
||||
|
||||
# Extra stuffs to pass to C compiler:
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\Watcom.mif
|
||||
|
||||
.before
|
||||
@set include=$(%os2tk)\h;$(%include);../include;./thread;./thread/os2;./video;./cdrom;./cdrom/os2;./joystick;./joystick/os2;
|
||||
|
||||
all : check_subdir_objects $(dllname).dll $(dllname).lib
|
||||
|
||||
$(dllname).dll : $(dllname).lnk $(object_files)
|
||||
wlink @$(dllname)
|
||||
|
||||
check_subdir_objects: .always .symbolic
|
||||
@cd audio
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\cdrom
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\cpuinfo
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\endian
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\events
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\file
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\joystick
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\thread
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\timer
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..\video
|
||||
@wmake -h -f Makefile.wat
|
||||
@cd ..
|
||||
|
||||
$(dllname).lnk :
|
||||
@echo Creating linker file ($(dllname).lnk)...
|
||||
@echo $#============================================================================= >$^@
|
||||
@echo $# This is a linker file to build SDL.DLL for OS/2 >>$^@
|
||||
@echo $# >>$^@
|
||||
@echo $# Generated automatically by Makefile.wat >>$^@
|
||||
@echo $#============================================================================= >>$^@
|
||||
@echo SYSTEM 386 LX DLL INITINSTANCE TERMINSTANCE >>$^@
|
||||
@echo NAME $^& >>$^@
|
||||
@for %i in ($(object_files)) do @echo FILE %i >>$^@
|
||||
@echo LIBPATH %os2tk%\lib >>$^@
|
||||
@echo LIBPATH %fslib% >>$^@
|
||||
@echo LIB mmpm2.lib >>$^@
|
||||
@echo LIB fslib.lib >>$^@
|
||||
@echo OPTION QUIET >>$^@
|
||||
@echo OPTION MAP=$^&.map >>$^@
|
||||
@echo OPTION DESCRIPTION 'Simple DirectMedia Layer v1.2.7' >>$^@
|
||||
@echo OPTION ELIMINATE >>$^@
|
||||
@echo OPTION MANYAUTODATA >>$^@
|
||||
@echo OPTION OSNAME='OS/2 and eComStation' >>$^@
|
||||
@echo OPTION SHOWDEAD >>$^@
|
||||
@echo Linker file created!
|
||||
|
||||
$(dllname).lib : $(dllname).dll
|
||||
implib $(dllname).lib $(dllname).dll
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.dll del *.dll
|
||||
@if exist *.lib del *.lib
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.lnk del *.lnk
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
||||
@cd audio
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\cdrom
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\cpuinfo
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\endian
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\events
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\file
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\joystick
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\thread
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\timer
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..\video
|
||||
@wmake -h -f Makefile.wat clean
|
||||
@cd ..
|
87
src/SDL.c
87
src/SDL.c
|
@ -220,15 +220,25 @@ Uint32 SDL_WasInit(Uint32 flags)
|
|||
void SDL_Quit(void)
|
||||
{
|
||||
/* Quit all subsystems */
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_Quit] : Enter! Calling QuitSubSystem()\n"); fflush(stdout);
|
||||
#endif
|
||||
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
|
||||
|
||||
#ifdef CHECK_LEAKS
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_Quit] : CHECK_LEAKS\n"); fflush(stdout);
|
||||
#endif
|
||||
|
||||
/* Print the number of surfaces not freed */
|
||||
if ( surfaces_allocated != 0 ) {
|
||||
fprintf(stderr, "SDL Warning: %d SDL surfaces extant\n",
|
||||
surfaces_allocated);
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_Quit] : SDL_UninstallParachute()\n"); fflush(stdout);
|
||||
#endif
|
||||
|
||||
/* Uninstall any parachute signal handlers */
|
||||
SDL_UninstallParachute();
|
||||
|
@ -236,6 +246,10 @@ void SDL_Quit(void)
|
|||
#if !defined(DISABLE_THREADS) && defined(ENABLE_PTH)
|
||||
pth_kill();
|
||||
#endif
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_Quit] : Returning!\n"); fflush(stdout);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Return the library version number */
|
||||
|
@ -244,6 +258,7 @@ const SDL_version * SDL_Linked_Version(void)
|
|||
return(&version);
|
||||
}
|
||||
|
||||
#ifndef __OS2__
|
||||
#if defined(_WIN32_WCE) || (defined(__WATCOMC__) && defined(BUILD_DLL))
|
||||
/* Need to include DllMain() on Windows CE and Watcom C for some reason.. */
|
||||
#include <windows.h>
|
||||
|
@ -262,3 +277,75 @@ BOOL APIENTRY DllMain( HANDLE hModule,
|
|||
return TRUE;
|
||||
}
|
||||
#endif /* _WIN32_WCE and building DLL with Watcom C */
|
||||
#else
|
||||
// Building for OS/2
|
||||
#ifdef __WATCOMC__
|
||||
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSEXCEPTIONS
|
||||
#include <os2.h>
|
||||
|
||||
// Exception handler to prevent the Audio thread hanging, making a zombie process!
|
||||
ULONG _System SDL_Main_ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
|
||||
PEXCEPTIONREGISTRATIONRECORD pERegRec,
|
||||
PCONTEXTRECORD pCtxRec,
|
||||
PVOID p)
|
||||
{
|
||||
if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
|
||||
return XCPT_CONTINUE_SEARCH;
|
||||
if (pERepRec->fHandlerFlags & EH_UNWINDING)
|
||||
return XCPT_CONTINUE_SEARCH;
|
||||
if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
|
||||
return XCPT_CONTINUE_SEARCH;
|
||||
|
||||
// Do cleanup at every fatal exception!
|
||||
if (((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION) &&
|
||||
(pERepRec->ExceptionNum != XCPT_BREAKPOINT) &&
|
||||
(pERepRec->ExceptionNum != XCPT_SINGLE_STEP)
|
||||
)
|
||||
{
|
||||
if (SDL_initialized & SDL_INIT_AUDIO)
|
||||
{
|
||||
// This removes the zombie audio thread in case of emergency.
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_Main_ExceptionHandler] : Calling SDL_CloseAudio()!\n");
|
||||
#endif
|
||||
SDL_CloseAudio();
|
||||
}
|
||||
}
|
||||
return (XCPT_CONTINUE_SEARCH);
|
||||
}
|
||||
|
||||
|
||||
EXCEPTIONREGISTRATIONRECORD SDL_Main_xcpthand = {0, SDL_Main_ExceptionHandler};
|
||||
|
||||
// The main DLL entry for DLL Initialization and Uninitialization:
|
||||
unsigned _System LibMain(unsigned hmod, unsigned termination)
|
||||
{
|
||||
if (termination)
|
||||
{
|
||||
#ifdef DEBUG_BUILD
|
||||
// printf("[SDL DLL Unintialization] : Removing exception handler\n");
|
||||
#endif
|
||||
DosUnsetExceptionHandler(&SDL_Main_xcpthand);
|
||||
return 1;
|
||||
} else
|
||||
{
|
||||
#ifdef DEBUG_BUILD
|
||||
// Make stdout and stderr unbuffered!
|
||||
setbuf(stdout, NULL);
|
||||
setbuf(stderr, NULL);
|
||||
#endif
|
||||
// Fire up exception handler
|
||||
#ifdef DEBUG_BUILD
|
||||
// printf("[SDL DLL Initialization] : Setting exception handler\n");
|
||||
#endif
|
||||
// Set exception handler
|
||||
DosSetExceptionHandler(&SDL_Main_xcpthand);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,8 @@ static char rcsid =
|
|||
# include "loadso/beos/SDL_loadso.c"
|
||||
#elif defined(__MINT__) && defined(ENABLE_LDG)
|
||||
# include "loadso/mint/SDL_loadso.c"
|
||||
#elif defined(__OS2__)
|
||||
# include "loadso/os2/SDL_loadso.c"
|
||||
#else
|
||||
# include "loadso/dummy/SDL_loadso.c"
|
||||
#endif /* system type */
|
||||
|
|
27
src/audio/Makefile.wat
Normal file
27
src/audio/Makefile.wat
Normal file
|
@ -0,0 +1,27 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for DART (audio support)
|
||||
#=============================================================================
|
||||
|
||||
object_files= SDL_audio.obj SDL_audiocvt.obj SDL_audiomem.obj SDL_mixer.obj SDL_mixer_MMX_VC.obj SDL_wave.obj SDL_dart.obj
|
||||
ExtraCFlags=-dUSE_ASM_MIXER_VC -dUSE_DOSSETPRIORITY
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;./dart
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
SDL_dart.obj: .AUTODEPEND
|
||||
wcc386 dart\SDL_dart.c $(cflags)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
|
@ -38,6 +38,12 @@ static char rcsid =
|
|||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#ifdef __OS2__
|
||||
// We'll need the DosSetPriority() API!
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
#endif
|
||||
|
||||
/* Available audio drivers */
|
||||
static AudioBootStrap *bootstrap[] = {
|
||||
#ifdef OPENBSD_AUDIO_SUPPORT
|
||||
|
@ -107,6 +113,9 @@ static AudioBootStrap *bootstrap[] = {
|
|||
#endif
|
||||
#ifdef DRENDERER_SUPPORT
|
||||
&DRENDERER_bootstrap,
|
||||
#endif
|
||||
#ifdef __OS2__
|
||||
&DART_bootstrap,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
@ -181,6 +190,16 @@ int SDL_RunAudio(void *audiop)
|
|||
D(bug("Entering audio loop...\n"));
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__
|
||||
// Increase the priority of this thread to make sure that
|
||||
// the audio will be continuous all the time!
|
||||
#ifdef USE_DOSSETPRIORITY
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID());
|
||||
#endif
|
||||
DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Loop, filling the audio buffers */
|
||||
while ( audio->enabled ) {
|
||||
|
@ -248,6 +267,11 @@ int SDL_RunAudio(void *audiop)
|
|||
|
||||
D(bug("CloseAudio..Done, subtask exiting...\n"));
|
||||
audio_configured = 0;
|
||||
#endif
|
||||
#ifdef __OS2__
|
||||
#ifdef DEBUG_BUILD
|
||||
printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
|
||||
#endif
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
// Mixing for 16 bit signed buffers
|
||||
////////////////////////////////////////////////
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
void SDL_MixAudio_MMX_S16_VC(char* dst,char* src,unsigned int nSize,int volume)
|
||||
{
|
||||
|
@ -41,7 +43,9 @@ void SDL_MixAudio_MMX_S16_VC(char* dst,char* src,unsigned int nSize,int volume)
|
|||
psllq mm0, 16 //$16,%%mm0
|
||||
por mm0, mm1 //%%mm1,%%mm0 // mm0 = vol|vol|vol|vol
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
align 16
|
||||
#endif
|
||||
mixloopS16:
|
||||
movq mm1, [esi] //(%%esi),%%mm1\n" // mm1 = a|b|c|d
|
||||
movq mm2, mm1 //%%mm1,%%mm2\n" // mm2 = a|b|c|d
|
||||
|
@ -121,7 +125,9 @@ void SDL_MixAudio_MMX_S8_VC(char* dst,char* src,unsigned int nSize,int volume)
|
|||
cmp ebx, 0 //$0,%%ebx
|
||||
je endS8
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
align 16
|
||||
#endif
|
||||
mixloopS8:
|
||||
pxor mm2, mm2 //%%mm2,%%mm2 // mm2 = 0
|
||||
movq mm1, [esi] //(%%esi),%%mm1 // mm1 = a|b|c|d|e|f|g|h
|
||||
|
|
|
@ -172,6 +172,9 @@ extern AudioBootStrap DRENDERER_bootstrap;
|
|||
#ifdef MMEAUDIO_SUPPORT
|
||||
extern AudioBootStrap MMEAUDIO_bootstrap;
|
||||
#endif
|
||||
#ifdef __OS2__
|
||||
extern AudioBootStrap DART_bootstrap;
|
||||
#endif
|
||||
|
||||
/* This is the current audio device */
|
||||
extern SDL_AudioDevice *current_audio;
|
||||
|
|
436
src/audio/dart/SDL_dart.c
Normal file
436
src/audio/dart/SDL_dart.c
Normal file
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_types.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_dart.h"
|
||||
|
||||
// Buffer states:
|
||||
#define BUFFER_EMPTY 0
|
||||
#define BUFFER_USED 1
|
||||
|
||||
typedef struct _tMixBufferDesc {
|
||||
int iBufferUsage; // BUFFER_EMPTY or BUFFER_USED
|
||||
SDL_AudioDevice *pSDLAudioDevice;
|
||||
} tMixBufferDesc, *pMixBufferDesc;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// DARTEventFunc
|
||||
//
|
||||
// This function is called by DART, when an event occures, like end of
|
||||
// playback of a buffer, etc...
|
||||
//---------------------------------------------------------------------
|
||||
LONG APIENTRY DARTEventFunc(ULONG ulStatus,
|
||||
PMCI_MIX_BUFFER pBuffer,
|
||||
ULONG ulFlags)
|
||||
{
|
||||
if (ulFlags && MIX_WRITE_COMPLETE)
|
||||
{ // Playback of buffer completed!
|
||||
|
||||
// Get pointer to buffer description
|
||||
pMixBufferDesc pBufDesc;
|
||||
|
||||
if (pBuffer)
|
||||
{
|
||||
pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm;
|
||||
|
||||
if (pBufDesc)
|
||||
{
|
||||
SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice;
|
||||
// Set the buffer to be empty
|
||||
pBufDesc->iBufferUsage = BUFFER_EMPTY;
|
||||
// And notify DART feeder thread that it will have to work a bit.
|
||||
if (pSDLAudioDevice)
|
||||
DosPostEventSem(pSDLAudioDevice->hidden->hevAudioBufferPlayed);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int DART_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
MCI_AMP_OPEN_PARMS AmpOpenParms;
|
||||
MCI_GENERIC_PARMS GenericParms;
|
||||
int iDeviceOrd = 0; // Default device to be used
|
||||
int bOpenShared = 1; // Try opening it shared
|
||||
int iBits = 16; // Default is 16 bits signed
|
||||
int iFreq = 44100; // Default is 44KHz
|
||||
int iChannels = 2; // Default is 2 channels (Stereo)
|
||||
int iNumBufs = 2; // Number of audio buffers: 2
|
||||
int iBufSize;
|
||||
int iOpenMode;
|
||||
int iSilence;
|
||||
int rc;
|
||||
|
||||
// First thing is to try to open a given DART device!
|
||||
memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
|
||||
// pszDeviceType should contain the device type in low word, and device ordinal in high word!
|
||||
AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16));
|
||||
|
||||
iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID;
|
||||
if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE;
|
||||
|
||||
rc = mciSendCommand( 0, MCI_OPEN,
|
||||
iOpenMode,
|
||||
(PVOID) &AmpOpenParms, 0);
|
||||
if (rc!=MCIERR_SUCCESS) // No audio available??
|
||||
return (-1);
|
||||
// Save the device ID we got from DART!
|
||||
// We will use this in the next calls!
|
||||
iDeviceOrd = AmpOpenParms.usDeviceID;
|
||||
|
||||
// Determine the audio parameters from the AudioSpec
|
||||
switch ( spec->format & 0xFF )
|
||||
{
|
||||
case 8:
|
||||
/* Unsigned 8 bit audio data */
|
||||
spec->format = AUDIO_U8;
|
||||
iSilence = 0x80;
|
||||
iBits = 8;
|
||||
break;
|
||||
case 16:
|
||||
/* Signed 16 bit audio data */
|
||||
spec->format = AUDIO_S16;
|
||||
iSilence = 0x00;
|
||||
iBits = 16;
|
||||
break;
|
||||
default:
|
||||
// Close DART, and exit with error code!
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("Unsupported audio format");
|
||||
return(-1);
|
||||
}
|
||||
iFreq = spec->freq;
|
||||
iChannels = spec->channels;
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
iBufSize = spec->size;
|
||||
|
||||
// Now query this device if it supports the given freq/bits/channels!
|
||||
memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS));
|
||||
_this->hidden->MixSetupParms.ulBitsPerSample = iBits;
|
||||
_this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||
_this->hidden->MixSetupParms.ulSamplesPerSec = iFreq;
|
||||
_this->hidden->MixSetupParms.ulChannels = iChannels;
|
||||
_this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY;
|
||||
_this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
|
||||
_this->hidden->MixSetupParms.pmixEvent = DARTEventFunc;
|
||||
rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
|
||||
&(_this->hidden->MixSetupParms), 0);
|
||||
if (rc!=MCIERR_SUCCESS)
|
||||
{ // The device cannot handle this format!
|
||||
// Close DART, and exit with error code!
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("Audio device doesn't support requested audio format");
|
||||
return(-1);
|
||||
}
|
||||
// The device can handle this format, so initialize!
|
||||
rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_INIT,
|
||||
&(_this->hidden->MixSetupParms), 0);
|
||||
if (rc!=MCIERR_SUCCESS)
|
||||
{ // The device could not be opened!
|
||||
// Close DART, and exit with error code!
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("Audio device could not be set up");
|
||||
return(-1);
|
||||
}
|
||||
// Ok, the device is initialized.
|
||||
// Now we should allocate buffers. For this, we need a place where
|
||||
// the buffer descriptors will be:
|
||||
_this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs);
|
||||
if (!(_this->hidden->pMixBuffers))
|
||||
{ // Not enough memory!
|
||||
// Close DART, and exit with error code!
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("Not enough memory for audio buffer descriptors");
|
||||
return(-1);
|
||||
}
|
||||
// Now that we have the place for buffer list, we can ask DART for the
|
||||
// buffers!
|
||||
_this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers
|
||||
_this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size
|
||||
_this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list
|
||||
// Allocate buffers!
|
||||
rc = mciSendCommand(iDeviceOrd, MCI_BUFFER,
|
||||
MCI_WAIT | MCI_ALLOCATE_MEMORY,
|
||||
&(_this->hidden->BufferParms), 0);
|
||||
if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0))
|
||||
{ // Could not allocate memory!
|
||||
// Close DART, and exit with error code!
|
||||
free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("DART could not allocate buffers");
|
||||
return(-1);
|
||||
}
|
||||
// Ok, we have all the buffers allocated, let's mark them!
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<iNumBufs; i++)
|
||||
{
|
||||
pMixBufferDesc pBufferDesc = (pMixBufferDesc) malloc(sizeof(tMixBufferDesc));;
|
||||
// Check if this buffer was really allocated by DART
|
||||
if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc))
|
||||
{ // Wrong buffer!
|
||||
// Close DART, and exit with error code!
|
||||
// Free buffer descriptions
|
||||
{ int j;
|
||||
for (j=0; j<i; j++) free((void *)(_this->hidden->pMixBuffers[j].ulUserParm));
|
||||
}
|
||||
// and cleanup
|
||||
mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
|
||||
free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("Error at internal buffer check");
|
||||
return(-1);
|
||||
}
|
||||
pBufferDesc->iBufferUsage = BUFFER_EMPTY;
|
||||
pBufferDesc->pSDLAudioDevice = _this;
|
||||
|
||||
_this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize;
|
||||
_this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer
|
||||
_this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of
|
||||
// audio data, but as we will continously send
|
||||
// audio data, there will be no end.:)
|
||||
memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize);
|
||||
}
|
||||
}
|
||||
_this->hidden->iNextFreeBuffer = 0;
|
||||
_this->hidden->iLastPlayedBuf = -1;
|
||||
// Create event semaphore
|
||||
if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR)
|
||||
{
|
||||
// Could not create event semaphore!
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<iNumBufs; i++) free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
|
||||
}
|
||||
mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
|
||||
free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
|
||||
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
|
||||
SDL_SetError("Could not create event semaphore");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Store the new settings in global variables
|
||||
_this->hidden->iCurrDeviceOrd = iDeviceOrd;
|
||||
_this->hidden->iCurrFreq = iFreq;
|
||||
_this->hidden->iCurrBits = iBits;
|
||||
_this->hidden->iCurrChannels = iChannels;
|
||||
_this->hidden->iCurrNumBufs = iNumBufs;
|
||||
_this->hidden->iCurrBufSize = iBufSize;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DART_ThreadInit(_THIS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
void DART_WaitAudio(_THIS)
|
||||
{
|
||||
int i;
|
||||
pMixBufferDesc pBufDesc;
|
||||
ULONG ulPostCount;
|
||||
|
||||
DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
|
||||
// If there is already an empty buffer, then return now!
|
||||
for (i=0; i<_this->hidden->iCurrNumBufs; i++)
|
||||
{
|
||||
pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm;
|
||||
if (pBufDesc->iBufferUsage == BUFFER_EMPTY)
|
||||
return;
|
||||
}
|
||||
// If there is no empty buffer, wait for one to be empty!
|
||||
DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important!
|
||||
return;
|
||||
}
|
||||
|
||||
void DART_PlayAudio(_THIS)
|
||||
{
|
||||
int iFreeBuf = _this->hidden->iNextFreeBuffer;
|
||||
pMixBufferDesc pBufDesc;
|
||||
|
||||
pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm;
|
||||
pBufDesc->iBufferUsage = BUFFER_USED;
|
||||
// Send it to DART to be queued
|
||||
_this->hidden->MixSetupParms.pmixWrite(_this->hidden->MixSetupParms.ulMixHandle,
|
||||
&(_this->hidden->pMixBuffers[iFreeBuf]), 1);
|
||||
|
||||
_this->hidden->iLastPlayedBuf = iFreeBuf;
|
||||
iFreeBuf = (iFreeBuf+1) % _this->hidden->iCurrNumBufs;
|
||||
_this->hidden->iNextFreeBuffer = iFreeBuf;
|
||||
}
|
||||
|
||||
Uint8 *DART_GetAudioBuf(_THIS)
|
||||
{
|
||||
int iFreeBuf;
|
||||
Uint8 *pResult;
|
||||
pMixBufferDesc pBufDesc;
|
||||
|
||||
if (_this)
|
||||
{
|
||||
if (_this->hidden)
|
||||
{
|
||||
iFreeBuf = _this->hidden->iNextFreeBuffer;
|
||||
pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm;
|
||||
|
||||
if (pBufDesc)
|
||||
{
|
||||
if (pBufDesc->iBufferUsage == BUFFER_EMPTY)
|
||||
{
|
||||
pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer;
|
||||
return pResult;
|
||||
}
|
||||
} else
|
||||
printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", pBufDesc);
|
||||
} else
|
||||
printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", _this->hidden);
|
||||
} else
|
||||
printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DART_WaitDone(_THIS)
|
||||
{
|
||||
pMixBufferDesc pBufDesc;
|
||||
ULONG ulPostCount;
|
||||
APIRET rc;
|
||||
|
||||
pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm;
|
||||
rc = NO_ERROR;
|
||||
while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc==NO_ERROR))
|
||||
{
|
||||
DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
|
||||
rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important!
|
||||
}
|
||||
}
|
||||
|
||||
void DART_CloseAudio(_THIS)
|
||||
{
|
||||
MCI_GENERIC_PARMS GenericParms;
|
||||
int rc;
|
||||
|
||||
// Stop DART playback
|
||||
rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, &GenericParms, 0);
|
||||
if (rc!=MCIERR_SUCCESS)
|
||||
{
|
||||
#ifdef SFX_DEBUG_BUILD
|
||||
printf("Could not stop DART playback!\n");
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close event semaphore
|
||||
DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
|
||||
|
||||
// Free memory of buffer descriptions
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<_this->hidden->iCurrNumBufs; i++) free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
|
||||
}
|
||||
|
||||
// Deallocate buffers
|
||||
rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
|
||||
|
||||
// Free bufferlist
|
||||
free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
|
||||
|
||||
// Close dart
|
||||
rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, &(GenericParms), 0);
|
||||
}
|
||||
|
||||
/* Audio driver bootstrap functions */
|
||||
|
||||
int Audio_Available(void)
|
||||
{
|
||||
return(1);
|
||||
}
|
||||
|
||||
void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this )
|
||||
{
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
if ( this )
|
||||
free(this);
|
||||
return(0);
|
||||
}
|
||||
memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = DART_OpenAudio;
|
||||
this->ThreadInit = DART_ThreadInit;
|
||||
this->WaitAudio = DART_WaitAudio;
|
||||
this->PlayAudio = DART_PlayAudio;
|
||||
this->GetAudioBuf = DART_GetAudioBuf;
|
||||
this->WaitDone = DART_WaitDone;
|
||||
this->CloseAudio = DART_CloseAudio;
|
||||
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap DART_bootstrap = {
|
||||
"dart", "OS/2 Direct Audio RouTines (DART)",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
67
src/audio/dart/SDL_dart.h
Normal file
67
src/audio/dart/SDL_dart.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
#ifndef _SDL_lowaudio_h
|
||||
#define _SDL_lowaudio_h
|
||||
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#define INCL_TYPES
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSRESOURCES
|
||||
#define INCL_DOSMISC
|
||||
#define INCL_DOSERRORS
|
||||
|
||||
#define INCL_OS2MM
|
||||
#define INCL_MMIOOS2
|
||||
#define INCL_MCIOS2
|
||||
#include <os2.h>
|
||||
#include <os2me.h> // DART stuff and MMIO stuff
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *_this
|
||||
|
||||
/* The DirectSound objects */
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
int iCurrDeviceOrd;
|
||||
int iCurrFreq;
|
||||
int iCurrBits;
|
||||
int iCurrChannels;
|
||||
int iCurrNumBufs;
|
||||
int iCurrBufSize;
|
||||
|
||||
int iLastPlayedBuf;
|
||||
int iNextFreeBuffer;
|
||||
|
||||
MCI_BUFFER_PARMS BufferParms; // Sound buffer parameters
|
||||
MCI_MIX_BUFFER *pMixBuffers; // Sound buffers
|
||||
MCI_MIXSETUP_PARMS MixSetupParms; // Mixer setup parameters
|
||||
HEV hevAudioBufferPlayed; // Event semaphore to indicate that an audio buffer has been played by DART
|
||||
};
|
||||
|
||||
#endif /* _SDL_lowaudio_h */
|
30
src/cdrom/Makefile.wat
Normal file
30
src/cdrom/Makefile.wat
Normal file
|
@ -0,0 +1,30 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for OS/2 System CDROM support
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_syscdrom.obj SDL_cdrom.obj
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
SDL_syscdrom.obj : .AUTODEPEND
|
||||
wcc386 os2\SDL_syscdrom.c $(cflags)
|
||||
|
||||
SDL_cdrom.obj : .AUTODEPEND
|
||||
wcc386 SDL_cdrom.c $(cflags)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
399
src/cdrom/os2/SDL_syscdrom.c
Normal file
399
src/cdrom/os2/SDL_syscdrom.c
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* Functions for system-level CD-ROM audio control */
|
||||
|
||||
#define INCL_MCIOS2
|
||||
#include <os2.h>
|
||||
#include <os2me.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_cdrom.h"
|
||||
#include "SDL_syscdrom.h"
|
||||
|
||||
/* Size of MCI result buffer (in bytes) */
|
||||
#define MCI_CMDRETBUFSIZE 128
|
||||
|
||||
/* The maximum number of CD-ROM drives we'll detect */
|
||||
#define MAX_DRIVES 16
|
||||
|
||||
/* A list of available CD-ROM drives */
|
||||
static char *SDL_cdlist[MAX_DRIVES];
|
||||
//static dev_t SDL_cdmode[MAX_DRIVES];
|
||||
|
||||
/* The system-dependent CD control functions */
|
||||
static const char *SDL_SYS_CDName(int drive);
|
||||
static int SDL_SYS_CDOpen(int drive);
|
||||
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
|
||||
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
|
||||
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
|
||||
static int SDL_SYS_CDPause(SDL_CD *cdrom);
|
||||
static int SDL_SYS_CDResume(SDL_CD *cdrom);
|
||||
static int SDL_SYS_CDStop(SDL_CD *cdrom);
|
||||
static int SDL_SYS_CDEject(SDL_CD *cdrom);
|
||||
static void SDL_SYS_CDClose(SDL_CD *cdrom);
|
||||
|
||||
/* MCI Timing Functions */
|
||||
#define MCI_MMTIMEPERSECOND 3000
|
||||
#define FRAMESFROMMM(mmtime) (((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND)
|
||||
|
||||
|
||||
/* Ready for MCI CDAudio Devices */
|
||||
int SDL_SYS_CDInit(void)
|
||||
{
|
||||
int i; /* generig counter */
|
||||
MCI_SYSINFO_PARMS msp; /* Structure to MCI SysInfo parameters */
|
||||
CHAR SysInfoRet[MCI_CMDRETBUFSIZE]; /* Buffer for MCI Command result */
|
||||
|
||||
/* Fill in our driver capabilities */
|
||||
SDL_CDcaps.Name = SDL_SYS_CDName;
|
||||
SDL_CDcaps.Open = SDL_SYS_CDOpen;
|
||||
SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
|
||||
SDL_CDcaps.Status = SDL_SYS_CDStatus;
|
||||
SDL_CDcaps.Play = SDL_SYS_CDPlay;
|
||||
SDL_CDcaps.Pause = SDL_SYS_CDPause;
|
||||
SDL_CDcaps.Resume = SDL_SYS_CDResume;
|
||||
SDL_CDcaps.Stop = SDL_SYS_CDStop;
|
||||
SDL_CDcaps.Eject = SDL_SYS_CDEject;
|
||||
SDL_CDcaps.Close = SDL_SYS_CDClose;
|
||||
|
||||
/* Get the number of CD ROMs in the System */
|
||||
/* Clean SysInfo structure */
|
||||
memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));
|
||||
/* Prepare structure to Ask Numer of Audio CDs */
|
||||
msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
|
||||
msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
|
||||
msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
|
||||
if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
|
||||
SDL_numcds = atoi(SysInfoRet);
|
||||
if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */
|
||||
|
||||
/* Get and Add their system name to the SDL_cdlist */
|
||||
msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
|
||||
msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
|
||||
msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
|
||||
for (i=0; i<SDL_numcds; i++)
|
||||
{
|
||||
msp.ulNumber = i+1;
|
||||
mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0);
|
||||
SDL_cdlist[i] = (char *)malloc(strlen(SysInfoRet)+1);
|
||||
if ( SDL_cdlist[i] == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return(-1);
|
||||
}
|
||||
strcpy(SDL_cdlist[i], SysInfoRet);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Return CDAudio System Dependent Device Name - Ready for MCI*/
|
||||
static const char *SDL_SYS_CDName(int drive)
|
||||
{
|
||||
return(SDL_cdlist[drive]);
|
||||
}
|
||||
|
||||
/* Open CDAudio Device - Ready for MCI */
|
||||
static int SDL_SYS_CDOpen(int drive)
|
||||
{
|
||||
MCI_OPEN_PARMS mop;
|
||||
MCI_SET_PARMS msp;
|
||||
MCI_GENERIC_PARMS mgp;
|
||||
|
||||
/* Open the device */
|
||||
mop.hwndCallback = (HWND)NULL; // None
|
||||
mop.usDeviceID = (USHORT)NULL; // Will be returned.
|
||||
mop.pszDeviceType = (PSZ)SDL_cdlist[drive]; // CDAudio Device
|
||||
if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
|
||||
/* Set time format */
|
||||
msp.hwndCallback = (HWND)NULL; // None
|
||||
msp.ulTimeFormat = MCI_FORMAT_MSF; // Minute : Second : Frame structure
|
||||
msp.ulSpeedFormat = (ULONG)NULL; // No change
|
||||
msp.ulAudio = (ULONG)NULL; // No Channel
|
||||
msp.ulLevel = (ULONG)NULL; // No Volume
|
||||
msp.ulOver = (ULONG)NULL; // No Delay
|
||||
msp.ulItem = (ULONG)NULL; // No item
|
||||
msp.ulValue = (ULONG)NULL; // No value for item flag
|
||||
if (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID);
|
||||
/* Error setting time format? - Close opened device */
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);
|
||||
return(CD_ERROR);
|
||||
}
|
||||
|
||||
/* Get CD Table Of Contents - Ready for MCI */
|
||||
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
|
||||
{
|
||||
MCI_TOC_PARMS mtp;
|
||||
MCI_STATUS_PARMS msp;
|
||||
MCI_TOC_REC * mtr;
|
||||
INT i;
|
||||
|
||||
/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */
|
||||
if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;
|
||||
|
||||
/* Get Number of Tracks */
|
||||
msp.hwndCallback = (HWND)NULL; /* None */
|
||||
msp.ulReturn = (ULONG)NULL; /* We want this information */
|
||||
msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;
|
||||
msp.ulValue = (ULONG)NULL; /* No additional information */
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
|
||||
cdrom->numtracks = msp.ulReturn;
|
||||
if ( cdrom->numtracks > SDL_MAX_TRACKS )
|
||||
{
|
||||
cdrom->numtracks = SDL_MAX_TRACKS;
|
||||
}
|
||||
/* Alocate space for TOC data */
|
||||
mtr = (MCI_TOC_REC *)malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));
|
||||
if ( mtr == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return(-1);
|
||||
}
|
||||
/* Get TOC from CD */
|
||||
mtp.pBuf = mtr;
|
||||
mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS)
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
free(mtr);
|
||||
return(CD_ERROR);
|
||||
}
|
||||
/* Fill SDL Tracks Structure */
|
||||
for (i=0; i<cdrom->numtracks; i++)
|
||||
{
|
||||
/* Set Track ID */
|
||||
cdrom->track[i].id = (mtr+i)->TrackNum;
|
||||
/* Set Track Type */
|
||||
msp.hwndCallback = (HWND)NULL; /* None */
|
||||
msp.ulReturn = (ULONG)NULL; /* We want this information */
|
||||
msp.ulItem = MCI_CD_STATUS_TRACK_TYPE;
|
||||
msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS)
|
||||
{
|
||||
free(mtr);
|
||||
return (CD_ERROR);
|
||||
}
|
||||
if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK;
|
||||
else cdrom->track[i].type = SDL_DATA_TRACK;
|
||||
/* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */
|
||||
cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr);
|
||||
/* Set Track Offset */
|
||||
cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr);
|
||||
}
|
||||
free(mtr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Get CD-ROM status - Ready for MCI */
|
||||
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
|
||||
{
|
||||
CDstatus status;
|
||||
MCI_STATUS_PARMS msp;
|
||||
|
||||
/* Get Status from MCI */
|
||||
msp.hwndCallback = (HWND)NULL; /* None */
|
||||
msp.ulReturn = (ULONG)NULL; /* We want this information */
|
||||
msp.ulItem = MCI_STATUS_MODE;
|
||||
msp.ulValue = (ULONG)NULL; /* No additional information */
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;
|
||||
else
|
||||
{
|
||||
switch(msp.ulReturn)
|
||||
{
|
||||
case MCI_MODE_NOT_READY:
|
||||
status = CD_TRAYEMPTY;
|
||||
break;
|
||||
case MCI_MODE_PAUSE:
|
||||
status = CD_PAUSED;
|
||||
break;
|
||||
case MCI_MODE_PLAY:
|
||||
status = CD_PLAYING;
|
||||
break;
|
||||
case MCI_MODE_STOP:
|
||||
status = CD_STOPPED;
|
||||
break;
|
||||
/* These cases should not occour */
|
||||
case MCI_MODE_RECORD:
|
||||
case MCI_MODE_SEEK:
|
||||
default:
|
||||
status = CD_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine position */
|
||||
if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */
|
||||
{
|
||||
if ((status == CD_PLAYING) || (status == CD_PAUSED))
|
||||
{
|
||||
/* Get Position */
|
||||
msp.hwndCallback = (HWND)NULL; /* None */
|
||||
msp.ulReturn = (ULONG)NULL; /* We want this information */
|
||||
msp.ulItem = MCI_STATUS_POSITION;
|
||||
msp.ulValue = (ULONG)NULL; /* No additiona info */
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR);
|
||||
/* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */
|
||||
*position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn));
|
||||
}
|
||||
else *position = 0;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Start play - Ready for MCI */
|
||||
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
|
||||
{
|
||||
MCI_GENERIC_PARMS mgp;
|
||||
MCI_STATUS_PARMS msp;
|
||||
MCI_PLAY_PARMS mpp;
|
||||
ULONG min,sec,frm;
|
||||
|
||||
/* Start MSF */
|
||||
FRAMES_TO_MSF(start, &min, &sec, &frm);
|
||||
MSF_MINUTE(mpp.ulFrom) = min;
|
||||
MSF_SECOND(mpp.ulFrom) = sec;
|
||||
MSF_FRAME(mpp.ulFrom) = frm;
|
||||
/* End MSF */
|
||||
FRAMES_TO_MSF(start+length, &min, &sec, &frm);
|
||||
MSF_MINUTE(mpp.ulTo) = min;
|
||||
MSF_SECOND(mpp.ulTo) = sec;
|
||||
MSF_FRAME(mpp.ulTo) = frm;
|
||||
#ifdef DEBUG_CDROM
|
||||
fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
|
||||
playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
|
||||
playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
|
||||
#endif
|
||||
/* Verifies if it is paused first... and if it is, unpause before stopping it. */
|
||||
msp.hwndCallback = (HWND)NULL; /* None */
|
||||
msp.ulReturn = (ULONG)NULL; /* We want this information */
|
||||
msp.ulItem = MCI_STATUS_MODE;
|
||||
msp.ulValue = (ULONG)NULL; /* No additional information */
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
|
||||
{
|
||||
if (msp.ulReturn == MCI_MODE_PAUSE)
|
||||
{
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
mciSendCommand(cdrom->id,MCI_RESUME,NULL,&mgp, 0);
|
||||
}
|
||||
}
|
||||
/* Now play it. */
|
||||
mpp.hwndCallback = (HWND)NULL; // We do not want the info. temp
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;
|
||||
return (CD_ERROR);
|
||||
}
|
||||
|
||||
/* Pause play - Ready for MCI */
|
||||
static int SDL_SYS_CDPause(SDL_CD *cdrom)
|
||||
{
|
||||
MCI_GENERIC_PARMS mgp;
|
||||
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
|
||||
return(CD_ERROR);
|
||||
}
|
||||
|
||||
/* Resume play - Ready for MCI */
|
||||
static int SDL_SYS_CDResume(SDL_CD *cdrom)
|
||||
{
|
||||
MCI_GENERIC_PARMS mgp;
|
||||
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
|
||||
return(CD_ERROR);
|
||||
}
|
||||
|
||||
/* Stop play - Ready for MCI */
|
||||
static int SDL_SYS_CDStop(SDL_CD *cdrom)
|
||||
{
|
||||
MCI_GENERIC_PARMS mgp;
|
||||
MCI_STATUS_PARMS msp;
|
||||
|
||||
/* Verifies if it is paused first... and if it is, unpause before stopping it. */
|
||||
msp.hwndCallback = (HWND)NULL; /* None */
|
||||
msp.ulReturn = (ULONG)NULL; /* We want this information */
|
||||
msp.ulItem = MCI_STATUS_MODE;
|
||||
msp.ulValue = (ULONG)NULL; /* No additional information */
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
|
||||
{
|
||||
if (msp.ulReturn == MCI_MODE_PAUSE)
|
||||
{
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
mciSendCommand(cdrom->id,MCI_RESUME,NULL,&mgp, 0);
|
||||
}
|
||||
}
|
||||
/* Now stops the media */
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
|
||||
return(CD_ERROR);
|
||||
}
|
||||
|
||||
/* Eject the CD-ROM - Ready for MCI */
|
||||
static int SDL_SYS_CDEject(SDL_CD *cdrom)
|
||||
{
|
||||
MCI_SET_PARMS msp;
|
||||
|
||||
msp.hwndCallback = (HWND)NULL; // None
|
||||
msp.ulTimeFormat = (ULONG)NULL; // No change
|
||||
msp.ulSpeedFormat = (ULONG)NULL; // No change
|
||||
msp.ulAudio = (ULONG)NULL; // No Channel
|
||||
msp.ulLevel = (ULONG)NULL; // No Volume
|
||||
msp.ulOver = (ULONG)NULL; // No Delay
|
||||
msp.ulItem = (ULONG)NULL; // No item
|
||||
msp.ulValue = (ULONG)NULL; // No value for item flag
|
||||
if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;
|
||||
return(CD_ERROR);
|
||||
}
|
||||
|
||||
/* Close the CD-ROM handle - Ready for MCI */
|
||||
static void SDL_SYS_CDClose(SDL_CD *cdrom)
|
||||
{
|
||||
MCI_GENERIC_PARMS mgp;
|
||||
|
||||
mgp.hwndCallback = (HWND)NULL; // None
|
||||
mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);
|
||||
}
|
||||
|
||||
/* Finalize CDROM Subsystem - Ready for MCI */
|
||||
void SDL_SYS_CDQuit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( SDL_numcds > 0 )
|
||||
{
|
||||
for ( i=0; i<SDL_numcds; ++i )
|
||||
{
|
||||
free(SDL_cdlist[i]);
|
||||
}
|
||||
SDL_numcds = 0;
|
||||
}
|
||||
}
|
||||
|
27
src/cpuinfo/Makefile.wat
Normal file
27
src/cpuinfo/Makefile.wat
Normal file
|
@ -0,0 +1,27 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for cpuinfo
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_cpuinfo.obj
|
||||
|
||||
# We have to define the following so the assembly parts can be
|
||||
# compiled by Watcom, too!
|
||||
ExtraCFlags=-d_MSC_VER
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
24
src/endian/Makefile.wat
Normal file
24
src/endian/Makefile.wat
Normal file
|
@ -0,0 +1,24 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for endianness
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_endian.obj
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
24
src/events/Makefile.wat
Normal file
24
src/events/Makefile.wat
Normal file
|
@ -0,0 +1,24 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for events
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_active.obj SDL_events.obj SDL_expose.obj SDL_keyboard.obj SDL_mouse.obj SDL_quit.obj SDL_resize.obj
|
||||
ExtraCFlags=-dUSE_DOSSETPRIORITY
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;../timer;../joystick;../video;
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
|
@ -89,9 +89,28 @@ void SDL_Unlock_EventThread(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __OS2__
|
||||
/*
|
||||
* We'll increase the priority of GobbleEvents thread, so it will process
|
||||
* events in time for sure! For this, we need the DosSetPriority() API
|
||||
* from the os2.h include file.
|
||||
*/
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static int SDL_GobbleEvents(void *unused)
|
||||
{
|
||||
event_thread = SDL_ThreadID();
|
||||
|
||||
#ifdef __OS2__
|
||||
#ifdef USE_DOSSETPRIORITY
|
||||
/* Increase thread priority, so it will process events in time for sure! */
|
||||
DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +16, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while ( SDL_EventQ.active ) {
|
||||
SDL_VideoDevice *video = current_video;
|
||||
SDL_VideoDevice *this = current_video;
|
||||
|
|
|
@ -45,8 +45,11 @@ int SDL_PrivateResize(int w, int h)
|
|||
SDL_Event events[32];
|
||||
|
||||
/* See if this event would change the video surface */
|
||||
if ( !w || !h ||
|
||||
((last_resize.w == w) && (last_resize.h == h)) ) {
|
||||
if ( !w || !h
|
||||
#ifndef __OS2__
|
||||
|| ((last_resize.w == w) && (last_resize.h == h))
|
||||
#endif
|
||||
) {
|
||||
return(0);
|
||||
}
|
||||
last_resize.w = w;
|
||||
|
|
|
@ -44,3 +44,7 @@ static char rcsid =
|
|||
#ifdef macintosh /* MacOS 7/8 don't support preemptive multi-tasking */
|
||||
#define CANT_THREAD_EVENTS
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__ /* The OS/2 event loop runs in a separate thread */
|
||||
#define MUST_THREAD_EVENTS
|
||||
#endif
|
||||
|
|
24
src/file/Makefile.wat
Normal file
24
src/file/Makefile.wat
Normal file
|
@ -0,0 +1,24 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for file
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_rwops.obj
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
27
src/joystick/Makefile.wat
Normal file
27
src/joystick/Makefile.wat
Normal file
|
@ -0,0 +1,27 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for joystick (using the dummy joystick driver)
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_joystick.obj SDL_sysjoystick.obj
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;./os2;../;../events;
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
SDL_sysjoystick.obj: .AUTODEPEND
|
||||
wcc386 os2\SDL_sysjoystick.c $(cflags)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
669
src/joystick/os2/SDL_sysjoystick.c
Normal file
669
src/joystick/os2/SDL_sysjoystick.c
Normal file
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* OS/2 Joystick driver, contributed by Daniel Caetano */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <mem.h>
|
||||
|
||||
#define INCL_DOSDEVICES
|
||||
#define INCL_DOSDEVIOCTL
|
||||
#define INCL_DOSMEMMGR
|
||||
#include <os2.h>
|
||||
#include "joyos2.h"
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_sysjoystick.h"
|
||||
#include "SDL_joystick_c.h"
|
||||
|
||||
HFILE hJoyPort = NULL; /* Joystick GAME$ Port Address */
|
||||
#define MAX_JOYSTICKS 2 /* Maximum of two joysticks */
|
||||
#define MAX_AXES 4 /* each joystick can have up to 4 axes */
|
||||
#define MAX_BUTTONS 8 /* 8 buttons */
|
||||
#define MAX_HATS 0 /* 0 hats - OS/2 doesn't support it */
|
||||
#define MAX_BALLS 0 /* and 0 balls - OS/2 doesn't support it */
|
||||
#define AXIS_MIN -32768 /* minimum value for axes coordinate */
|
||||
#define AXIS_MAX 32767 /* maximum value for axes coordinate */
|
||||
#define MAX_JOYNAME 128 /* Joystick name may have 128 characters */
|
||||
/* limit axes to 256 possible positions to filter out noise */
|
||||
#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256)
|
||||
/* Calc Button Flag for buttons A to D */
|
||||
#define JOY_BUTTON_FLAG(n) (1<<n)
|
||||
|
||||
/* Joystick data... hold information about detected devices */
|
||||
struct _SYS_JoyData
|
||||
{
|
||||
Sint8 id; // Device ID
|
||||
char szDeviceName[MAX_JOYNAME]; // Device Name
|
||||
char axes; // Number of axes
|
||||
char buttons; // Number of buttons
|
||||
char hats; // Number of buttons
|
||||
char balls; // Number of buttons
|
||||
int axes_min[MAX_AXES]; // minimum callibration value for axes
|
||||
int axes_med[MAX_AXES]; // medium callibration value for axes
|
||||
int axes_max[MAX_AXES]; // maximum callibration value for axes
|
||||
int buttoncalc[4]; // Used for buttons 5, 6, 7 and 8.
|
||||
} SYS_JoyData[MAX_JOYSTICKS];
|
||||
|
||||
|
||||
/* Structure used to convert data from OS/2 driver format to SDL format */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
Sint8 id;
|
||||
struct _transaxes
|
||||
{
|
||||
int offset; /* Center Offset */
|
||||
float scale1; /* Center to left/up Scale */
|
||||
float scale2; /* Center to right/down Scale */
|
||||
} transaxes[MAX_AXES];
|
||||
};
|
||||
|
||||
/* Structure used to get values from Joystick Environment Variable */
|
||||
struct _joycfg
|
||||
{
|
||||
char name[MAX_JOYNAME];
|
||||
unsigned int axes;
|
||||
unsigned int buttons;
|
||||
unsigned int hats;
|
||||
unsigned int balls;
|
||||
};
|
||||
|
||||
/* OS/2 Implementation Function Prototypes */
|
||||
APIRET joyPortOpen(HFILE * hGame);
|
||||
void joyPortClose(HFILE * hGame);
|
||||
int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars);
|
||||
int joyGetEnv(struct _joycfg * joydata);
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Function to scan the system for joysticks. */
|
||||
/* This function should set SDL_numjoysticks to the number of available */
|
||||
/* joysticks. Joystick 0 should be the system default joystick. */
|
||||
/* It should return 0, or -1 on an unrecoverable fatal error. */
|
||||
/************************************************************************/
|
||||
int SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
APIRET rc; /* Generic OS/2 return code */
|
||||
GAME_PORT_STRUCT stJoyStatus; /* Joystick Status Structure */
|
||||
GAME_PARM_STRUCT stGameParms; /* Joystick Parameter Structure */
|
||||
GAME_CALIB_STRUCT stGameCalib; /* Calibration Struct */
|
||||
ULONG ulDataLen; /* Size of data */
|
||||
ULONG ulLastTick; /* Tick Counter for timing operations */
|
||||
Uint8 maxdevs; /* Maximum number of devices */
|
||||
Uint8 numdevs; /* Number of present devices */
|
||||
Uint8 maxbut; /* Maximum number of buttons... */
|
||||
Uint8 i; /* Temporary Count Vars */
|
||||
Uint8 ucNewJoystickMask; /* Mask for Joystick Detection */
|
||||
struct _joycfg joycfg; /* Joy Configuration from envvar */
|
||||
|
||||
|
||||
/* Get Max Number of Devices */
|
||||
rc = joyPortOpen(&hJoyPort); /* Open GAME$ port */
|
||||
if (rc != 0) return 0; /* Cannot open... report no joystick */
|
||||
ulDataLen = sizeof(stGameParms);
|
||||
rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_PARMS,
|
||||
NULL, 0, NULL, &stGameParms, ulDataLen, &ulDataLen); /* Ask device info */
|
||||
if (rc != 0)
|
||||
{
|
||||
joyPortClose(&hJoyPort);
|
||||
SDL_SetError("Could not read joystick port.");
|
||||
return -1;
|
||||
}
|
||||
if (stGameParms.useA != 0) maxdevs++;
|
||||
if (stGameParms.useB != 0) maxdevs++;
|
||||
if ( maxdevs > MAX_JOYSTICKS ) maxdevs = MAX_JOYSTICKS;
|
||||
|
||||
/* Defines min/max axes values (callibration) */
|
||||
ulDataLen = sizeof(stGameCalib);
|
||||
rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_CALIB,
|
||||
NULL, 0, NULL, &stGameCalib, ulDataLen, &ulDataLen);
|
||||
if (rc != 0)
|
||||
{
|
||||
joyPortClose(&hJoyPort);
|
||||
SDL_SetError("Could not read callibration data.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Determine how many joysticks are active */
|
||||
numdevs = 0; /* Points no device */
|
||||
ucNewJoystickMask = 0x0F; /* read all 4 joystick axis */
|
||||
ulDataLen = sizeof(ucNewJoystickMask);
|
||||
rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_RESET,
|
||||
&ucNewJoystickMask, ulDataLen, &ulDataLen, NULL, 0, NULL);
|
||||
if (rc == 0)
|
||||
{
|
||||
ulDataLen = sizeof(stJoyStatus);
|
||||
rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
|
||||
NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
|
||||
if (rc != 0)
|
||||
{
|
||||
joyPortClose(&hJoyPort);
|
||||
SDL_SetError("Could not call joystick port.");
|
||||
return -1;
|
||||
}
|
||||
ulLastTick = stJoyStatus.ulJs_Ticks;
|
||||
while (stJoyStatus.ulJs_Ticks == ulLastTick)
|
||||
{
|
||||
rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
|
||||
NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
|
||||
}
|
||||
if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) numdevs++;
|
||||
if (((stJoyStatus.ucJs_JoyStickMask >> 2) & 0x03) > 0) numdevs++;
|
||||
}
|
||||
|
||||
if (numdevs>maxdevs) numdevs=maxdevs;
|
||||
|
||||
/* If *any* joystick was detected... Let's configure SDL for them */
|
||||
if (numdevs > 0)
|
||||
{
|
||||
/* Verify if it is a "user defined" joystick */
|
||||
if (joyGetEnv(&joycfg))
|
||||
{
|
||||
GAME_3POS_STRUCT * axis[4];
|
||||
axis[0] = &stGameCalib.Ax;
|
||||
axis[1] = &stGameCalib.Ay;
|
||||
axis[2] = &stGameCalib.Bx;
|
||||
axis[3] = &stGameCalib.By;
|
||||
/* Say it has one device only (user defined is always one device only) */
|
||||
numdevs = 1;
|
||||
/* Define Device 0 as... */
|
||||
SYS_JoyData[0].id=0;
|
||||
/* Define Number of Axes... up to 4 */
|
||||
if (joycfg.axes>MAX_AXES) joycfg.axes = MAX_AXES;
|
||||
SYS_JoyData[0].axes = joycfg.axes;
|
||||
/* Define number of buttons... 8 if 2 axes, 6 if 3 axes and 4 if 4 axes */
|
||||
maxbut = MAX_BUTTONS;
|
||||
if (joycfg.axes>2) maxbut-=((joycfg.axes-2)<<1); /* MAX_BUTTONS - 2*(axes-2) */
|
||||
if (joycfg.buttons > maxbut) joycfg.buttons = maxbut;
|
||||
SYS_JoyData[0].buttons = joycfg.buttons;
|
||||
/* Define number of hats */
|
||||
if (joycfg.hats > MAX_HATS) joycfg.hats = MAX_HATS;
|
||||
SYS_JoyData[0].hats = joycfg.hats;
|
||||
/* Define number of balls */
|
||||
if (joycfg.balls > MAX_BALLS) joycfg.balls = MAX_BALLS;
|
||||
SYS_JoyData[0].balls = joycfg.balls;
|
||||
/* Initialize Axes Callibration Values */
|
||||
for (i=0; i<joycfg.axes; i++)
|
||||
{
|
||||
SYS_JoyData[0].axes_min[i] = axis[i]->lower;
|
||||
SYS_JoyData[0].axes_med[i] = axis[i]->centre;
|
||||
SYS_JoyData[0].axes_max[i] = axis[i]->upper;
|
||||
}
|
||||
/* Initialize Buttons 5 to 8 structures */
|
||||
if (joycfg.buttons>=5) SYS_JoyData[0].buttoncalc[0]=((axis[2]->lower+axis[3]->centre)>>1);
|
||||
if (joycfg.buttons>=6) SYS_JoyData[0].buttoncalc[1]=((axis[3]->lower+axis[3]->centre)>>1);
|
||||
if (joycfg.buttons>=7) SYS_JoyData[0].buttoncalc[2]=((axis[2]->upper+axis[3]->centre)>>1);
|
||||
if (joycfg.buttons>=8) SYS_JoyData[0].buttoncalc[3]=((axis[3]->upper+axis[3]->centre)>>1);
|
||||
/* Intialize Joystick Name */
|
||||
strcpy (SYS_JoyData[0].szDeviceName,joycfg.name);
|
||||
}
|
||||
/* Default Init ... autoconfig */
|
||||
else
|
||||
{
|
||||
/* if two devices were detected... configure as Joy1 4 axis and Joy2 2 axis */
|
||||
if (numdevs==2)
|
||||
{
|
||||
/* Define Device 0 as 4 axes, 4 buttons */
|
||||
SYS_JoyData[0].id=0;
|
||||
SYS_JoyData[0].axes = 4;
|
||||
SYS_JoyData[0].buttons = 4;
|
||||
SYS_JoyData[0].hats = 0;
|
||||
SYS_JoyData[0].balls = 0;
|
||||
SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
|
||||
SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
|
||||
SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
|
||||
SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
|
||||
SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
|
||||
SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
|
||||
SYS_JoyData[0].axes_min[2] = stGameCalib.Bx.lower;
|
||||
SYS_JoyData[0].axes_med[2] = stGameCalib.Bx.centre;
|
||||
SYS_JoyData[0].axes_max[2] = stGameCalib.Bx.upper;
|
||||
SYS_JoyData[0].axes_min[3] = stGameCalib.By.lower;
|
||||
SYS_JoyData[0].axes_med[3] = stGameCalib.By.centre;
|
||||
SYS_JoyData[0].axes_max[3] = stGameCalib.By.upper;
|
||||
/* Define Device 1 as 2 axes, 2 buttons */
|
||||
SYS_JoyData[1].id=1;
|
||||
SYS_JoyData[1].axes = 2;
|
||||
SYS_JoyData[1].buttons = 2;
|
||||
SYS_JoyData[1].hats = 0;
|
||||
SYS_JoyData[1].balls = 0;
|
||||
SYS_JoyData[1].axes_min[0] = stGameCalib.Bx.lower;
|
||||
SYS_JoyData[1].axes_med[0] = stGameCalib.Bx.centre;
|
||||
SYS_JoyData[1].axes_max[0] = stGameCalib.Bx.upper;
|
||||
SYS_JoyData[1].axes_min[1] = stGameCalib.By.lower;
|
||||
SYS_JoyData[1].axes_med[1] = stGameCalib.By.centre;
|
||||
SYS_JoyData[1].axes_max[1] = stGameCalib.By.upper;
|
||||
}
|
||||
/* One joystick only? */
|
||||
else
|
||||
{
|
||||
/* If it is joystick A... */
|
||||
if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0)
|
||||
{
|
||||
/* Define Device 0 as 2 axes, 4 buttons */
|
||||
SYS_JoyData[0].id=0;
|
||||
SYS_JoyData[0].axes = 2;
|
||||
SYS_JoyData[0].buttons = 4;
|
||||
SYS_JoyData[0].hats = 0;
|
||||
SYS_JoyData[0].balls = 0;
|
||||
SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
|
||||
SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
|
||||
SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
|
||||
SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
|
||||
SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
|
||||
SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
|
||||
}
|
||||
/* If not, it is joystick B */
|
||||
else
|
||||
{
|
||||
/* Define Device 1 as 2 axes, 2 buttons */
|
||||
SYS_JoyData[0].id=1;
|
||||
SYS_JoyData[0].axes = 2;
|
||||
SYS_JoyData[0].buttons = 2;
|
||||
SYS_JoyData[0].hats = 0;
|
||||
SYS_JoyData[0].balls = 0;
|
||||
SYS_JoyData[0].axes_min[0] = stGameCalib.Bx.lower;
|
||||
SYS_JoyData[0].axes_med[0] = stGameCalib.Bx.centre;
|
||||
SYS_JoyData[0].axes_max[0] = stGameCalib.Bx.upper;
|
||||
SYS_JoyData[0].axes_min[1] = stGameCalib.By.lower;
|
||||
SYS_JoyData[0].axes_med[1] = stGameCalib.By.centre;
|
||||
SYS_JoyData[0].axes_max[1] = stGameCalib.By.upper;
|
||||
}
|
||||
}
|
||||
/* Hack to define Joystick Port Names */
|
||||
if ( numdevs > maxdevs ) numdevs = maxdevs;
|
||||
for (i=0; i<numdevs; i++) sprintf (SYS_JoyData[i].szDeviceName,"Default Joystick %c",'A'+SYS_JoyData[i].id);
|
||||
}
|
||||
}
|
||||
/* Return the number of devices found */
|
||||
return(numdevs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************/
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
/***********************************************************/
|
||||
const char *SDL_SYS_JoystickName(int index)
|
||||
{
|
||||
/* No need to verify if device exists, already done in upper layer */
|
||||
return(SYS_JoyData[index].szDeviceName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Function to open a joystick for use. */
|
||||
/* The joystick to open is specified by the index field of the joystick. */
|
||||
/* This should fill the nbuttons and naxes fields of the joystick structure. */
|
||||
/* It returns 0, or -1 if there is an error. */
|
||||
/******************************************************************************/
|
||||
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
|
||||
{
|
||||
int index; /* Index shortcut for index in joystick structure */
|
||||
int i; /* Generic Counter */
|
||||
|
||||
/* allocate memory for system specific hardware data */
|
||||
joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
|
||||
if (joystick->hwdata == NULL)
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return(-1);
|
||||
}
|
||||
/* Reset Hardware Data */
|
||||
memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
|
||||
|
||||
/* ShortCut Pointer */
|
||||
index = joystick->index;
|
||||
/* Define offsets and scales for all axes */
|
||||
joystick->hwdata->id = SYS_JoyData[index].id;
|
||||
for ( i = 0; i < MAX_AXES; ++i )
|
||||
{
|
||||
if ( (i<2) || i < SYS_JoyData[index].axes )
|
||||
{
|
||||
joystick->hwdata->transaxes[i].offset = ((AXIS_MAX + AXIS_MIN)>>1) - SYS_JoyData[index].axes_med[i];
|
||||
//joystick->hwdata->transaxes[i].scale = (float)((AXIS_MAX - AXIS_MIN)/(SYS_JoyData[index].axes_max[i]-SYS_JoyData[index].axes_min[i]));
|
||||
joystick->hwdata->transaxes[i].scale1 = (float)abs((AXIS_MIN/SYS_JoyData[index].axes_min[i]));
|
||||
joystick->hwdata->transaxes[i].scale2 = (float)abs((AXIS_MAX/SYS_JoyData[index].axes_max[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
joystick->hwdata->transaxes[i].offset = 0;
|
||||
//joystick->hwdata->transaxes[i].scale = 1.0; /* Just in case */
|
||||
joystick->hwdata->transaxes[i].scale1 = 1.0; /* Just in case */
|
||||
joystick->hwdata->transaxes[i].scale2 = 1.0; /* Just in case */
|
||||
}
|
||||
}
|
||||
|
||||
/* fill nbuttons, naxes, and nhats fields */
|
||||
joystick->nbuttons = SYS_JoyData[index].buttons;
|
||||
joystick->naxes = SYS_JoyData[index].axes;
|
||||
/* joystick->nhats = SYS_JoyData[index].hats; */
|
||||
joystick->nhats = 0; /* No support for hats at this time */
|
||||
/* joystick->nballs = SYS_JoyData[index].balls; */
|
||||
joystick->nballs = 0; /* No support for balls at this time */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Function to update the state of a joystick - called as a device poll. */
|
||||
/* This function shouldn't update the joystick structure directly, */
|
||||
/* but instead should call SDL_PrivateJoystick*() to deliver events */
|
||||
/* and update joystick device state. */
|
||||
/***************************************************************************/
|
||||
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
|
||||
{
|
||||
APIRET rc; /* Generic OS/2 return code */
|
||||
int index; /* index shortcurt to joystick index */
|
||||
int i; /* Generic counter */
|
||||
int normbut; /* Number of buttons reported by joystick */
|
||||
int corr; /* Correction for button names */
|
||||
Sint16 value, change; /* Values used to update axis values */
|
||||
struct _transaxes *transaxes; /* Shortcut for Correction structure */
|
||||
Uint32 pos[MAX_AXES]; /* Vector to inform the Axis status */
|
||||
ULONG ulDataLen; /* Size of data */
|
||||
GAME_STATUS_STRUCT stGameStatus; /* Joystick Status Structure */
|
||||
|
||||
ulDataLen = sizeof(stGameStatus);
|
||||
rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_STATUS,
|
||||
NULL, 0, NULL, &stGameStatus, ulDataLen, &ulDataLen);
|
||||
if (rc != 0)
|
||||
{
|
||||
SDL_SetError("Could not read joystick status.");
|
||||
return; /* Could not read data */
|
||||
}
|
||||
|
||||
/* Shortcut pointer */
|
||||
index = joystick->index;
|
||||
/* joystick motion events */
|
||||
|
||||
if (SYS_JoyData[index].id == 0)
|
||||
{
|
||||
pos[0] = stGameStatus.curdata.A.x;
|
||||
pos[1] = stGameStatus.curdata.A.y;
|
||||
if (SYS_JoyData[index].axes >= 3) pos[2] = stGameStatus.curdata.B.x;
|
||||
else pos[2]=0;
|
||||
if (SYS_JoyData[index].axes >= 4) pos[3] = stGameStatus.curdata.B.y;
|
||||
else pos[3]=0;
|
||||
pos[4]=0; /* OS/2 basic drivers do not support more than 4 axes joysticks */
|
||||
pos[5]=0;
|
||||
}
|
||||
else if (SYS_JoyData[index].id == 1)
|
||||
{
|
||||
pos[0] = stGameStatus.curdata.B.x;
|
||||
pos[1] = stGameStatus.curdata.B.y;
|
||||
pos[2]=0;
|
||||
pos[3]=0;
|
||||
pos[4]=0;
|
||||
pos[5]=0;
|
||||
}
|
||||
|
||||
/* Corrects the movements using the callibration */
|
||||
transaxes = joystick->hwdata->transaxes;
|
||||
for (i = 0; i < joystick->naxes; i++)
|
||||
{
|
||||
value = pos[i] + transaxes[i].offset;
|
||||
if (value<0)
|
||||
{
|
||||
value*=transaxes[i].scale1;
|
||||
if (value>0) value = AXIS_MIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
value*=transaxes[i].scale2;
|
||||
if (value<0) value = AXIS_MAX;
|
||||
}
|
||||
change = (value - joystick->axes[i]);
|
||||
if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) )
|
||||
{
|
||||
SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value);
|
||||
}
|
||||
}
|
||||
|
||||
/* joystick button A to D events */
|
||||
if (SYS_JoyData[index].id == 1) corr = 2;
|
||||
else corr = 0;
|
||||
normbut=4; /* Number of normal buttons */
|
||||
if (joystick->nbuttons<normbut) normbut = joystick->nbuttons;
|
||||
for ( i = corr; (i-corr) < normbut; ++i )
|
||||
{
|
||||
/*
|
||||
Button A: 1110 0000
|
||||
Button B: 1101 0000
|
||||
Button C: 1011 0000
|
||||
Button D: 0111 0000
|
||||
*/
|
||||
if ( (~stGameStatus.curdata.butMask)>>4 & JOY_BUTTON_FLAG(i) )
|
||||
{
|
||||
if ( ! joystick->buttons[i-corr] )
|
||||
{
|
||||
SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_PRESSED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( joystick->buttons[i-corr] )
|
||||
{
|
||||
SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Joystick button E to H buttons */
|
||||
/*
|
||||
Button E: Axis 2 X Left
|
||||
Button F: Axis 2 Y Up
|
||||
Button G: Axis 2 X Right
|
||||
Button H: Axis 2 Y Down
|
||||
*/
|
||||
if (joystick->nbuttons>=5)
|
||||
{
|
||||
if (stGameStatus.curdata.B.x < SYS_JoyData[index].buttoncalc[0]) SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_PRESSED);
|
||||
else SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_RELEASED);
|
||||
}
|
||||
if (joystick->nbuttons>=6)
|
||||
{
|
||||
if (stGameStatus.curdata.B.y < SYS_JoyData[index].buttoncalc[1]) SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_PRESSED);
|
||||
else SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_RELEASED);
|
||||
}
|
||||
if (joystick->nbuttons>=7)
|
||||
{
|
||||
if (stGameStatus.curdata.B.x > SYS_JoyData[index].buttoncalc[2]) SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_PRESSED);
|
||||
else SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_RELEASED);
|
||||
}
|
||||
if (joystick->nbuttons>=8)
|
||||
{
|
||||
if (stGameStatus.curdata.B.y > SYS_JoyData[index].buttoncalc[3]) SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_PRESSED);
|
||||
else SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_RELEASED);
|
||||
}
|
||||
|
||||
/* joystick hat events */
|
||||
/* Not Supported under OS/2 */
|
||||
/* joystick ball events */
|
||||
/* Not Supported under OS/2 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* Function to close a joystick after use */
|
||||
/******************************************/
|
||||
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
|
||||
{
|
||||
if (joystick->hwdata != NULL)
|
||||
{
|
||||
/* free system specific hardware data */
|
||||
free(joystick->hwdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
/********************************************************************/
|
||||
void SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
joyPortClose(&hJoyPort);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************/
|
||||
/************************/
|
||||
/* OS/2 Implementations */
|
||||
/************************/
|
||||
/************************/
|
||||
|
||||
|
||||
/*****************************************/
|
||||
/* Open Joystick Port, if not opened yet */
|
||||
/*****************************************/
|
||||
APIRET joyPortOpen(HFILE * hGame)
|
||||
{
|
||||
APIRET rc; /* Generic Return Code */
|
||||
ULONG ulAction; /* ? */
|
||||
ULONG ulVersion; /* Version of joystick driver */
|
||||
ULONG ulDataLen; /* Size of version data */
|
||||
|
||||
/* Verifies if joyport is not already open... */
|
||||
if (*hGame != NULL) return 0;
|
||||
/* Open GAME$ for read */
|
||||
rc = DosOpen((PSZ)GAMEPDDNAME, hGame, &ulAction, 0, FILE_READONLY,
|
||||
FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL);
|
||||
if (rc != 0)
|
||||
{
|
||||
SDL_SetError("Could not open Joystick Port.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get Joystick Driver Version... must be 2.0 or higher */
|
||||
ulVersion = 0;
|
||||
ulDataLen = sizeof(ulVersion);
|
||||
rc = DosDevIOCtl( *hGame, IOCTL_CAT_USER, GAME_GET_VERSION,
|
||||
NULL, 0, NULL, &ulVersion, ulDataLen, &ulDataLen);
|
||||
if (rc != 0)
|
||||
{
|
||||
joyPortClose(hGame);
|
||||
SDL_SetError("Could not get Joystick Driver version.");
|
||||
return -1;
|
||||
}
|
||||
if (ulVersion < GAME_VERSION)
|
||||
{
|
||||
joyPortClose(hGame);
|
||||
SDL_SetError("Driver too old. At least IBM driver version 2.0 required.");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************/
|
||||
/* Close JoyPort, if opened */
|
||||
/****************************/
|
||||
void joyPortClose(HFILE * hGame)
|
||||
{
|
||||
if (*hGame != NULL) DosClose(*hGame);
|
||||
*hGame = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************/
|
||||
/* Get SDL Joystick EnvVar */
|
||||
/***************************/
|
||||
int joyGetEnv(struct _joycfg * joydata)
|
||||
{
|
||||
char *joyenv; /* Pointer to tested character */
|
||||
char tempnumber[5]; /* Temporary place to put numeric texts */
|
||||
|
||||
joyenv = getenv("SDL_OS2_JOYSTICK");
|
||||
if (joyenv == NULL) return 0;
|
||||
/* Joystick Environment is defined! */
|
||||
while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
|
||||
/* If the string name starts with '... get if fully */
|
||||
if (*joyenv=='\'') joyenv+=joyGetData(++joyenv,joydata->name,'\'',sizeof(joydata->name));
|
||||
/* If not, get it until the next space */
|
||||
else if (*joyenv=='\"') joyenv+=joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name));
|
||||
else joyenv+=joyGetData(joyenv,joydata->name,' ',sizeof(joydata->name));
|
||||
/* Now get the number of axes */
|
||||
while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
|
||||
joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
|
||||
joydata->axes = atoi(tempnumber);
|
||||
/* Now get the number of buttons */
|
||||
while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
|
||||
joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
|
||||
joydata->buttons = atoi(tempnumber);
|
||||
/* Now get the number of hats */
|
||||
while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
|
||||
joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
|
||||
joydata->hats = atoi(tempnumber);
|
||||
/* Now get the number of balls */
|
||||
while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */
|
||||
joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
|
||||
joydata->balls = atoi(tempnumber);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Get a text from in the string starting in joyenv until it finds */
|
||||
/* the stopchar or maxchars is reached. The result is placed in name. */
|
||||
/************************************************************************/
|
||||
int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars)
|
||||
{
|
||||
char *nameptr; /* Pointer to the selected character */
|
||||
int chcnt=0; /* Count how many characters where copied */
|
||||
|
||||
nameptr=name;
|
||||
while (*joyenv!=stopchar && *joyenv!=0)
|
||||
{
|
||||
if (nameptr<(name+(maxchars-1)))
|
||||
{
|
||||
*nameptr = *joyenv; /* Only copy if smaller than maximum */
|
||||
nameptr++;
|
||||
}
|
||||
chcnt++;
|
||||
joyenv++;
|
||||
}
|
||||
if (*joyenv==stopchar)
|
||||
{
|
||||
joyenv++; /* Jump stopchar */
|
||||
chcnt++;
|
||||
}
|
||||
*nameptr = 0; /* Mark last byte */
|
||||
return chcnt;
|
||||
}
|
||||
|
||||
|
177
src/joystick/os2/joyos2.h
Normal file
177
src/joystick/os2/joyos2.h
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COPYRIGHT Copyright (C) 1995 IBM Corporation */
|
||||
/* */
|
||||
/* The following IBM OS/2 source code is provided to you solely for */
|
||||
/* the purpose of assisting you in your development of OS/2 device */
|
||||
/* drivers. You may use this code in accordance with the IBM License */
|
||||
/* Agreement provided in the IBM Device Driver Source Kit for OS/2. This */
|
||||
/* Copyright statement may not be removed. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#ifndef JOYOS2_H
|
||||
#define JOYOS2_H
|
||||
|
||||
/****** GAMEPORT.SYS joystick definitions, start *****************************/
|
||||
#define GAME_VERSION 0x20 /* 2.0 First IBM version */
|
||||
#define GAMEPDDNAME "GAME$ "
|
||||
#define IOCTL_CAT_USER 0x80
|
||||
#define GAME_PORT_GET 0x20 /* read GAMEPORT.SYS values */
|
||||
#define GAME_PORT_RESET 0x60 /* reset joystick mask with given value */
|
||||
|
||||
#pragma pack(1) /* pack structure size is 1 byte */
|
||||
typedef struct { /* GAMEPORT.SYS structure */
|
||||
USHORT usJs_AxCnt; /* Joystick_A X position */
|
||||
USHORT usJs_AyCnt; /* Joystick_A Y position */
|
||||
USHORT usJs_BxCnt; /* Joystick_B X position */
|
||||
USHORT usJs_ByCnt; /* Joystick_B Y position */
|
||||
USHORT usJs_ButtonA1Cnt; /* button A1 press count */
|
||||
USHORT usJs_ButtonA2Cnt; /* button A2 press count */
|
||||
USHORT usJs_ButtonB1Cnt; /* button B1 press count */
|
||||
USHORT usJs_ButtonB2Cnt; /* button B2 press count */
|
||||
UCHAR ucJs_JoyStickMask; /* mask of connected joystick pots */
|
||||
UCHAR ucJs_ButtonStatus; /* bits of switches down */
|
||||
ULONG ulJs_Ticks; /* joystick clock ticks */
|
||||
} GAME_PORT_STRUCT;
|
||||
#pragma pack() /*reset to normal pack size */
|
||||
/****** GAMEPORT.SYS joystick definitions, end *******************************/
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#define GAME_GET_VERSION 0x01
|
||||
#define GAME_GET_PARMS 0x02
|
||||
#define GAME_SET_PARMS 0x03
|
||||
#define GAME_GET_CALIB 0x04
|
||||
#define GAME_SET_CALIB 0x05
|
||||
#define GAME_GET_DIGSET 0x06
|
||||
#define GAME_SET_DIGSET 0x07
|
||||
#define GAME_GET_STATUS 0x10
|
||||
#define GAME_GET_STATUS_BUTWAIT 0x11
|
||||
#define GAME_GET_STATUS_SAMPWAIT 0x12
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
// bit masks for each axis
|
||||
#define JOY_AX_BIT 0x01
|
||||
#define JOY_AY_BIT 0x02
|
||||
#define JOY_A_BITS (JOY_AX_BIT|JOY_AY_BIT)
|
||||
#define JOY_BX_BIT 0x04
|
||||
#define JOY_BY_BIT 0x08
|
||||
#define JOY_B_BITS (JOY_BX_BIT|JOY_BY_BIT)
|
||||
#define JOY_ALLPOS_BITS (JOY_A_BITS|JOY_B_BITS)
|
||||
|
||||
// bit masks for each button
|
||||
#define JOY_BUT1_BIT 0x10
|
||||
#define JOY_BUT2_BIT 0x20
|
||||
#define JOY_BUT3_BIT 0x40
|
||||
#define JOY_BUT4_BIT 0x80
|
||||
#define JOY_ALL_BUTS (JOY_BUT1_BIT|JOY_BUT2_BIT|JOY_BUT3_BIT|JOY_BUT4_BIT)
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
// 1-D position struct used for each axis
|
||||
typedef SHORT GAME_POS; /* some data formats require signed values */
|
||||
|
||||
// simple 2-D position for each joystick
|
||||
typedef struct
|
||||
{
|
||||
GAME_POS x;
|
||||
GAME_POS y;
|
||||
}
|
||||
GAME_2DPOS_STRUCT;
|
||||
|
||||
// struct defining the instantaneous state of both sticks and all buttons
|
||||
typedef struct
|
||||
{
|
||||
GAME_2DPOS_STRUCT A;
|
||||
GAME_2DPOS_STRUCT B;
|
||||
USHORT butMask;
|
||||
}
|
||||
GAME_DATA_STRUCT;
|
||||
|
||||
// struct to be used for calibration and digital response on each axis
|
||||
typedef struct
|
||||
{
|
||||
GAME_POS lower;
|
||||
GAME_POS centre;
|
||||
GAME_POS upper;
|
||||
}
|
||||
GAME_3POS_STRUCT;
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
// status struct returned to OS/2 applications:
|
||||
// current data for all sticks as well as button counts since last read
|
||||
typedef struct
|
||||
{
|
||||
GAME_DATA_STRUCT curdata;
|
||||
USHORT b1cnt;
|
||||
USHORT b2cnt;
|
||||
USHORT b3cnt;
|
||||
USHORT b4cnt;
|
||||
}
|
||||
GAME_STATUS_STRUCT;
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/* in use bitmasks originating in 0.2b */
|
||||
#define GAME_USE_BOTH_OLDMASK 0x01 /* for backward compat with bool */
|
||||
#define GAME_USE_X_NEWMASK 0x02
|
||||
#define GAME_USE_Y_NEWMASK 0x04
|
||||
#define GAME_USE_X_EITHERMASK (GAME_USE_X_NEWMASK|GAME_USE_BOTH_OLDMASK)
|
||||
#define GAME_USE_Y_EITHERMASK (GAME_USE_Y_NEWMASK|GAME_USE_BOTH_OLDMASK)
|
||||
#define GAME_USE_BOTH_NEWMASK (GAME_USE_X_NEWMASK|GAME_USE_Y_NEWMASK)
|
||||
|
||||
/* only timed sampling implemented in version 1.0 */
|
||||
#define GAME_MODE_TIMED 1 /* timed sampling */
|
||||
#define GAME_MODE_REQUEST 2 /* request driven sampling */
|
||||
|
||||
/* only raw implemented in version 1.0 */
|
||||
#define GAME_DATA_FORMAT_RAW 1 /* [l,c,r] */
|
||||
#define GAME_DATA_FORMAT_SIGNED 2 /* [-l,0,+r] */
|
||||
#define GAME_DATA_FORMAT_BINARY 3 /* {-1,0,+1} */
|
||||
#define GAME_DATA_FORMAT_SCALED 4 /* [-10,+10] */
|
||||
|
||||
// parameters defining the operation of the driver
|
||||
typedef struct
|
||||
{
|
||||
USHORT useA; /* new bitmasks: see above */
|
||||
USHORT useB;
|
||||
USHORT mode; /* see consts above */
|
||||
USHORT format; /* see consts above */
|
||||
USHORT sampDiv; /* samp freq = 32 / n */
|
||||
USHORT scale; /* scaling factor */
|
||||
USHORT res1; /* must be 0 */
|
||||
USHORT res2; /* must be 0 */
|
||||
}
|
||||
GAME_PARM_STRUCT;
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
// calibration values for each axis:
|
||||
// - upper limit on value to be considered in lower range
|
||||
// - centre value
|
||||
// - lower limit on value to be considered in upper range
|
||||
typedef struct
|
||||
{
|
||||
GAME_3POS_STRUCT Ax;
|
||||
GAME_3POS_STRUCT Ay;
|
||||
GAME_3POS_STRUCT Bx;
|
||||
GAME_3POS_STRUCT By;
|
||||
}
|
||||
GAME_CALIB_STRUCT;
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
// struct defining the digital response values for all axes
|
||||
typedef struct
|
||||
{
|
||||
GAME_3POS_STRUCT Ax;
|
||||
GAME_3POS_STRUCT Ay;
|
||||
GAME_3POS_STRUCT Bx;
|
||||
GAME_3POS_STRUCT By;
|
||||
}
|
||||
GAME_DIGSET_STRUCT;
|
||||
/****************************************************************************/
|
||||
|
||||
#endif
|
|
@ -781,6 +781,7 @@ static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, in
|
|||
const char *errstr;
|
||||
const char *file;
|
||||
void (*init) (void);
|
||||
|
||||
ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
|
||||
switch (ofirc)
|
||||
{
|
||||
|
|
82
src/loadso/os2/SDL_loadso.c
Normal file
82
src/loadso/os2/SDL_loadso.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* System dependent library loading routines */
|
||||
|
||||
#if !SDL_INTERNAL_BUILDING_LOADSO
|
||||
#error Do not compile directly...compile src/SDL_loadso.c instead!
|
||||
#endif
|
||||
|
||||
#if !defined(__OS2__)
|
||||
#error Compiling for the wrong platform?
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSMODULEMGR
|
||||
#include <os2.h>
|
||||
|
||||
#include "SDL_types.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
void *SDL_LoadObject(const char *sofile)
|
||||
{
|
||||
HMODULE handle = NULL;
|
||||
char buf[512];
|
||||
APIRET ulrc = DosLoadModule(buf, sizeof (buf), (char *) sofile, &handle);
|
||||
|
||||
/* Generate an error message if all loads failed */
|
||||
if ((ulrc != NO_ERROR) || (handle == NULL))
|
||||
SDL_SetError("Failed loading %s: %s", sofile, buf);
|
||||
|
||||
return((void *) handle);
|
||||
}
|
||||
|
||||
void *SDL_LoadFunction(void *handle, const char *name)
|
||||
{
|
||||
const char *loaderror = "Unknown error";
|
||||
void *symbol = NULL;
|
||||
APIRET ulrc = DosQueryProcAddr((HMODULE)handle, 0, (char *)name, &symbol);
|
||||
if (ulrc == ERROR_INVALID_HANDLE)
|
||||
loaderror = "Invalid module handle";
|
||||
else if (ulrc == ERROR_INVALID_NAME)
|
||||
loaderror = "Symbol not found";
|
||||
|
||||
if (symbol == NULL)
|
||||
SDL_SetError("Failed loading %s: %s", name, loaderror);
|
||||
|
||||
return(symbol);
|
||||
}
|
||||
|
||||
void SDL_UnloadObject(void *handle)
|
||||
{
|
||||
if ( handle != NULL )
|
||||
DosFreeModule((HMODULE) handle);
|
||||
}
|
||||
|
36
src/thread/Makefile.wat
Normal file
36
src/thread/Makefile.wat
Normal file
|
@ -0,0 +1,36 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for threading
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_thread.obj SDL_sysmutex.obj SDL_syssem.obj SDL_systhread.obj SDL_syscond.obj
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
SDL_sysmutex.obj: .AUTODEPEND
|
||||
wcc386 os2\SDL_sysmutex.c $(cflags)
|
||||
|
||||
SDL_syssem.obj: .AUTODEPEND
|
||||
wcc386 os2\SDL_syssem.c $(cflags)
|
||||
|
||||
SDL_systhread.obj: .AUTODEPEND
|
||||
wcc386 os2\SDL_systhread.c $(cflags)
|
||||
|
||||
SDL_syscond.obj: .AUTODEPEND
|
||||
wcc386 os2\SDL_syscond.c $(cflags)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
|
@ -33,7 +33,11 @@ static char rcsid =
|
|||
saves a system-dependent thread id in thread->id, and returns 0
|
||||
on success.
|
||||
*/
|
||||
#ifdef __OS2__
|
||||
extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
|
||||
#else
|
||||
extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args);
|
||||
#endif
|
||||
|
||||
/* This function does any necessary setup in the child thread */
|
||||
extern void SDL_SYS_SetupThread(void);
|
||||
|
|
|
@ -218,7 +218,11 @@ void SDL_RunThread(void *data)
|
|||
*statusloc = userfunc(userdata);
|
||||
}
|
||||
|
||||
SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
|
||||
#ifdef __OS2__
|
||||
DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread_Core(int (*fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
|
||||
#else
|
||||
DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (*fn)(void *), void *data)
|
||||
#endif
|
||||
{
|
||||
SDL_Thread *thread;
|
||||
thread_args *args;
|
||||
|
@ -254,7 +258,11 @@ SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
|
|||
SDL_AddThread(thread);
|
||||
|
||||
/* Create the thread and go! */
|
||||
#ifdef __OS2__
|
||||
ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
|
||||
#else
|
||||
ret = SDL_SYS_CreateThread(thread, args);
|
||||
#endif
|
||||
if ( ret >= 0 ) {
|
||||
/* Wait for the thread function to use arguments */
|
||||
SDL_SemWait(args->wait);
|
||||
|
|
223
src/thread/os2/SDL_syscond.c
Normal file
223
src/thread/os2/SDL_syscond.c
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* An implementation of condition variables using semaphores and mutexes */
|
||||
/*
|
||||
This implementation borrows heavily from the BeOS condition variable
|
||||
implementation, written by Christopher Tate and Owen Smith. Thanks!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_sem *wait_sem;
|
||||
SDL_sem *wait_done;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
|
||||
cond = (SDL_cond *) malloc(sizeof(SDL_cond));
|
||||
if ( cond ) {
|
||||
cond->lock = SDL_CreateMutex();
|
||||
cond->wait_sem = SDL_CreateSemaphore(0);
|
||||
cond->wait_done = SDL_CreateSemaphore(0);
|
||||
cond->waiting = cond->signals = 0;
|
||||
if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) {
|
||||
SDL_DestroyCond(cond);
|
||||
cond = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return(cond);
|
||||
}
|
||||
|
||||
/* Destroy a condition variable */
|
||||
DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond)
|
||||
{
|
||||
if ( cond ) {
|
||||
if ( cond->wait_sem ) {
|
||||
SDL_DestroySemaphore(cond->wait_sem);
|
||||
}
|
||||
if ( cond->wait_done ) {
|
||||
SDL_DestroySemaphore(cond->wait_done);
|
||||
}
|
||||
if ( cond->lock ) {
|
||||
SDL_DestroyMutex(cond->lock);
|
||||
}
|
||||
free(cond);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart one of the threads that are waiting on the condition variable */
|
||||
DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if ( cond->waiting > cond->signals ) {
|
||||
++cond->signals;
|
||||
SDL_SemPost(cond->wait_sem);
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_SemWait(cond->wait_done);
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if ( cond->waiting > cond->signals ) {
|
||||
int i, num_waiting;
|
||||
|
||||
num_waiting = (cond->waiting - cond->signals);
|
||||
cond->signals = cond->waiting;
|
||||
for ( i=0; i<num_waiting; ++i ) {
|
||||
SDL_SemPost(cond->wait_sem);
|
||||
}
|
||||
/* Now all released threads are blocked here, waiting for us.
|
||||
Collect them all (and win fabulous prizes!) :-)
|
||||
*/
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
for ( i=0; i<num_waiting; ++i ) {
|
||||
SDL_SemWait(cond->wait_done);
|
||||
}
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
The mutex must be locked before entering this function!
|
||||
The mutex is unlocked during the wait, and locked again after the wait.
|
||||
|
||||
Typical use:
|
||||
|
||||
Thread A:
|
||||
SDL_LockMutex(lock);
|
||||
while ( ! condition ) {
|
||||
SDL_CondWait(cond);
|
||||
}
|
||||
SDL_UnlockMutex(lock);
|
||||
|
||||
Thread B:
|
||||
SDL_LockMutex(lock);
|
||||
...
|
||||
condition = true;
|
||||
...
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Obtain the protection mutex, and increment the number of waiters.
|
||||
This allows the signal mechanism to only perform a signal if there
|
||||
are waiting threads.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
++cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Unlock the mutex, as is required by condition variable semantics */
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
/* Wait for a signal */
|
||||
if ( ms == SDL_MUTEX_MAXWAIT ) {
|
||||
retval = SDL_SemWait(cond->wait_sem);
|
||||
} else {
|
||||
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
|
||||
}
|
||||
|
||||
/* Let the signaler know we have completed the wait, otherwise
|
||||
the signaler can race ahead and get the condition semaphore
|
||||
if we are stopped between the mutex unlock and semaphore wait,
|
||||
giving a deadlock. See the following URL for details:
|
||||
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if ( cond->signals > 0 ) {
|
||||
/* If we timed out, we need to eat a condition signal */
|
||||
if ( retval > 0 ) {
|
||||
SDL_SemWait(cond->wait_sem);
|
||||
}
|
||||
/* We always notify the signal thread that we are done */
|
||||
SDL_SemPost(cond->wait_done);
|
||||
|
||||
/* Signal handshake complete */
|
||||
--cond->signals;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
27
src/thread/os2/SDL_syscond_c.h
Normal file
27
src/thread/os2/SDL_syscond_c.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
115
src/thread/os2/SDL_sysmutex.c
Normal file
115
src/thread/os2/SDL_sysmutex.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* Mutex functions using the OS/2 API */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#include <os2.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
|
||||
struct SDL_mutex {
|
||||
HMTX hmtxID;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
APIRET ulrc;
|
||||
|
||||
/* Allocate mutex memory */
|
||||
mutex = (SDL_mutex *)malloc(sizeof(*mutex));
|
||||
if (mutex)
|
||||
{
|
||||
/* Create the mutex, with initial value signaled */
|
||||
ulrc = DosCreateMutexSem(NULL, // Create unnamed semaphore
|
||||
&(mutex->hmtxID), // Pointer to handle
|
||||
0L, // Flags: create it private (not shared)
|
||||
FALSE); // Initial value: unowned
|
||||
if (ulrc!=NO_ERROR)
|
||||
{
|
||||
SDL_SetError("Couldn't create mutex");
|
||||
free(mutex);
|
||||
mutex = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return(mutex);
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
|
||||
{
|
||||
if ( mutex )
|
||||
{
|
||||
if ( mutex->hmtxID )
|
||||
{
|
||||
DosCloseMutexSem(mutex->hmtxID);
|
||||
mutex->hmtxID = 0;
|
||||
}
|
||||
free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex)
|
||||
{
|
||||
if ( mutex == NULL )
|
||||
{
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if ( DosRequestMutexSem(mutex->hmtxID, SEM_INDEFINITE_WAIT) != NO_ERROR )
|
||||
{
|
||||
SDL_SetError("Couldn't wait on mutex");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex)
|
||||
{
|
||||
if ( mutex == NULL )
|
||||
{
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if ( DosReleaseMutexSem(mutex->hmtxID) != NO_ERROR )
|
||||
{
|
||||
SDL_SetError("Couldn't release mutex");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
}
|
199
src/thread/os2/SDL_syssem.c
Normal file
199
src/thread/os2/SDL_syssem.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* Semaphore functions using the OS/2 API */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#include <os2.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
|
||||
struct SDL_semaphore {
|
||||
HMTX id;
|
||||
HEV changed;
|
||||
Uint32 value;
|
||||
};
|
||||
|
||||
|
||||
/* Create a semaphore */
|
||||
DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
ULONG ulrc;
|
||||
|
||||
/* Allocate sem memory */
|
||||
sem = (SDL_sem *)malloc(sizeof(*sem));
|
||||
if ( sem ) {
|
||||
/* Create the mutex semaphore */
|
||||
ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE);
|
||||
if ( ulrc ) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
free(sem);
|
||||
sem = NULL;
|
||||
} else
|
||||
{
|
||||
DosCreateEventSem(NULL, &(sem->changed), 0, FALSE);
|
||||
sem->value = initial_value;
|
||||
DosReleaseMutexSem(sem->id);
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return(sem);
|
||||
}
|
||||
|
||||
/* Free the semaphore */
|
||||
DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
|
||||
{
|
||||
if ( sem ) {
|
||||
if ( sem->id ) {
|
||||
DosCloseEventSem(sem->changed);
|
||||
DosCloseMutexSem(sem->id);
|
||||
sem->id = 0;
|
||||
}
|
||||
free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
{
|
||||
ULONG ulrc;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( timeout == SDL_MUTEX_MAXWAIT ) {
|
||||
while (1) {
|
||||
ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
|
||||
if (ulrc) {
|
||||
/* if error waiting mutex */
|
||||
SDL_SetError("DosRequestMutexSem() failed");
|
||||
return -1;
|
||||
} else if (sem->value) {
|
||||
sem->value--;
|
||||
DosReleaseMutexSem(sem->id);
|
||||
return 0;
|
||||
} else {
|
||||
ULONG ulPostCount;
|
||||
DosResetEventSem(sem->changed, &ulPostCount);
|
||||
DosReleaseMutexSem(sem->id);
|
||||
/* continue waiting until somebody posts the semaphore */
|
||||
DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT);
|
||||
}
|
||||
}
|
||||
} else
|
||||
if ( timeout == 0 )
|
||||
{
|
||||
ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
|
||||
if (ulrc==NO_ERROR)
|
||||
{
|
||||
if (sem->value)
|
||||
{
|
||||
sem->value--;
|
||||
DosReleaseMutexSem(sem->id);
|
||||
return 0;
|
||||
} else
|
||||
{
|
||||
DosReleaseMutexSem(sem->id);
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
}
|
||||
} else
|
||||
{
|
||||
SDL_SetError("DosRequestMutexSem() failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
|
||||
if (ulrc) {
|
||||
/* if error waiting mutex */
|
||||
SDL_SetError("DosRequestMutexSem() failed");
|
||||
return -1;
|
||||
} else
|
||||
if (sem->value) {
|
||||
sem->value--;
|
||||
DosReleaseMutexSem(sem->id);
|
||||
return 0;
|
||||
} else {
|
||||
ULONG ulPostCount;
|
||||
DosResetEventSem(sem->changed, &ulPostCount);
|
||||
DosReleaseMutexSem(sem->id);
|
||||
/* continue waiting until somebody posts the semaphore */
|
||||
ulrc = DosWaitEventSem(sem->changed, timeout);
|
||||
if (ulrc==NO_ERROR)
|
||||
return 0;
|
||||
else
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
}
|
||||
}
|
||||
/* never reached */
|
||||
return -1;
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return sem->value;
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) {
|
||||
SDL_SetError("DosRequestMutexSem() failed");
|
||||
return -1;
|
||||
}
|
||||
sem->value++;
|
||||
DosPostEventSem(sem->changed);
|
||||
DosReleaseMutexSem(sem->id);
|
||||
return 0;
|
||||
}
|
114
src/thread/os2/SDL_systhread.c
Normal file
114
src/thread/os2/SDL_systhread.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
/* OS/2 thread management routines for SDL */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <process.h>
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread.h"
|
||||
|
||||
typedef struct ThreadStartParms
|
||||
{
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
} tThreadStartParms, *pThreadStartParms;
|
||||
|
||||
static void threadfunc(void *pparm)
|
||||
{
|
||||
pThreadStartParms pThreadParms = pparm;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
|
||||
// Call the thread function!
|
||||
SDL_RunThread(pThreadParms->args);
|
||||
|
||||
// Get the current endthread we have to use!
|
||||
if (pThreadParms)
|
||||
{
|
||||
pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
|
||||
free(pThreadParms);
|
||||
}
|
||||
// Call endthread!
|
||||
if (pfnCurrentEndThread)
|
||||
(*pfnCurrentEndThread)();
|
||||
}
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
|
||||
{
|
||||
pThreadStartParms pThreadParms = malloc(sizeof(tThreadStartParms));
|
||||
if (!pThreadParms)
|
||||
{
|
||||
SDL_SetError("Not enough memory to create thread");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Save the function which we will have to call to clear the RTL of calling app!
|
||||
pThreadParms->pfnCurrentEndThread = pfnEndThread;
|
||||
// Also save the real parameters we have to pass to thread function
|
||||
pThreadParms->args = args;
|
||||
// Start the thread using the runtime library of calling app!
|
||||
thread->threadid = thread->handle = (*pfnBeginThread)(threadfunc, 512*1024, pThreadParms);
|
||||
if (thread->threadid<=0)
|
||||
{
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DECLSPEC Uint32 SDLCALL SDL_ThreadID(void)
|
||||
{
|
||||
PTIB tib;
|
||||
DosGetInfoBlocks(&tib, NULL);
|
||||
return((Uint32) (tib->tib_ptib2->tib2_ultid));
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
{
|
||||
TID tid = thread->handle;
|
||||
DosWaitThread(&tid, DCWW_WAIT);
|
||||
}
|
||||
|
||||
/* WARNING: This function is really a last resort.
|
||||
* Threads should be signaled and then exit by themselves.
|
||||
* TerminateThread() doesn't perform stack and DLL cleanup.
|
||||
*/
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
{
|
||||
DosKillThread(thread->handle);
|
||||
}
|
27
src/thread/os2/SDL_systhread_c.h
Normal file
27
src/thread/os2/SDL_systhread_c.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
|
||||
typedef TID SYS_ThreadHandle;
|
||||
|
27
src/timer/Makefile.wat
Normal file
27
src/timer/Makefile.wat
Normal file
|
@ -0,0 +1,27 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for timers
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_timer.obj SDL_systimer.obj
|
||||
ExtraCFlags=
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;./os2;../;
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
SDL_systimer.obj: .AUTODEPEND
|
||||
wcc386 os2\SDL_systimer.c $(cflags)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
|
@ -242,7 +242,7 @@ SDL_bool SDL_RemoveTimer(SDL_TimerID id)
|
|||
}
|
||||
|
||||
/* Old style callback functions are wrapped through this */
|
||||
static Uint32 callback_wrapper(Uint32 ms, void *param)
|
||||
static Uint32 SDLCALL callback_wrapper(Uint32 ms, void *param)
|
||||
{
|
||||
SDL_TimerCallback func = (SDL_TimerCallback) param;
|
||||
return (*func)(ms);
|
||||
|
|
230
src/timer/os2/SDL_systimer.c
Normal file
230
src/timer/os2/SDL_systimer.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
#define INCL_DOSMISC
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSDATETIME
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSPROFILE
|
||||
#define INCL_DOSEXCEPTIONS
|
||||
#include <os2.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_timer_c.h"
|
||||
#include "SDL_error.h"
|
||||
|
||||
|
||||
#define TIME_WRAP_VALUE (~(DWORD)0)
|
||||
|
||||
/* The first high-resolution ticks value of the application */
|
||||
static long long hires_start_ticks;
|
||||
/* The number of ticks per second of the high-resolution performance counter */
|
||||
static ULONG hires_ticks_per_second;
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
DosTmrQueryFreq(&hires_ticks_per_second);
|
||||
DosTmrQueryTime((PQWORD)&hires_start_ticks);
|
||||
}
|
||||
|
||||
DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
|
||||
{
|
||||
long long hires_now;
|
||||
ULONG ticks = ticks;
|
||||
|
||||
DosTmrQueryTime((PQWORD)&hires_now);
|
||||
/*
|
||||
hires_now -= hires_start_ticks;
|
||||
hires_now *= 1000;
|
||||
hires_now /= hires_ticks_per_second;
|
||||
*/
|
||||
/* inline asm to avoid runtime inclusion */
|
||||
_asm {
|
||||
push edx
|
||||
push eax
|
||||
mov eax, dword ptr hires_now
|
||||
mov edx, dword ptr hires_now+4
|
||||
sub eax, dword ptr hires_start_ticks
|
||||
sbb edx, dword ptr hires_start_ticks+4
|
||||
mov ebx,1000
|
||||
mov ecx,edx
|
||||
mul ebx
|
||||
push eax
|
||||
push edx
|
||||
mov eax,ecx
|
||||
mul ebx
|
||||
pop eax
|
||||
add edx,eax
|
||||
pop eax
|
||||
mov ebx, dword ptr hires_ticks_per_second
|
||||
div ebx
|
||||
mov dword ptr ticks, eax
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
|
||||
return ticks;
|
||||
|
||||
}
|
||||
|
||||
/* High resolution sleep, originally made by Ilya Zakharevich */
|
||||
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
|
||||
{
|
||||
/* This is similar to DosSleep(), but has 8ms granularity in time-critical
|
||||
threads even on Warp3. */
|
||||
HEV hevEvent1 = 0; /* Event semaphore handle */
|
||||
HTIMER htimerEvent1 = 0; /* Timer handle */
|
||||
APIRET rc = NO_ERROR; /* Return code */
|
||||
int ret = 1;
|
||||
ULONG priority = 0, nesting; /* Shut down the warnings */
|
||||
PPIB pib;
|
||||
PTIB tib;
|
||||
char *e = NULL;
|
||||
APIRET badrc;
|
||||
int switch_priority = 50;
|
||||
|
||||
DosCreateEventSem(NULL, /* Unnamed */
|
||||
&hevEvent1, /* Handle of semaphore returned */
|
||||
DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */
|
||||
FALSE); /* Semaphore is in RESET state */
|
||||
|
||||
if (ms >= switch_priority)
|
||||
switch_priority = 0;
|
||||
if (switch_priority)
|
||||
{
|
||||
if (DosGetInfoBlocks(&tib, &pib)!=NO_ERROR)
|
||||
switch_priority = 0;
|
||||
else
|
||||
{
|
||||
/* In Warp3, to switch scheduling to 8ms step, one needs to do
|
||||
DosAsyncTimer() in time-critical thread. On laters versions,
|
||||
more and more cases of wait-for-something are covered.
|
||||
|
||||
It turns out that on Warp3fp42 it is the priority at the time
|
||||
of DosAsyncTimer() which matters. Let's hope that this works
|
||||
with later versions too... XXXX
|
||||
*/
|
||||
priority = (tib->tib_ptib2->tib2_ulpri);
|
||||
if ((priority & 0xFF00) == 0x0300) /* already time-critical */
|
||||
switch_priority = 0;
|
||||
/* Make us time-critical. Just modifying TIB is not enough... */
|
||||
/* tib->tib_ptib2->tib2_ulpri = 0x0300;*/
|
||||
/* We do not want to run at high priority if a signal causes us
|
||||
to longjmp() out of this section... */
|
||||
if (DosEnterMustComplete(&nesting))
|
||||
switch_priority = 0;
|
||||
else
|
||||
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((badrc = DosAsyncTimer(ms,
|
||||
(HSEM) hevEvent1, /* Semaphore to post */
|
||||
&htimerEvent1))) /* Timer handler (returned) */
|
||||
e = "DosAsyncTimer";
|
||||
|
||||
if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300)
|
||||
{
|
||||
/* Nobody switched priority while we slept... Ignore errors... */
|
||||
/* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */
|
||||
if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0)))
|
||||
rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0);
|
||||
}
|
||||
if (switch_priority)
|
||||
rc = DosExitMustComplete(&nesting); /* Ignore errors */
|
||||
|
||||
/* The actual blocking call is made with "normal" priority. This way we
|
||||
should not bother with DosSleep(0) etc. to compensate for us interrupting
|
||||
higher-priority threads. The goal is to prohibit the system spending too
|
||||
much time halt()ing, not to run us "no matter what". */
|
||||
if (!e) /* Wait for AsyncTimer event */
|
||||
badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT);
|
||||
|
||||
if (e) ; /* Do nothing */
|
||||
else if (badrc == ERROR_INTERRUPT)
|
||||
ret = 0;
|
||||
else if (badrc)
|
||||
e = "DosWaitEventSem";
|
||||
if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */
|
||||
e = "DosCloseEventSem";
|
||||
badrc = rc;
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
SDL_SetError("[SDL_Delay] : Had error in %s(), rc is 0x%x\n", e, badrc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: OS/2 uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
27
src/video/Makefile.wat
Normal file
27
src/video/Makefile.wat
Normal file
|
@ -0,0 +1,27 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for threading
|
||||
#=============================================================================
|
||||
|
||||
object_files=SDL_blit.obj SDL_blit_0.obj SDL_blit_1.obj SDL_blit_A.obj SDL_blit_N.obj SDL_bmp.obj SDL_cursor.obj SDL_gamma.obj SDL_pixels.obj SDL_RLEaccel.obj SDL_stretch.obj SDL_surface.obj SDL_video.obj SDL_yuv.obj SDL_yuv_mmx.obj SDL_yuv_sw.obj SDL_os2fslib.obj
|
||||
ExtraCFlags=-dUSE_DOSSETPRIORITY
|
||||
|
||||
#
|
||||
#==============================================================================
|
||||
#
|
||||
!include ..\..\Watcom.mif
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../../include;../;./os2;../events;../hermes;$(%FSLIB);
|
||||
|
||||
all : $(object_files)
|
||||
|
||||
SDL_os2fslib.obj : .AUTODEPEND
|
||||
wcc386 os2fslib\SDL_os2fslib.c $(cflags)
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
|
@ -423,6 +423,9 @@ extern VideoBootStrap DC_bootstrap;
|
|||
#ifdef ENABLE_RISCOS
|
||||
extern VideoBootStrap RISCOS_bootstrap;
|
||||
#endif
|
||||
#ifdef __OS2__
|
||||
extern VideoBootStrap OS2FSLib_bootstrap;
|
||||
#endif
|
||||
/* This is the current video device */
|
||||
extern SDL_VideoDevice *current_video;
|
||||
|
||||
|
|
|
@ -126,6 +126,9 @@ static VideoBootStrap *bootstrap[] = {
|
|||
#ifdef ENABLE_RISCOS
|
||||
&RISCOS_bootstrap,
|
||||
#endif
|
||||
#ifdef __OS2__
|
||||
&OS2FSLib_bootstrap,
|
||||
#endif
|
||||
#ifdef ENABLE_DUMMYVIDEO
|
||||
&DUMMY_bootstrap,
|
||||
#endif
|
||||
|
@ -664,7 +667,10 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
|
|||
SDL_VideoSurface = NULL; /* In case it's freed by driver */
|
||||
mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
|
||||
if ( mode ) { /* Prevent resize events from mode change */
|
||||
/* But not on OS/2 */
|
||||
#ifndef __OS2__
|
||||
SDL_PrivateResize(mode->w, mode->h);
|
||||
#endif
|
||||
|
||||
/* Sam - If we asked for OpenGL mode, and didn't get it, fail */
|
||||
if ( is_opengl && !(mode->flags & SDL_OPENGL) ) {
|
||||
|
|
2787
src/video/os2fslib/SDL_os2fslib.c
Normal file
2787
src/video/os2fslib/SDL_os2fslib.c
Normal file
File diff suppressed because it is too large
Load diff
63
src/video/os2fslib/SDL_os2fslib.h
Normal file
63
src/video/os2fslib/SDL_os2fslib.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifndef _SDL_os2fslib_h
|
||||
#define _SDL_os2fslib_h
|
||||
|
||||
|
||||
// OS2 specific includes
|
||||
#define INCL_TYPES
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_WIN
|
||||
#define INCL_GPI
|
||||
#include <os2.h>
|
||||
|
||||
#include <FSLib.h>
|
||||
|
||||
/* Hidden "this" pointer for the video functions */
|
||||
#define _THIS SDL_VideoDevice *_this
|
||||
|
||||
/* Private display data */
|
||||
struct SDL_PrivateVideoData
|
||||
{
|
||||
FSLib_VideoMode_p pAvailableFSLibVideoModes;
|
||||
SDL_Rect **pListModesResult; // Allocated memory to return list of modes for os2fslib_ListModes() API
|
||||
|
||||
FSLib_VideoMode SrcBufferDesc; // Description of current source image buffer
|
||||
char *pchSrcBuffer; // The source image buffer itself
|
||||
SDL_Surface *pSDLSurface; // The SDL surface describing the buffer
|
||||
HMTX hmtxUseSrcBuffer; // Mutex semaphore to manipulate src buffer
|
||||
HWND hwndFrame, hwndClient; // Window handle of frame and client
|
||||
int iPMThreadStatus; // 0: Not running
|
||||
// 1: Running
|
||||
// Other: Not running, had an error
|
||||
int tidPMThread; // Thread ID of PM Thread
|
||||
int fInFocus; // True if we're in focus!
|
||||
int iSkipWMMOUSEMOVE; // Number of WM_MOUSEMOVE messages to skip!
|
||||
int iMouseVisible; //
|
||||
};
|
||||
|
||||
extern DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF);
|
||||
|
||||
#endif /* _SDL_os2fslib_h */
|
79
src/video/os2fslib/SDL_vkeys.h
Normal file
79
src/video/os2fslib/SDL_vkeys.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
#ifndef VK_0
|
||||
#define VK_0 '0'
|
||||
#define VK_1 '1'
|
||||
#define VK_2 '2'
|
||||
#define VK_3 '3'
|
||||
#define VK_4 '4'
|
||||
#define VK_5 '5'
|
||||
#define VK_6 '6'
|
||||
#define VK_7 '7'
|
||||
#define VK_8 '8'
|
||||
#define VK_9 '9'
|
||||
#define VK_A 'A'
|
||||
#define VK_B 'B'
|
||||
#define VK_C 'C'
|
||||
#define VK_D 'D'
|
||||
#define VK_E 'E'
|
||||
#define VK_F 'F'
|
||||
#define VK_G 'G'
|
||||
#define VK_H 'H'
|
||||
#define VK_I 'I'
|
||||
#define VK_J 'J'
|
||||
#define VK_K 'K'
|
||||
#define VK_L 'L'
|
||||
#define VK_M 'M'
|
||||
#define VK_N 'N'
|
||||
#define VK_O 'O'
|
||||
#define VK_P 'P'
|
||||
#define VK_Q 'Q'
|
||||
#define VK_R 'R'
|
||||
#define VK_S 'S'
|
||||
#define VK_T 'T'
|
||||
#define VK_U 'U'
|
||||
#define VK_V 'V'
|
||||
#define VK_W 'W'
|
||||
#define VK_X 'X'
|
||||
#define VK_Y 'Y'
|
||||
#define VK_Z 'Z'
|
||||
#endif /* VK_0 */
|
||||
|
||||
/* These keys haven't been defined, but were experimentally determined */
|
||||
#define VK_SEMICOLON 0xBA
|
||||
#define VK_EQUALS 0xBB
|
||||
#define VK_COMMA 0xBC
|
||||
#define VK_MINUS 0xBD
|
||||
#define VK_PERIOD 0xBE
|
||||
#define VK_SLASH 0xBF
|
||||
#define VK_GRAVE 0xC0
|
||||
#define VK_LBRACKET 0xDB
|
||||
#define VK_BACKSLASH 0xDC
|
||||
#define VK_RBRACKET 0xDD
|
||||
#define VK_APOSTROPHE 0xDE
|
||||
#define VK_BACKTICK 0xDF
|
52
test/Makefile.wat
Normal file
52
test/Makefile.wat
Normal file
|
@ -0,0 +1,52 @@
|
|||
#=============================================================================
|
||||
# This is a Watcom makefile to build SDL.DLL for OS/2
|
||||
#
|
||||
# Makefile for test applications
|
||||
#=============================================================================
|
||||
|
||||
# Create debug build or not?
|
||||
debug_build=defined
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# The next part is somewhat general, for creation of EXE files.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
cflags = $(debugflags) -bm -bt=OS2 -5 -fpi -sg -otexan -wx -ei
|
||||
|
||||
.before
|
||||
set include=$(%os2tk)\h;$(%include);../include
|
||||
|
||||
.extensions:
|
||||
.extensions: .exe .obj .c
|
||||
|
||||
all : testalpha.exe &
|
||||
testbitmap.exe &
|
||||
testcdrom.exe &
|
||||
testcpuinfo.exe &
|
||||
testjoystick.exe &
|
||||
testkeys.exe &
|
||||
testlock.exe &
|
||||
testsem.exe &
|
||||
testsprite.exe &
|
||||
testtimer.exe &
|
||||
testtypes.exe &
|
||||
testver.exe &
|
||||
testvidinfo.exe &
|
||||
testwin.exe &
|
||||
testwm.exe &
|
||||
threadwin.exe &
|
||||
torturethread.exe &
|
||||
checkkeys.exe
|
||||
|
||||
.c.obj : .AUTODEPEND
|
||||
wcc386 -zq -bm -5s -ei -oteaxan -wx $[* $(cflags)
|
||||
|
||||
.obj.exe : .AUTODEPEND
|
||||
wlink system os2v2 F $* L ..\src\sdl.lib name $@ op quiet
|
||||
|
||||
clean : .SYMBOLIC
|
||||
@if exist *.exe del *.exe
|
||||
@if exist *.obj del *.obj
|
||||
@if exist *.map del *.map
|
||||
@if exist *.res del *.res
|
||||
@if exist *.lst del *.lst
|
Loading…
Add table
Add a link
Reference in a new issue