From a44e4e17d539e163714a562f2d98a554a3ef40d2 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 13 Nov 2020 12:02:37 +0300 Subject: [PATCH 01/41] Imported MojoAL, link SDL and SDL_sound in MSVS project SDL2: general backend; SDL_Sound: for reading and decoding sound formats; MojoAL: a SDL-based implementation of OpenAL API. --- Solutions/Common.Lib/Common.Lib.vcxproj | 59 +- Solutions/Engine.App/Engine.App.vcxproj | 80 +- .../Engine.App/Engine.App.vcxproj.filters | 15 + Solutions/Engine.sln | 5 - Solutions/sdl2.props | 17 + libsrc/mojoAL/.hg_archival.txt | 6 + libsrc/mojoAL/AL/al.h | 663 +++ libsrc/mojoAL/AL/alc.h | 241 + libsrc/mojoAL/LICENSE.txt | 23 + libsrc/mojoAL/mojoal.c | 4591 +++++++++++++++++ 10 files changed, 5583 insertions(+), 117 deletions(-) create mode 100644 Solutions/sdl2.props create mode 100644 libsrc/mojoAL/.hg_archival.txt create mode 100644 libsrc/mojoAL/AL/al.h create mode 100644 libsrc/mojoAL/AL/alc.h create mode 100644 libsrc/mojoAL/LICENSE.txt create mode 100644 libsrc/mojoAL/mojoal.c diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj b/Solutions/Common.Lib/Common.Lib.vcxproj index 82b47535434..b9898f00a95 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj +++ b/Solutions/Common.Lib/Common.Lib.vcxproj @@ -17,10 +17,6 @@ Release_MD Win32 - - Release_NoMP3 - Win32 - Release_XP Win32 @@ -48,12 +44,6 @@ Unicode true - - StaticLibrary - v140 - Unicode - true - StaticLibrary v140 @@ -82,30 +72,32 @@ + - - - - + + + + + @@ -143,14 +135,6 @@ - - $(SolutionDir)\.lib\$(Configuration)\ - $(Configuration)\ - Common - MinimumRecommendedRules.ruleset - - - $(SolutionDir)\.lib\$(Configuration)\ $(Configuration)\ @@ -170,7 +154,7 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks @@ -189,7 +173,7 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks @@ -210,7 +194,7 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -229,7 +213,7 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -245,30 +229,11 @@ $(OutDir)$(TargetName)$(TargetExt) - - - MaxSpeed - true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;NO_MP3_PLAYER;%(PreprocessorDefinitions) - MultiThreaded - true - - Level3 - ProgramDatabase - 4996;%(DisableSpecificWarnings) - true - 4013; 4150; 4477 - - - $(OutDir)$(TargetName)$(TargetExt) - - MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -286,7 +251,7 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\Windows\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 297574c6b23..2e510665736 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -9,10 +9,6 @@ Debug Win32 - - Release_NoMP3 - Win32 - Release_XP Win32 @@ -29,12 +25,6 @@ 8.1 - - Application - v140 - MultiByte - true - Application v140 @@ -60,14 +50,6 @@ - - - - - - - - @@ -75,6 +57,7 @@ + @@ -83,6 +66,7 @@ + @@ -91,6 +75,7 @@ + @@ -99,6 +84,7 @@ + @@ -128,16 +114,10 @@ false acwin - - $(SolutionDir)\.build\$(Configuration)\ - $(Configuration)\ - false - acwin - Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Windows\include;..\..\Engine\libsrc\glad\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks @@ -150,7 +130,7 @@ 4013; 4150; 4477 - Common_d.lib;alleg-debug-static-mt.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) @@ -165,7 +145,7 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Windows\include;..\..\Engine\libsrc\glad\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks @@ -179,7 +159,7 @@ 4013; 4150; 4477 - Common_d.lib;alleg-debug-static-mt.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) @@ -195,7 +175,7 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Windows\include;..\..\Engine\libsrc\glad\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -207,7 +187,7 @@ 4013; 4150; 4477 - Common.lib;alleg-static-mt.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common.lib;alleg-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) @@ -228,7 +208,7 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Windows\include;..\..\Engine\libsrc\glad\include;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -241,7 +221,7 @@ 4013; 4150; 4477 - Common.lib;alleg-static-mt.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common.lib;alleg-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) @@ -260,39 +240,6 @@ true - - - MaxSpeed - true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Windows\include;..\..\Engine\libsrc\glad\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;NO_MP3_PLAYER;%(PreprocessorDefinitions) - MultiThreaded - true - - Level3 - ProgramDatabase - 4996;%(DisableSpecificWarnings) - true - 4013; 4150; 4477 - - - Common.lib;alleg-static-mt.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) - LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) - true - true - Windows - true - - false - - MachineX86 - - - true - - @@ -579,6 +526,7 @@ + @@ -873,6 +821,8 @@ + + diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index e0bbfa9f208..c5a8046a04e 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -175,6 +175,12 @@ {c3e78d00-def2-49a7-9fa4-d5f693d14655} + + {b04763fd-6213-43f6-8309-fd556b59eadd} + + + {c683eef3-2c8f-4b45-af32-2423f41102ad} + @@ -1032,6 +1038,9 @@ Source Files\ac + + Library Sources\MojoAL + @@ -1910,6 +1919,12 @@ Header Files\ac + + Library Sources\MojoAL\AL + + + Library Sources\MojoAL\AL + diff --git a/Solutions/Engine.sln b/Solutions/Engine.sln index 4acb1620f68..da2fdd1c2e0 100644 --- a/Solutions/Engine.sln +++ b/Solutions/Engine.sln @@ -14,7 +14,6 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_XP|Win32 = Debug_XP|Win32 Debug|Win32 = Debug|Win32 - Release_NoMP3|Win32 = Release_NoMP3|Win32 Release_XP|Win32 = Release_XP|Win32 Release|Win32 = Release|Win32 EndGlobalSection @@ -23,8 +22,6 @@ Global {463A715C-3EF3-47C7-AC7F-D97660149C49}.Debug_XP|Win32.Build.0 = Debug_XP|Win32 {463A715C-3EF3-47C7-AC7F-D97660149C49}.Debug|Win32.ActiveCfg = Debug|Win32 {463A715C-3EF3-47C7-AC7F-D97660149C49}.Debug|Win32.Build.0 = Debug|Win32 - {463A715C-3EF3-47C7-AC7F-D97660149C49}.Release_NoMP3|Win32.ActiveCfg = Release_NoMP3|Win32 - {463A715C-3EF3-47C7-AC7F-D97660149C49}.Release_NoMP3|Win32.Build.0 = Release_NoMP3|Win32 {463A715C-3EF3-47C7-AC7F-D97660149C49}.Release_XP|Win32.ActiveCfg = Release_XP|Win32 {463A715C-3EF3-47C7-AC7F-D97660149C49}.Release_XP|Win32.Build.0 = Release_XP|Win32 {463A715C-3EF3-47C7-AC7F-D97660149C49}.Release|Win32.ActiveCfg = Release|Win32 @@ -33,8 +30,6 @@ Global {49A909AF-49F3-451D-B6DF-839159E54A01}.Debug_XP|Win32.Build.0 = Debug_XP|Win32 {49A909AF-49F3-451D-B6DF-839159E54A01}.Debug|Win32.ActiveCfg = Debug|Win32 {49A909AF-49F3-451D-B6DF-839159E54A01}.Debug|Win32.Build.0 = Debug|Win32 - {49A909AF-49F3-451D-B6DF-839159E54A01}.Release_NoMP3|Win32.ActiveCfg = Release_NoMP3|Win32 - {49A909AF-49F3-451D-B6DF-839159E54A01}.Release_NoMP3|Win32.Build.0 = Release_NoMP3|Win32 {49A909AF-49F3-451D-B6DF-839159E54A01}.Release_XP|Win32.ActiveCfg = Release_XP|Win32 {49A909AF-49F3-451D-B6DF-839159E54A01}.Release_XP|Win32.Build.0 = Release_XP|Win32 {49A909AF-49F3-451D-B6DF-839159E54A01}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/Solutions/sdl2.props b/Solutions/sdl2.props new file mode 100644 index 00000000000..aaf7e2286ff --- /dev/null +++ b/Solutions/sdl2.props @@ -0,0 +1,17 @@ + + + + + + <_PropertySheetDisplayName>libsdl2 + + + + $(AGS_SDL_INCLUDE);$(AGS_SDL_SOUND_INCLUDE);%(AdditionalIncludeDirectories) + + + $(AGS_SDL_LIB);$(AGS_SDL_SOUND_LIB);%(AdditionalLibraryDirectories) + + + + \ No newline at end of file diff --git a/libsrc/mojoAL/.hg_archival.txt b/libsrc/mojoAL/.hg_archival.txt new file mode 100644 index 00000000000..1bb11d5b61b --- /dev/null +++ b/libsrc/mojoAL/.hg_archival.txt @@ -0,0 +1,6 @@ +repo: ac5f3251418d4cf2e05eab2fcb5f30e4f11b5cc5 +node: c5b9b489f7b062abcf364f5c4074656b6178860c +branch: default +latesttag: null +latesttagdistance: 120 +changessincelatesttag: 120 diff --git a/libsrc/mojoAL/AL/al.h b/libsrc/mojoAL/AL/al.h new file mode 100644 index 00000000000..34e35d5b359 --- /dev/null +++ b/libsrc/mojoAL/AL/al.h @@ -0,0 +1,663 @@ +#ifndef AL_AL_H +#define AL_AL_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef AL_API + #if defined(AL_LIBTYPE_STATIC) + #define AL_API + #elif defined(_WIN32) + #define AL_API __declspec(dllimport) + #else + #define AL_API extern + #endif +#endif + +#if defined(_WIN32) + #define AL_APIENTRY __cdecl +#else + #define AL_APIENTRY +#endif + + +/** Deprecated macro. */ +#define OPENAL +#define ALAPI AL_API +#define ALAPIENTRY AL_APIENTRY +#define AL_INVALID (-1) +#define AL_ILLEGAL_ENUM AL_INVALID_ENUM +#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION + +/** Supported AL version. */ +#define AL_VERSION_1_0 +#define AL_VERSION_1_1 + +/** 8-bit boolean */ +typedef char ALboolean; + +/** character */ +typedef char ALchar; + +/** signed 8-bit 2's complement integer */ +typedef signed char ALbyte; + +/** unsigned 8-bit integer */ +typedef unsigned char ALubyte; + +/** signed 16-bit 2's complement integer */ +typedef short ALshort; + +/** unsigned 16-bit integer */ +typedef unsigned short ALushort; + +/** signed 32-bit 2's complement integer */ +typedef int ALint; + +/** unsigned 32-bit integer */ +typedef unsigned int ALuint; + +/** non-negative 32-bit binary integer size */ +typedef int ALsizei; + +/** enumerated 32-bit value */ +typedef int ALenum; + +/** 32-bit IEEE754 floating-point */ +typedef float ALfloat; + +/** 64-bit IEEE754 floating-point */ +typedef double ALdouble; + +/** void type (for opaque pointers only) */ +typedef void ALvoid; + + +/* Enumerant values begin at column 50. No tabs. */ + +/** "no distance model" or "no buffer" */ +#define AL_NONE 0 + +/** Boolean False. */ +#define AL_FALSE 0 + +/** Boolean True. */ +#define AL_TRUE 1 + + +/** + * Relative source. + * Type: ALboolean + * Range: [AL_TRUE, AL_FALSE] + * Default: AL_FALSE + * + * Specifies if the Source has relative coordinates. + */ +#define AL_SOURCE_RELATIVE 0x202 + + +/** + * Inner cone angle, in degrees. + * Type: ALint, ALfloat + * Range: [0 - 360] + * Default: 360 + * + * The angle covered by the inner cone, where the source will not attenuate. + */ +#define AL_CONE_INNER_ANGLE 0x1001 + +/** + * Outer cone angle, in degrees. + * Range: [0 - 360] + * Default: 360 + * + * The angle covered by the outer cone, where the source will be fully + * attenuated. + */ +#define AL_CONE_OUTER_ANGLE 0x1002 + +/** + * Source pitch. + * Type: ALfloat + * Range: [0.5 - 2.0] + * Default: 1.0 + * + * A multiplier for the frequency (sample rate) of the source's buffer. + */ +#define AL_PITCH 0x1003 + +/** + * Source or listener position. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * The source or listener location in three dimensional space. + * + * OpenAL, like OpenGL, uses a right handed coordinate system, where in a + * frontal default view X (thumb) points right, Y points up (index finger), and + * Z points towards the viewer/camera (middle finger). + * + * To switch from a left handed coordinate system, flip the sign on the Z + * coordinate. + */ +#define AL_POSITION 0x1004 + +/** + * Source direction. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * Specifies the current direction in local space. + * A zero-length vector specifies an omni-directional source (cone is ignored). + */ +#define AL_DIRECTION 0x1005 + +/** + * Source or listener velocity. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * Specifies the current velocity in local space. + */ +#define AL_VELOCITY 0x1006 + +/** + * Source looping. + * Type: ALboolean + * Range: [AL_TRUE, AL_FALSE] + * Default: AL_FALSE + * + * Specifies whether source is looping. + */ +#define AL_LOOPING 0x1007 + +/** + * Source buffer. + * Type: ALuint + * Range: any valid Buffer. + * + * Specifies the buffer to provide sound samples. + */ +#define AL_BUFFER 0x1009 + +/** + * Source or listener gain. + * Type: ALfloat + * Range: [0.0 - ] + * + * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation + * of about -6dB. Each multiplicaton by 2 equals an amplification of about + * +6dB. + * + * A value of 0.0 is meaningless with respect to a logarithmic scale; it is + * silent. + */ +#define AL_GAIN 0x100A + +/** + * Minimum source gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * The minimum gain allowed for a source, after distance and cone attenation is + * applied (if applicable). + */ +#define AL_MIN_GAIN 0x100D + +/** + * Maximum source gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * The maximum gain allowed for a source, after distance and cone attenation is + * applied (if applicable). + */ +#define AL_MAX_GAIN 0x100E + +/** + * Listener orientation. + * Type: ALfloat[6] + * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0} + * + * Effectively two three dimensional vectors. The first vector is the front (or + * "at") and the second is the top (or "up"). + * + * Both vectors are in local space. + */ +#define AL_ORIENTATION 0x100F + +/** + * Source state (query only). + * Type: ALint + * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED] + */ +#define AL_SOURCE_STATE 0x1010 + +/** Source state value. */ +#define AL_INITIAL 0x1011 +#define AL_PLAYING 0x1012 +#define AL_PAUSED 0x1013 +#define AL_STOPPED 0x1014 + +/** + * Source Buffer Queue size (query only). + * Type: ALint + * + * The number of buffers queued using alSourceQueueBuffers, minus the buffers + * removed with alSourceUnqueueBuffers. + */ +#define AL_BUFFERS_QUEUED 0x1015 + +/** + * Source Buffer Queue processed count (query only). + * Type: ALint + * + * The number of queued buffers that have been fully processed, and can be + * removed with alSourceUnqueueBuffers. + * + * Looping sources will never fully process buffers because they will be set to + * play again for when the source loops. + */ +#define AL_BUFFERS_PROCESSED 0x1016 + +/** + * Source reference distance. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * The distance in units that no attenuation occurs. + * + * At 0.0, no distance attenuation ever occurs on non-linear attenuation models. + */ +#define AL_REFERENCE_DISTANCE 0x1020 + +/** + * Source rolloff factor. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * Multiplier to exaggerate or diminish distance attenuation. + * + * At 0.0, no distance attenuation ever occurs. + */ +#define AL_ROLLOFF_FACTOR 0x1021 + +/** + * Outer cone gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * Default: 0.0 + * + * The gain attenuation applied when the listener is outside of the source's + * outer cone. + */ +#define AL_CONE_OUTER_GAIN 0x1022 + +/** + * Source maximum distance. + * Type: ALfloat + * Range: [0.0 - ] + * Default: +inf + * + * The distance above which the source is not attenuated any further with a + * clamped distance model, or where attenuation reaches 0.0 gain for linear + * distance models with a default rolloff factor. + */ +#define AL_MAX_DISTANCE 0x1023 + +/** Source buffer position, in seconds */ +#define AL_SEC_OFFSET 0x1024 +/** Source buffer position, in sample frames */ +#define AL_SAMPLE_OFFSET 0x1025 +/** Source buffer position, in bytes */ +#define AL_BYTE_OFFSET 0x1026 + +/** + * Source type (query only). + * Type: ALint + * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED] + * + * A Source is Static if a Buffer has been attached using AL_BUFFER. + * + * A Source is Streaming if one or more Buffers have been attached using + * alSourceQueueBuffers. + * + * A Source is Undetermined when it has the NULL buffer attached using + * AL_BUFFER. + */ +#define AL_SOURCE_TYPE 0x1027 + +/** Source type value. */ +#define AL_STATIC 0x1028 +#define AL_STREAMING 0x1029 +#define AL_UNDETERMINED 0x1030 + +/** Buffer format specifier. */ +#define AL_FORMAT_MONO8 0x1100 +#define AL_FORMAT_MONO16 0x1101 +#define AL_FORMAT_STEREO8 0x1102 +#define AL_FORMAT_STEREO16 0x1103 + +/** Buffer frequency (query only). */ +#define AL_FREQUENCY 0x2001 +/** Buffer bits per sample (query only). */ +#define AL_BITS 0x2002 +/** Buffer channel count (query only). */ +#define AL_CHANNELS 0x2003 +/** Buffer data size (query only). */ +#define AL_SIZE 0x2004 + +/** + * Buffer state. + * + * Not for public use. + */ +#define AL_UNUSED 0x2010 +#define AL_PENDING 0x2011 +#define AL_PROCESSED 0x2012 + + +/** No error. */ +#define AL_NO_ERROR 0 + +/** Invalid name paramater passed to AL call. */ +#define AL_INVALID_NAME 0xA001 + +/** Invalid enum parameter passed to AL call. */ +#define AL_INVALID_ENUM 0xA002 + +/** Invalid value parameter passed to AL call. */ +#define AL_INVALID_VALUE 0xA003 + +/** Illegal AL call. */ +#define AL_INVALID_OPERATION 0xA004 + +/** Not enough memory. */ +#define AL_OUT_OF_MEMORY 0xA005 + + +/** Context string: Vendor ID. */ +#define AL_VENDOR 0xB001 +/** Context string: Version. */ +#define AL_VERSION 0xB002 +/** Context string: Renderer ID. */ +#define AL_RENDERER 0xB003 +/** Context string: Space-separated extension list. */ +#define AL_EXTENSIONS 0xB004 + + +/** + * Doppler scale. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * Scale for source and listener velocities. + */ +#define AL_DOPPLER_FACTOR 0xC000 +AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); + +/** + * Doppler velocity (deprecated). + * + * A multiplier applied to the Speed of Sound. + */ +#define AL_DOPPLER_VELOCITY 0xC001 +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); + +/** + * Speed of Sound, in units per second. + * Type: ALfloat + * Range: [0.0001 - ] + * Default: 343.3 + * + * The speed at which sound waves are assumed to travel, when calculating the + * doppler effect. + */ +#define AL_SPEED_OF_SOUND 0xC003 +AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); + +/** + * Distance attenuation model. + * Type: ALint + * Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED, + * AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, + * AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED] + * Default: AL_INVERSE_DISTANCE_CLAMPED + * + * The model by which sources attenuate with distance. + * + * None - No distance attenuation. + * Inverse - Doubling the distance halves the source gain. + * Linear - Linear gain scaling between the reference and max distances. + * Exponent - Exponential gain dropoff. + * + * Clamped variations work like the non-clamped counterparts, except the + * distance calculated is clamped between the reference and max distances. + */ +#define AL_DISTANCE_MODEL 0xD000 +AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); + +/** Distance model value. */ +#define AL_INVERSE_DISTANCE 0xD001 +#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 +#define AL_LINEAR_DISTANCE 0xD003 +#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 +#define AL_EXPONENT_DISTANCE 0xD005 +#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 + +/** Renderer State management. */ +AL_API void AL_APIENTRY alEnable(ALenum capability); +AL_API void AL_APIENTRY alDisable(ALenum capability); +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); + +/** State retrieval. */ +AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); +AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); +AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); +AL_API ALint AL_APIENTRY alGetInteger(ALenum param); +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); + +/** + * Error retrieval. + * + * Obtain the first error generated in the AL context since the last check. + */ +AL_API ALenum AL_APIENTRY alGetError(void); + +/** + * Extension support. + * + * Query for the presence of an extension, and obtain any appropriate function + * pointers and enum values. + */ +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); +AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); + + +/** Set Listener parameters */ +AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); +AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); +AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); +AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); +AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); + +/** Get Listener parameters */ +AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); +AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); +AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); +AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); + + +/** Create Source objects. */ +AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); +/** Delete Source objects. */ +AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); +/** Verify a handle is a valid Source. */ +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); + +/** Set Source parameters. */ +AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); +AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); +AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); + +/** Get Source parameters. */ +AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); +AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); + + +/** Play, replay, or resume (if paused) a list of Sources */ +AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); +/** Stop a list of Sources */ +AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); +/** Rewind a list of Sources */ +AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); +/** Pause a list of Sources */ +AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); + +/** Play, replay, or resume a Source */ +AL_API void AL_APIENTRY alSourcePlay(ALuint source); +/** Stop a Source */ +AL_API void AL_APIENTRY alSourceStop(ALuint source); +/** Rewind a Source (set playback postiton to beginning) */ +AL_API void AL_APIENTRY alSourceRewind(ALuint source); +/** Pause a Source */ +AL_API void AL_APIENTRY alSourcePause(ALuint source); + +/** Queue buffers onto a source */ +AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); +/** Unqueue processed buffers from a source */ +AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); + + +/** Create Buffer objects */ +AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); +/** Delete Buffer objects */ +AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); +/** Verify a handle is a valid Buffer */ +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); + +/** Specifies the data to be copied into a buffer */ +AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); + +/** Set Buffer parameters, */ +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); + +/** Get Buffer parameters. */ +AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); + +/** Pointer-to-function type, useful for dynamically getting AL entry points. */ +typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); +typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); +typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); +typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); +typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); +typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); +typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); +typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); +typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); +typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); +typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); +typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); + +#define AL_EXT_TRACE_INFO 1 +typedef void (AL_APIENTRY *LPALTRACEPUSHSCOPE)(const ALchar *str); +typedef void (AL_APIENTRY *LPALTRACEPOPSCOPE)(void); +typedef void (AL_APIENTRY *LPALTRACEMESSAGE)(const ALchar *str); +typedef void (AL_APIENTRY *LPALTRACEBUFFERLABEL)(ALuint name, const ALchar *str); +typedef void (AL_APIENTRY *LPALTRACESOURCELABEL)(ALuint name, const ALchar *str); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* AL_AL_H */ diff --git a/libsrc/mojoAL/AL/alc.h b/libsrc/mojoAL/AL/alc.h new file mode 100644 index 00000000000..eb503bced1a --- /dev/null +++ b/libsrc/mojoAL/AL/alc.h @@ -0,0 +1,241 @@ +#ifndef AL_ALC_H +#define AL_ALC_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef ALC_API + #if defined(AL_LIBTYPE_STATIC) + #define ALC_API + #elif defined(_WIN32) + #define ALC_API __declspec(dllimport) + #else + #define ALC_API extern + #endif +#endif + +#if defined(_WIN32) + #define ALC_APIENTRY __cdecl +#else + #define ALC_APIENTRY +#endif + + +/** Deprecated macro. */ +#define ALCAPI ALC_API +#define ALCAPIENTRY ALC_APIENTRY +#define ALC_INVALID 0 + +/** Supported ALC version? */ +#define ALC_VERSION_0_1 1 + +/** Opaque device handle */ +typedef struct ALCdevice_struct ALCdevice; +/** Opaque context handle */ +typedef struct ALCcontext_struct ALCcontext; + +/** 8-bit boolean */ +typedef char ALCboolean; + +/** character */ +typedef char ALCchar; + +/** signed 8-bit 2's complement integer */ +typedef signed char ALCbyte; + +/** unsigned 8-bit integer */ +typedef unsigned char ALCubyte; + +/** signed 16-bit 2's complement integer */ +typedef short ALCshort; + +/** unsigned 16-bit integer */ +typedef unsigned short ALCushort; + +/** signed 32-bit 2's complement integer */ +typedef int ALCint; + +/** unsigned 32-bit integer */ +typedef unsigned int ALCuint; + +/** non-negative 32-bit binary integer size */ +typedef int ALCsizei; + +/** enumerated 32-bit value */ +typedef int ALCenum; + +/** 32-bit IEEE754 floating-point */ +typedef float ALCfloat; + +/** 64-bit IEEE754 floating-point */ +typedef double ALCdouble; + +/** void type (for opaque pointers only) */ +typedef void ALCvoid; + + +/* Enumerant values begin at column 50. No tabs. */ + +/** Boolean False. */ +#define ALC_FALSE 0 + +/** Boolean True. */ +#define ALC_TRUE 1 + +/** Context attribute: Hz. */ +#define ALC_FREQUENCY 0x1007 + +/** Context attribute: Hz. */ +#define ALC_REFRESH 0x1008 + +/** Context attribute: AL_TRUE or AL_FALSE. */ +#define ALC_SYNC 0x1009 + +/** Context attribute: requested Mono (3D) Sources. */ +#define ALC_MONO_SOURCES 0x1010 + +/** Context attribute: requested Stereo Sources. */ +#define ALC_STEREO_SOURCES 0x1011 + +/** No error. */ +#define ALC_NO_ERROR 0 + +/** Invalid device handle. */ +#define ALC_INVALID_DEVICE 0xA001 + +/** Invalid context handle. */ +#define ALC_INVALID_CONTEXT 0xA002 + +/** Invalid enum parameter passed to an ALC call. */ +#define ALC_INVALID_ENUM 0xA003 + +/** Invalid value parameter passed to an ALC call. */ +#define ALC_INVALID_VALUE 0xA004 + +/** Out of memory. */ +#define ALC_OUT_OF_MEMORY 0xA005 + + +/** Runtime ALC version. */ +#define ALC_MAJOR_VERSION 0x1000 +#define ALC_MINOR_VERSION 0x1001 + +/** Context attribute list properties. */ +#define ALC_ATTRIBUTES_SIZE 0x1002 +#define ALC_ALL_ATTRIBUTES 0x1003 + +/** String for the default device specifier. */ +#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 +/** + * String for the given device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known device specifiers (list ends with an empty string). + */ +#define ALC_DEVICE_SPECIFIER 0x1005 +/** String for space-separated list of ALC extensions. */ +#define ALC_EXTENSIONS 0x1006 + + +/** Capture extension */ +#define ALC_EXT_CAPTURE 1 +/** + * String for the given capture device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known capture device specifiers (list ends with an empty string). + */ +#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 +/** String for the default capture device specifier. */ +#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 +/** Number of sample frames available for capture. */ +#define ALC_CAPTURE_SAMPLES 0x312 + + +/** Enumerate All extension */ +#define ALC_ENUMERATE_ALL_EXT 1 +/** String for the default extended device specifier. */ +#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 +/** + * String for the given extended device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known extended device specifiers (list ends with an empty string). + */ +#define ALC_ALL_DEVICES_SPECIFIER 0x1013 + + +/** Context management. */ +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist); +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); +ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); + +/** Device management. */ +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); + + +/** + * Error support. + * + * Obtain the most recent Device error. + */ +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); + +/** + * Extension support. + * + * Query for the presence of an extension, and obtain any appropriate + * function pointers and enum values. + */ +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); +ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); + +/** Query function. */ +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); + +/** Capture function. */ +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); + +/** Pointer-to-function type, useful for dynamically getting ALC entry points. */ +typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); +typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); +typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); +typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); +typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); +typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); + +#define ALC_EXT_TRACE_INFO 1 +typedef void (AL_APIENTRY *LPALCTRACEDEVICELABEL)(ALCdevice *device, const ALCchar *str); +typedef void (AL_APIENTRY *LPALCTRACECONTEXTLABEL)(ALCcontext *ctx, const ALCchar *str); + +#if defined(__cplusplus) +} +#endif + +#endif /* AL_ALC_H */ diff --git a/libsrc/mojoAL/LICENSE.txt b/libsrc/mojoAL/LICENSE.txt new file mode 100644 index 00000000000..8c9693e81de --- /dev/null +++ b/libsrc/mojoAL/LICENSE.txt @@ -0,0 +1,23 @@ + + Copyright (c) 2018-2019 Ryan C. Gordon and others. + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from + the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Ryan C. Gordon + diff --git a/libsrc/mojoAL/mojoal.c b/libsrc/mojoAL/mojoal.c new file mode 100644 index 00000000000..30dccbad885 --- /dev/null +++ b/libsrc/mojoAL/mojoal.c @@ -0,0 +1,4591 @@ +/** + * MojoAL; a simple drop-in OpenAL implementation. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +#include +#include +#include + +#ifdef _MSC_VER + #define AL_API __declspec(dllexport) + #define ALC_API __declspec(dllexport) +#endif + +#ifndef M_PI + #define M_PI (3.14159265358979323846264338327950288) +#endif + +#include "AL/al.h" +#include "AL/alc.h" +#include "SDL.h" + +#ifdef __SSE__ /* if you are on x86 or x86-64, we assume you have SSE1 by now. */ +#define NEED_SCALAR_FALLBACK 0 +#elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) /* ARMv8 always has NEON. */ +#define NEED_SCALAR_FALLBACK 0 +#elif (defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) /* All ARMv7 chips from Apple have NEON. */ +#define NEED_SCALAR_FALLBACK 0 +#elif (defined(__WINDOWS__) || defined(__WINRT__)) && defined(_M_ARM) /* all WinRT-level Microsoft devices have NEON */ +#define NEED_SCALAR_FALLBACK 0 +#else +#define NEED_SCALAR_FALLBACK 1 +#endif + +/* Some platforms fail to define __ARM_NEON__, others need it or arm_neon.h will fail. */ +#if (defined(__ARM_ARCH) || defined(_M_ARM)) +# if !NEED_SCALAR_FALLBACK && !defined(__ARM_NEON__) +# define __ARM_NEON__ 1 +# endif +#endif + +#ifdef __SSE__ +#include +#endif + +#ifdef __ARM_NEON__ +#include +#endif + +#define OPENAL_VERSION_MAJOR 1 +#define OPENAL_VERSION_MINOR 1 +#define OPENAL_VERSION_STRING3(major, minor) #major "." #minor +#define OPENAL_VERSION_STRING2(major, minor) OPENAL_VERSION_STRING3(major, minor) + +/* !!! FIXME: make some decisions about VENDOR and RENDERER strings here */ +#define OPENAL_VERSION_STRING OPENAL_VERSION_STRING2(OPENAL_VERSION_MAJOR, OPENAL_VERSION_MINOR) +#define OPENAL_VENDOR_STRING "Ryan C. Gordon" +#define OPENAL_RENDERER_STRING "mojoAL" + +#define DEFAULT_PLAYBACK_DEVICE "Default OpenAL playback device" +#define DEFAULT_CAPTURE_DEVICE "Default OpenAL capture device" + +/* Number of buffers to allocate at once when we need a new block during alGenBuffers(). */ +#ifndef OPENAL_BUFFER_BLOCK_SIZE +#define OPENAL_BUFFER_BLOCK_SIZE 256 +#endif + +/* Number of sources to allocate at once when we need a new block during alGenSources(). */ +#ifndef OPENAL_SOURCE_BLOCK_SIZE +#define OPENAL_SOURCE_BLOCK_SIZE 64 +#endif + +/* AL_EXT_FLOAT32 support... */ +#ifndef AL_FORMAT_MONO_FLOAT32 +#define AL_FORMAT_MONO_FLOAT32 0x10010 +#endif + +#ifndef AL_FORMAT_STEREO_FLOAT32 +#define AL_FORMAT_STEREO_FLOAT32 0x10011 +#endif + +/* ALC_EXT_DISCONNECTED support... */ +#ifndef ALC_CONNECTED +#define ALC_CONNECTED 0x313 +#endif + + +/* +The locking strategy for this OpenAL implementation: + +- The initial work on this implementation attempted to be completely + lock free, and it lead to fragile, overly-clever, and complicated code. + Attempt #2 is making more reasonable tradeoffs. + +- All API entry points are protected by a global mutex, which means that + calls into the API are serialized, but we expect this to not be a + serious problem; most AL calls are likely to come from a single thread + and uncontended mutexes generally aren't very expensive. This mutex + is not shared with the mixer thread, so there is never a point where + an innocent "fast" call into the AL will block because of the bad luck + of a high mixing load and the wrong moment. + +- In rare cases we'll lock the mixer thread for a brief time; when a playing + source is accessible to the mixer, it is flagged as such. The mixer has a + mutex that it holds when mixing a source, and if we need to touch a source + that is flagged as accessible, we'll grab that lock to make sure there isn't + a conflict. Not all source changes need to do this. The likelihood of + hitting this case is extremely small, and the lock hold time is pretty + short. Things that might do this, only on currently-playing sources: + alDeleteSources, alSourceStop, alSourceRewind. alSourcePlay and + alSourcePause never need to lock. + +- Devices are expected to live for the entire life of your OpenAL + experience, so closing one while another thread is using it is your own + fault. Don't do that. Devices are allocated pointers, and the AL doesn't + know if you've deleted it, making the pointer invalid. Device open and + close are not meant to be "fast" calls. + +- Creating or destroying a context will lock the mixer thread completely + (so it isn't running _at all_ during the lock), so we can add/remove the + context on the device's list without racing. So don't do this in + time-critical code. + +- Generating an object (source, buffer, etc) might need to allocate + memory, which can always take longer than you would expect. We allocate in + blocks, so not every call will allocate more memory. Generating an object + does not lock the mixer thread. + +- Deleting a buffer does not lock the mixer thread (in-use buffers can + not be deleted per API spec). Deleting a source will lock the mixer briefly + if the source is still visible to the mixer. We don't believe this will be + a serious issue in normal use cases. Deleted objects' memory is marked for + reuse, but no memory is free'd by deleting sources or buffers until the + context or device, respectively, are destroyed. A deleted source that's + still visible to the mixer will not be available for reallocation until + the mixer runs another iteration, where it will mark it as no longer + visible. If you call alGenSources() during this time, a different source + will be allocated. + +- alBufferData needs to allocate memory to copy new audio data. Often, + you can avoid doing these things in time-critical code. You can't set + a buffer's data when it's attached to a source (either with AL_BUFFER + or buffer queueing), so there's never a chance of contention with the + mixer thread here. + +- Buffers and sources are allocated in blocks of OPENAL_BUFFER_BLOCK_SIZE + (or OPENAL_SOURCE_BLOCK_SIZE). These blocks are never deallocated as long + as the device (for buffers) or context (for sources) lives, so they don't + need a lock to access as the pointers are immutable once they're wired in. + We don't keep a ALuint name index array, but rather an array of block + pointers, which lets us find the right offset in the correct block without + iteration. The mixer thread never references the blocks directly, as they + get buffer and source pointers to objects within those blocks. Sources keep + a pointer to their specifically-bound buffer, and the mixer keeps a list of + pointers to playing sources. Since the API is serialized and the mixer + doesn't touch them, we don't need to tapdance to add new blocks. + +- Buffer data is owned by the AL, and it's illegal to delete a buffer or + alBufferData() its contents while attached to a source with either + AL_BUFFER or alSourceQueueBuffers(). We keep an atomic refcount for each + buffer, and you can't change its state or delete it when its refcount is + > 0, so there isn't a race with the mixer. Refcounts only change when + changing a source's AL_BUFFER or altering its buffer queue, both of which + are protected by the api lock. The mixer thread doesn't touch the + refcount, as a buffer moving from AL_PENDING to AL_PROCESSED is still + attached to a source. + +- alSource(Stop|Pause|Rewind)v with > 1 source used will always lock the + mixer thread to guarantee that all sources change in sync (!!! FIXME?). + The non-v version of these functions do not lock the mixer thread. + alSourcePlayv never locks the mixer thread (it atomically appends to a + linked list of sources to be played, which the mixer will pick up all + at once). + +- alSourceQueueBuffers will build a linked list of buffers, then atomically + move this list into position for the mixer to obtain it. The mixer will + process this list without the need to be atomic (as it owns it once it + atomically claims it from from the just_queued field where + alSourceQueueBuffers staged it). As buffers are processed, the mixer moves + them atomically to a linked list that other threads can pick up for + alSourceUnqueueBuffers. + +- Capture just locks the SDL audio device for everything, since it's a very + lightweight load and a much simplified API; good enough. The capture device + thread is an almost-constant minimal load (1 or 2 memcpy's, depending on the + ring buffer position), and the worst load on the API side (alcCaptureSamples) + is the same deal, so this never takes long, and is good enough. + +- Probably other things. These notes might get updates later. +*/ + +#if 1 +#define FIXME(x) +#else +#define FIXME(x) { \ + static int seen = 0; \ + if (!seen) { \ + seen = 1; \ + fprintf(stderr, "FIXME: %s (%s@%s:%d)\n", x, __FUNCTION__, __FILE__, __LINE__); \ + } \ +} +#endif + +/* restrict is from C99, but __restrict works with both Visual Studio and GCC. */ +#if !defined(restrict) && ((!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901))) +#define restrict __restrict +#endif + +#ifdef _MSC_VER +#define SIMDALIGNEDSTRUCT __declspec(align(16)) struct +#elif (defined(__GNUC__) || defined(__clang__)) +#define SIMDALIGNEDSTRUCT struct __attribute__((aligned(16))) +#else +#define SIMDALIGNEDSTRUCT struct +#endif + +#ifdef __SSE__ /* we assume you always have this on x86/x86-64 chips. SSE1 is 20 years old! */ +#define has_sse 1 +#endif + +#ifdef __ARM_NEON__ +#if NEED_SCALAR_FALLBACK +static int has_neon = 0; +#else +#define has_neon 1 +#endif +#endif + +static SDL_mutex *api_lock = NULL; + +static int init_api_lock(void) +{ + if (!api_lock) { + api_lock = SDL_CreateMutex(); + if (!api_lock) { + return 0; + } + } + return 1; +} + +static void grab_api_lock(void) +{ + if (!api_lock) { + if (!init_api_lock()) { + return; + } + } + const int rc = SDL_LockMutex(api_lock); + SDL_assert(rc == 0); +} + +static void ungrab_api_lock(void) +{ + if (!api_lock) { + init_api_lock(); + return; + } + + const int rc = SDL_UnlockMutex(api_lock); + SDL_assert(rc == 0); +} + +#define ENTRYPOINT(rettype,fn,params,args) \ + rettype fn params { rettype retval; grab_api_lock(); retval = _##fn args ; ungrab_api_lock(); return retval; } + +#define ENTRYPOINTVOID(fn,params,args) \ + void fn params { grab_api_lock(); _##fn args ; ungrab_api_lock(); } + + +/* lifted this ring buffer code from my al_osx project; I wrote it all, so it's stealable. */ +typedef struct +{ + ALCubyte *buffer; + ALCsizei size; + ALCsizei write; + ALCsizei read; + ALCsizei used; +} RingBuffer; + +static void ring_buffer_put(RingBuffer *ring, const void *_data, const ALCsizei size) +{ + const ALCubyte *data = (const ALCubyte *) _data; + ALCsizei cpy; + ALCsizei avail; + + if (!size) /* just in case... */ + return; + + /* Putting more data than ring buffer holds in total? Replace it all. */ + if (size > ring->size) { + ring->write = 0; + ring->read = 0; + ring->used = ring->size; + SDL_memcpy(ring->buffer, data + (size - ring->size), ring->size); + return; + } + + /* Buffer overflow? Push read pointer to oldest sample not overwritten... */ + avail = ring->size - ring->used; + if (size > avail) { + ring->read += size - avail; + if (ring->read > ring->size) + ring->read -= ring->size; + } + + /* Clip to end of buffer and copy first block... */ + cpy = ring->size - ring->write; + if (size < cpy) + cpy = size; + if (cpy) SDL_memcpy(ring->buffer + ring->write, data, cpy); + + /* Wrap around to front of ring buffer and copy remaining data... */ + avail = size - cpy; + if (avail) SDL_memcpy(ring->buffer, data + cpy, avail); + + /* Update write pointer... */ + ring->write += size; + if (ring->write > ring->size) + ring->write -= ring->size; + + ring->used += size; + if (ring->used > ring->size) + ring->used = ring->size; +} + + +static ALCsizei ring_buffer_get(RingBuffer *ring, void *_data, ALCsizei size) +{ + ALCubyte *data = (ALCubyte *) _data; + ALCsizei cpy; + ALCsizei avail = ring->used; + + /* Clamp amount to read to available data... */ + if (size > avail) + size = avail; + + /* Clip to end of buffer and copy first block... */ + cpy = ring->size - ring->read; + if (cpy > size) cpy = size; + if (cpy) SDL_memcpy(data, ring->buffer + ring->read, cpy); + + /* Wrap around to front of ring buffer and copy remaining data... */ + avail = size - cpy; + if (avail) SDL_memcpy(data + cpy, ring->buffer, avail); + + /* Update read pointer... */ + ring->read += size; + if (ring->read > ring->size) + ring->read -= ring->size; + + ring->used -= size; + + return size; /* may have been clamped if there wasn't enough data... */ +} + +static void *calloc_simd_aligned(const size_t len) +{ + Uint8 *retval = NULL; + Uint8 *ptr = (Uint8 *) SDL_calloc(1, len + 16 + sizeof (void *)); + if (ptr) { + void **storeptr; + retval = ptr + sizeof (void *); + retval += 16 - (((size_t) retval) % 16); + storeptr = (void **) retval; + storeptr--; + *storeptr = ptr; + } + return retval; +} + +static void free_simd_aligned(void *ptr) +{ + if (ptr) { + void **realptr = (void **) ptr; + realptr--; + SDL_free(*realptr); + } +} + + +typedef struct ALbuffer +{ + ALboolean allocated; + ALuint name; + ALint channels; + ALint bits; /* always float32 internally, but this is what alBufferData saw */ + ALsizei frequency; + ALsizei len; /* length of data in bytes. */ + const float *data; /* we only work in Float32 format. */ + SDL_atomic_t refcount; /* if zero, can be deleted or alBufferData'd */ +} ALbuffer; + +/* !!! FIXME: buffers and sources use almost identical code for blocks */ +typedef struct BufferBlock +{ + ALbuffer buffers[OPENAL_BUFFER_BLOCK_SIZE]; /* allocate these in blocks so we can step through faster. */ + ALuint used; + ALuint tmp; /* only touch under api_lock, assume it'll be gone later. */ +} BufferBlock; + +typedef struct BufferQueueItem +{ + ALbuffer *buffer; + void *next; /* void* because we'll atomicgetptr it. */ +} BufferQueueItem; + +typedef struct BufferQueue +{ + void *just_queued; /* void* because we'll atomicgetptr it. */ + BufferQueueItem *head; + BufferQueueItem *tail; + SDL_atomic_t num_items; /* counts just_queued+head/tail */ +} BufferQueue; + +typedef struct ALsource ALsource; + +SIMDALIGNEDSTRUCT ALsource +{ + /* keep these first to help guarantee that its elements are aligned for SIMD */ + ALfloat position[4]; + ALfloat velocity[4]; + ALfloat direction[4]; + ALfloat panning[2]; /* we only do stereo for now */ + SDL_atomic_t mixer_accessible; + SDL_atomic_t state; /* initial, playing, paused, stopped */ + ALuint name; + ALboolean allocated; + ALenum type; /* undetermined, static, streaming */ + ALboolean recalc; + ALboolean source_relative; + ALboolean looping; + ALfloat gain; + ALfloat min_gain; + ALfloat max_gain; + ALfloat reference_distance; + ALfloat max_distance; + ALfloat rolloff_factor; + ALfloat pitch; + ALfloat cone_inner_angle; + ALfloat cone_outer_angle; + ALfloat cone_outer_gain; + ALbuffer *buffer; + SDL_AudioStream *stream; /* for resampling. */ + BufferQueue buffer_queue; + BufferQueue buffer_queue_processed; + ALsizei offset; /* offset in bytes for converted stream! */ + ALboolean offset_latched; /* AL_SEC_OFFSET, etc, say set values apply to next alSourcePlay if not currently playing! */ + ALint queue_channels; + ALsizei queue_frequency; + ALsource *playlist_next; /* linked list that contains currently-playing sources! Only touched by mixer thread! */ +}; + +/* !!! FIXME: buffers and sources use almost identical code for blocks */ +typedef struct SourceBlock +{ + ALsource sources[OPENAL_SOURCE_BLOCK_SIZE]; /* allocate these in blocks so we can step through faster. */ + ALuint used; + ALuint tmp; /* only touch under api_lock, assume it'll be gone later. */ +} SourceBlock; + + +typedef struct SourcePlayTodo +{ + ALsource *source; + struct SourcePlayTodo *next; +} SourcePlayTodo; + +struct ALCdevice_struct +{ + char *name; + ALCenum error; + SDL_atomic_t connected; + ALCboolean iscapture; + SDL_AudioDeviceID sdldevice; + + ALint channels; + ALint frequency; + ALCsizei framesize; + + union { + struct { + ALCcontext *contexts; + BufferBlock **buffer_blocks; /* buffers are shared between contexts on the same device. */ + ALCsizei num_buffer_blocks; + BufferQueueItem *buffer_queue_pool; /* mixer thread doesn't touch this. */ + void *source_todo_pool; /* void* because we'll atomicgetptr it. */ + } playback; + struct { + RingBuffer ring; /* only used if iscapture */ + } capture; + }; +}; + +struct ALCcontext_struct +{ + /* keep these first to help guarantee that its elements are aligned for SIMD */ + SourceBlock **source_blocks; + ALsizei num_source_blocks; + + SIMDALIGNEDSTRUCT { + ALfloat position[4]; + ALfloat velocity[4]; + ALfloat orientation[8]; + ALfloat gain; + } listener; + + ALCdevice *device; + SDL_atomic_t processing; + ALenum error; + ALCint *attributes; + ALCsizei attributes_count; + + ALCboolean recalc; + ALenum distance_model; + ALfloat doppler_factor; + ALfloat doppler_velocity; + ALfloat speed_of_sound; + + SDL_mutex *source_lock; + + void *playlist_todo; /* void* so we can AtomicCASPtr it. Transmits new play commands from api thread to mixer thread */ + ALsource *playlist; /* linked list of currently-playing sources. Mixer thread only! */ + ALsource *playlist_tail; /* end of playlist so we know if last item is being readded. Mixer thread only! */ + + ALCcontext *prev; /* contexts are in a double-linked list */ + ALCcontext *next; +}; + +/* forward declarations */ +static int source_get_offset(ALsource *src, ALenum param); +static void source_set_offset(ALsource *src, ALenum param, ALfloat value); + +/* the just_queued list is backwards. Add it to the queue in the correct order. */ +static void queue_new_buffer_items_recursive(BufferQueue *queue, BufferQueueItem *items) +{ + if (items == NULL) { + return; + } + + queue_new_buffer_items_recursive(queue, items->next); + items->next = NULL; + if (queue->tail) { + queue->tail->next = items; + } else { + queue->head = items; + } + queue->tail = items; +} + +static void obtain_newly_queued_buffers(BufferQueue *queue) +{ + BufferQueueItem *items; + do { + items = (BufferQueueItem *) SDL_AtomicGetPtr(&queue->just_queued); + } while (!SDL_AtomicCASPtr(&queue->just_queued, items, NULL)); + + /* Now that we own this pointer, we can just do whatever we want with it. + Nothing touches the head/tail fields other than the mixer thread, so we + move it there. Not even atomically! :) */ + SDL_assert((queue->tail != NULL) == (queue->head != NULL)); + + queue_new_buffer_items_recursive(queue, items); +} + +/* You probably need to hold a lock before you call this (currently). */ +static void source_mark_all_buffers_processed(ALsource *src) +{ + obtain_newly_queued_buffers(&src->buffer_queue); + while (src->buffer_queue.head) { + void *ptr; + BufferQueueItem *item = src->buffer_queue.head; + src->buffer_queue.head = item->next; + SDL_AtomicAdd(&src->buffer_queue.num_items, -1); + + /* Move it to the processed queue for alSourceUnqueueBuffers() to pick up. */ + do { + ptr = SDL_AtomicGetPtr(&src->buffer_queue_processed.just_queued); + SDL_AtomicSetPtr(&item->next, ptr); + } while (!SDL_AtomicCASPtr(&src->buffer_queue_processed.just_queued, ptr, item)); + + SDL_AtomicAdd(&src->buffer_queue_processed.num_items, 1); + } + src->buffer_queue.tail = NULL; +} + +static void source_release_buffer_queue(ALCcontext *ctx, ALsource *src) +{ + /* move any buffer queue items to the device's available pool for reuse. */ + obtain_newly_queued_buffers(&src->buffer_queue); + if (src->buffer_queue.tail != NULL) { + BufferQueueItem *i; + for (i = src->buffer_queue.head; i; i = i->next) { + (void) SDL_AtomicDecRef(&i->buffer->refcount); + } + src->buffer_queue.tail->next = ctx->device->playback.buffer_queue_pool; + ctx->device->playback.buffer_queue_pool = src->buffer_queue.head; + } + src->buffer_queue.head = src->buffer_queue.tail = NULL; + SDL_AtomicSet(&src->buffer_queue.num_items, 0); + + obtain_newly_queued_buffers(&src->buffer_queue_processed); + if (src->buffer_queue_processed.tail != NULL) { + BufferQueueItem *i; + for (i = src->buffer_queue_processed.head; i; i = i->next) { + (void) SDL_AtomicDecRef(&i->buffer->refcount); + } + src->buffer_queue_processed.tail->next = ctx->device->playback.buffer_queue_pool; + ctx->device->playback.buffer_queue_pool = src->buffer_queue_processed.head; + } + src->buffer_queue_processed.head = src->buffer_queue_processed.tail = NULL; + SDL_AtomicSet(&src->buffer_queue_processed.num_items, 0); +} + + +/* ALC implementation... */ + +static void *current_context = NULL; +static ALCenum null_device_error = ALC_NO_ERROR; + +/* we don't have any device-specific extensions. */ +#define ALC_EXTENSION_ITEMS \ + ALC_EXTENSION_ITEM(ALC_ENUMERATION_EXT) \ + ALC_EXTENSION_ITEM(ALC_EXT_CAPTURE) \ + ALC_EXTENSION_ITEM(ALC_EXT_DISCONNECT) + +#define AL_EXTENSION_ITEMS \ + AL_EXTENSION_ITEM(AL_EXT_FLOAT32) + + +static void set_alc_error(ALCdevice *device, const ALCenum error) +{ + ALCenum *perr = device ? &device->error : &null_device_error; + /* can't set a new error when the previous hasn't been cleared yet. */ + if (*perr == ALC_NO_ERROR) { + *perr = error; + } +} + +/* all data written before the release barrier must be available before the recalc flag changes. */ \ +#define context_needs_recalc(ctx) SDL_MemoryBarrierRelease(); ctx->recalc = AL_TRUE; +#define source_needs_recalc(src) SDL_MemoryBarrierRelease(); src->recalc = AL_TRUE; + +static ALCdevice *prep_alc_device(const char *devicename, const ALCboolean iscapture) +{ + ALCdevice *dev = NULL; + + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { + return NULL; + } + + #ifdef __SSE__ + if (!SDL_HasSSE()) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; /* whoa! Better order a new Pentium III from Gateway 2000! */ + } + #endif + + #if defined(__ARM_NEON__) && !NEED_SCALAR_FALLBACK + if (!SDL_HasNEON()) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; /* :( */ + } + #elif defined(__ARM_NEON__) && NEED_SCALAR_FALLBACK + has_neon = SDL_HasNEON(); + #endif + + if (!init_api_lock()) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; + } + + dev = (ALCdevice *) SDL_calloc(1, sizeof (ALCdevice)); + if (!dev) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; + } + + dev->name = SDL_strdup(devicename); + if (!dev->name) { + SDL_free(dev); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; + } + + SDL_AtomicSet(&dev->connected, ALC_TRUE); + dev->iscapture = iscapture; + + return dev; +} + +/* no api lock; this creates it and otherwise doesn't have any state that can race */ +ALCdevice *alcOpenDevice(const ALCchar *devicename) +{ + if (!devicename) { + devicename = DEFAULT_PLAYBACK_DEVICE; /* so ALC_DEVICE_SPECIFIER is meaningful */ + } + + return prep_alc_device(devicename, ALC_FALSE); + + /* we don't open an SDL audio device until the first context is + created, so we can attempt to match audio formats. */ +} + +/* no api lock; this requires you to not destroy a device that's still in use */ +ALCboolean alcCloseDevice(ALCdevice *device) +{ + BufferQueueItem *item; + SourcePlayTodo *todo; + ALCsizei i; + + if (!device || device->iscapture) { + return ALC_FALSE; + } + + /* spec: "Failure will occur if all the device's contexts and buffers have not been destroyed." */ + if (device->playback.contexts) { + return ALC_FALSE; + } + + for (i = 0; i playback.num_buffer_blocks; i++) { + if (device->playback.buffer_blocks[i]->used > 0) { + return ALC_FALSE; /* still buffers allocated. */ + } + } + + if (device->sdldevice) { + SDL_CloseAudioDevice(device->sdldevice); + } + + for (i = 0; i < device->playback.num_buffer_blocks; i++) { + SDL_free(device->playback.buffer_blocks[i]); + } + SDL_free(device->playback.buffer_blocks); + + item = device->playback.buffer_queue_pool; + while (item) { + BufferQueueItem *next = item->next; + SDL_free(item); + item = next; + } + + todo = (SourcePlayTodo *) device->playback.source_todo_pool; + while (todo) { + SourcePlayTodo *next = todo->next; + SDL_free(todo); + todo = next; + } + + SDL_free(device->name); + SDL_free(device); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + + return ALC_TRUE; +} + + +static ALCboolean alcfmt_to_sdlfmt(const ALCenum alfmt, SDL_AudioFormat *sdlfmt, Uint8 *channels, ALCsizei *framesize) +{ + switch (alfmt) { + case AL_FORMAT_MONO8: + *sdlfmt = AUDIO_U8; + *channels = 1; + *framesize = 1; + break; + case AL_FORMAT_MONO16: + *sdlfmt = AUDIO_S16SYS; + *channels = 1; + *framesize = 2; + break; + case AL_FORMAT_STEREO8: + *sdlfmt = AUDIO_U8; + *channels = 2; + *framesize = 2; + break; + case AL_FORMAT_STEREO16: + *sdlfmt = AUDIO_S16SYS; + *channels = 2; + *framesize = 4; + break; + case AL_FORMAT_MONO_FLOAT32: + *sdlfmt = AUDIO_F32SYS; + *channels = 1; + *framesize = 4; + break; + case AL_FORMAT_STEREO_FLOAT32: + *sdlfmt = AUDIO_F32SYS; + *channels = 2; + *framesize = 8; + break; + default: + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void mix_float32_c1_scalar(const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + const int unrolled = mixframes / 4; + const int leftover = mixframes % 4; + ALsizei i; + + if ((left == 1.0f) && (right == 1.0f)) { + for (i = 0; i < unrolled; i++, data += 4, stream += 8) { + const float samp0 = data[0]; + const float samp1 = data[1]; + const float samp2 = data[2]; + const float samp3 = data[3]; + stream[0] += samp0; + stream[1] += samp0; + stream[2] += samp1; + stream[3] += samp1; + stream[4] += samp2; + stream[5] += samp2; + stream[6] += samp3; + stream[7] += samp3; + } + for (i = 0; i < leftover; i++, stream += 2) { + const float samp = *(data++); + stream[0] += samp; + stream[1] += samp; + } + } else { + for (i = 0; i < unrolled; i++, data += 4, stream += 8) { + const float samp0 = data[0]; + const float samp1 = data[1]; + const float samp2 = data[2]; + const float samp3 = data[3]; + stream[0] += samp0 * left; + stream[1] += samp0 * right; + stream[2] += samp1 * left; + stream[3] += samp1 * right; + stream[4] += samp2 * left; + stream[5] += samp2 * right; + stream[6] += samp3 * left; + stream[7] += samp3 * right; + } + for (i = 0; i < leftover; i++, stream += 2) { + const float samp = *(data++); + stream[0] += samp * left; + stream[1] += samp * right; + } + } +} + +static void mix_float32_c2_scalar(const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + const int unrolled = mixframes / 4; + const int leftover = mixframes % 4; + ALsizei i; + + if ((left == 1.0f) && (right == 1.0f)) { + for (i = 0; i < unrolled; i++, stream += 8, data += 8) { + stream[0] += data[0]; + stream[1] += data[1]; + stream[2] += data[2]; + stream[3] += data[3]; + stream[4] += data[4]; + stream[5] += data[5]; + stream[6] += data[6]; + stream[7] += data[7]; + } + for (i = 0; i < leftover; i++, stream += 2, data += 2) { + stream[0] += data[0]; + stream[1] += data[1]; + } + } else { + for (i = 0; i < unrolled; i++, stream += 8, data += 8) { + stream[0] += data[0] * left; + stream[1] += data[1] * right; + stream[2] += data[2] * left; + stream[3] += data[3] * right; + stream[4] += data[4] * left; + stream[5] += data[5] * right; + stream[6] += data[6] * left; + stream[7] += data[7] * right; + } + for (i = 0; i < leftover; i++, stream += 2, data += 2) { + stream[0] += data[0] * left; + stream[1] += data[1] * right; + } + } +} + +#ifdef __SSE__ +static void mix_float32_c1_sse(const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + const int unrolled = mixframes / 8; + const int leftover = mixframes % 8; + ALsizei i; + + /* We can align this to 16 in one special case. */ + if ( ((((size_t)data) % 16) == 8) && ((((size_t)stream) % 16) == 0) && (mixframes >= 2) ) { + stream[0] += data[0] * left; + stream[1] += data[0] * right; + stream[2] += data[1] * left; + stream[3] += data[1] * right; + mix_float32_c1_sse(panning, data + 2, stream + 4, mixframes - 2); + } else if ( (((size_t)stream) % 16) || (((size_t)data) % 16) ) { + /* unaligned, do scalar version. */ + mix_float32_c1_scalar(panning, data, stream, mixframes); + } else if ((left == 1.0f) && (right == 1.0f)) { + for (i = 0; i < unrolled; i++, data += 8, stream += 16) { + /* We have 8 SSE registers, load 6 of them, have two for math (unrolled once). */ + { + const __m128 vdataload1 = _mm_load_ps(data); + const __m128 vdataload2 = _mm_load_ps(data+4); + const __m128 vstream1 = _mm_load_ps(stream); + const __m128 vstream2 = _mm_load_ps(stream+4); + const __m128 vstream3 = _mm_load_ps(stream+8); + const __m128 vstream4 = _mm_load_ps(stream+12); + _mm_store_ps(stream, _mm_add_ps(vstream1, _mm_shuffle_ps(vdataload1, vdataload1, _MM_SHUFFLE(0, 0, 1, 1)))); + _mm_store_ps(stream+4, _mm_add_ps(vstream2, _mm_shuffle_ps(vdataload1, vdataload1, _MM_SHUFFLE(2, 2, 3, 3)))); + _mm_store_ps(stream+8, _mm_add_ps(vstream3, _mm_shuffle_ps(vdataload2, vdataload2, _MM_SHUFFLE(0, 0, 1, 1)))); + _mm_store_ps(stream+12, _mm_add_ps(vstream4, _mm_shuffle_ps(vdataload2, vdataload2, _MM_SHUFFLE(2, 2, 3, 3)))); + } + } + for (i = 0; i < leftover; i++, stream += 2) { + const float samp = *(data++); + stream[0] += samp; + stream[1] += samp; + } + } else { + const __m128 vleftright = { left, right, left, right }; + for (i = 0; i < unrolled; i++, data += 8, stream += 16) { + /* We have 8 SSE registers, load 6 of them, have two for math (unrolled once). */ + const __m128 vdataload1 = _mm_load_ps(data); + const __m128 vdataload2 = _mm_load_ps(data+4); + const __m128 vstream1 = _mm_load_ps(stream); + const __m128 vstream2 = _mm_load_ps(stream+4); + const __m128 vstream3 = _mm_load_ps(stream+8); + const __m128 vstream4 = _mm_load_ps(stream+12); + _mm_store_ps(stream, _mm_add_ps(vstream1, _mm_mul_ps(_mm_shuffle_ps(vdataload1, vdataload1, _MM_SHUFFLE(0, 0, 1, 1)), vleftright))); + _mm_store_ps(stream+4, _mm_add_ps(vstream2, _mm_mul_ps(_mm_shuffle_ps(vdataload1, vdataload1, _MM_SHUFFLE(2, 2, 3, 3)), vleftright))); + _mm_store_ps(stream+8, _mm_add_ps(vstream3, _mm_mul_ps(_mm_shuffle_ps(vdataload2, vdataload2, _MM_SHUFFLE(0, 0, 1, 1)), vleftright))); + _mm_store_ps(stream+12, _mm_add_ps(vstream4, _mm_mul_ps(_mm_shuffle_ps(vdataload2, vdataload2, _MM_SHUFFLE(2, 2, 3, 3)), vleftright))); + } + for (i = 0; i < leftover; i++, stream += 2) { + const float samp = *(data++); + stream[0] += samp * left; + stream[1] += samp * right; + } + } +} + +static void mix_float32_c2_sse(const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + const int unrolled = mixframes / 4; + const int leftover = mixframes % 4; + ALsizei i; + + /* We can align this to 16 in one special case. */ + if ( ((((size_t)stream) % 16) == 8) && ((((size_t)data) % 16) == 8) && mixframes ) { + stream[0] += data[0] * left; + stream[1] += data[1] * right; + mix_float32_c2_sse(panning, data + 2, stream + 2, mixframes - 1); + } else if ( (((size_t)stream) % 16) || (((size_t)data) % 16) ) { + /* unaligned, do scalar version. */ + mix_float32_c2_scalar(panning, data, stream, mixframes); + } else if ((left == 1.0f) && (right == 1.0f)) { + for (i = 0; i < unrolled; i++, data += 8, stream += 8) { + const __m128 vdata1 = _mm_load_ps(data); + const __m128 vdata2 = _mm_load_ps(data+4); + const __m128 vstream1 = _mm_load_ps(stream); + const __m128 vstream2 = _mm_load_ps(stream+4); + _mm_store_ps(stream, _mm_add_ps(vstream1, vdata1)); + _mm_store_ps(stream+4, _mm_add_ps(vstream2, vdata2)); + } + for (i = 0; i < leftover; i++, stream += 2, data += 2) { + stream[0] += data[0]; + stream[1] += data[1]; + } + } else { + const __m128 vleftright = { left, right, left, right }; + for (i = 0; i < unrolled; i++, data += 8, stream += 8) { + const __m128 vdata1 = _mm_load_ps(data); + const __m128 vdata2 = _mm_load_ps(data+4); + const __m128 vstream1 = _mm_load_ps(stream); + const __m128 vstream2 = _mm_load_ps(stream+4); + _mm_store_ps(stream, _mm_add_ps(vstream1, _mm_mul_ps(vdata1, vleftright))); + _mm_store_ps(stream+4, _mm_add_ps(vstream2, _mm_mul_ps(vdata2, vleftright))); + } + for (i = 0; i < leftover; i++, stream += 2, data += 2) { + stream[0] += data[0] * left; + stream[1] += data[1] * right; + } + } +} +#endif + +#ifdef __ARM_NEON__ +static void mix_float32_c1_neon(const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + const int unrolled = mixframes / 8; + const int leftover = mixframes % 8; + ALsizei i; + + /* We can align this to 16 in one special case. */ + if ( ((((size_t)data) % 16) == 8) && ((((size_t)stream) % 16) == 0) && (mixframes >= 2) ) { + stream[0] += data[0] * left; + stream[1] += data[0] * right; + stream[2] += data[1] * left; + stream[3] += data[1] * right; + mix_float32_c1_neon(panning, data + 2, stream + 4, mixframes - 2); + } else if ( (((size_t)stream) % 16) || (((size_t)data) % 16) ) { + /* unaligned, do scalar version. */ + mix_float32_c1_scalar(panning, data, stream, mixframes); + } else if ((left == 1.0f) && (right == 1.0f)) { + for (i = 0; i < unrolled; i++, data += 8, stream += 16) { + const float32x4_t vdataload1 = vld1q_f32(data); + const float32x4_t vdataload2 = vld1q_f32(data+4); + const float32x4_t vstream1 = vld1q_f32(stream); + const float32x4_t vstream2 = vld1q_f32(stream+4); + const float32x4_t vstream3 = vld1q_f32(stream+8); + const float32x4_t vstream4 = vld1q_f32(stream+12); + const float32x4x2_t vzipped1 = vzipq_f32(vdataload1, vdataload1); + const float32x4x2_t vzipped2 = vzipq_f32(vdataload2, vdataload2); + vst1q_f32(stream, vaddq_f32(vstream1, vzipped1.val[0])); + vst1q_f32(stream+4, vaddq_f32(vstream2, vzipped1.val[1])); + vst1q_f32(stream+8, vaddq_f32(vstream3, vzipped2.val[0])); + vst1q_f32(stream+12, vaddq_f32(vstream4, vzipped2.val[1])); + } + for (i = 0; i < leftover; i++, stream += 2) { + const float samp = *(data++); + stream[0] += samp; + stream[1] += samp; + } + } else { + const float32x4_t vleftright = { left, right, left, right }; + for (i = 0; i < unrolled; i++, data += 8, stream += 16) { + const float32x4_t vdataload1 = vld1q_f32(data); + const float32x4_t vdataload2 = vld1q_f32(data+4); + const float32x4_t vstream1 = vld1q_f32(stream); + const float32x4_t vstream2 = vld1q_f32(stream+4); + const float32x4_t vstream3 = vld1q_f32(stream+8); + const float32x4_t vstream4 = vld1q_f32(stream+12); + const float32x4x2_t vzipped1 = vzipq_f32(vdataload1, vdataload1); + const float32x4x2_t vzipped2 = vzipq_f32(vdataload2, vdataload2); + vst1q_f32(stream, vmlaq_f32(vstream1, vzipped1.val[0], vleftright)); + vst1q_f32(stream+4, vmlaq_f32(vstream2, vzipped1.val[1], vleftright)); + vst1q_f32(stream+8, vmlaq_f32(vstream3, vzipped2.val[0], vleftright)); + vst1q_f32(stream+12, vmlaq_f32(vstream4, vzipped2.val[1], vleftright)); + } + for (i = 0; i < leftover; i++, stream += 2) { + const float samp = *(data++); + stream[0] += samp * left; + stream[1] += samp * right; + } + } +} + +static void mix_float32_c2_neon(const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + const int unrolled = mixframes / 8; + const int leftover = mixframes % 8; + ALsizei i; + + /* We can align this to 16 in one special case. */ + if ( ((((size_t)stream) % 16) == 8) && ((((size_t)data) % 16) == 8) && mixframes ) { + stream[0] += data[0] * left; + stream[1] += data[1] * right; + mix_float32_c2_neon(panning, data + 2, stream + 2, mixframes - 1); + } else if ( (((size_t)stream) % 16) || (((size_t)data) % 16) ) { + /* unaligned, do scalar version. */ + mix_float32_c2_scalar(panning, data, stream, mixframes); + } else if ((left == 1.0f) && (right == 1.0f)) { + for (i = 0; i < unrolled; i++, data += 16, stream += 16) { + const float32x4_t vdata1 = vld1q_f32(data); + const float32x4_t vdata2 = vld1q_f32(data+4); + const float32x4_t vdata3 = vld1q_f32(data+8); + const float32x4_t vdata4 = vld1q_f32(data+12); + const float32x4_t vstream1 = vld1q_f32(stream); + const float32x4_t vstream2 = vld1q_f32(stream+4); + const float32x4_t vstream3 = vld1q_f32(stream+8); + const float32x4_t vstream4 = vld1q_f32(stream+12); + vst1q_f32(stream, vaddq_f32(vstream1, vdata1)); + vst1q_f32(stream+4, vaddq_f32(vstream2, vdata2)); + vst1q_f32(stream+8, vaddq_f32(vstream3, vdata3)); + vst1q_f32(stream+12, vaddq_f32(vstream4, vdata4)); + } + for (i = 0; i < leftover; i++, stream += 2, data += 2) { + stream[0] += data[0]; + stream[1] += data[1]; + } + } else { + const float32x4_t vleftright = { left, right, left, right }; + for (i = 0; i < unrolled; i++, data += 16, stream += 16) { + const float32x4_t vdata1 = vld1q_f32(data); + const float32x4_t vdata2 = vld1q_f32(data+4); + const float32x4_t vdata3 = vld1q_f32(data+8); + const float32x4_t vdata4 = vld1q_f32(data+12); + const float32x4_t vstream1 = vld1q_f32(stream); + const float32x4_t vstream2 = vld1q_f32(stream+4); + const float32x4_t vstream3 = vld1q_f32(stream+8); + const float32x4_t vstream4 = vld1q_f32(stream+12); + vst1q_f32(stream, vmlaq_f32(vstream1, vdata1, vleftright)); + vst1q_f32(stream+4, vmlaq_f32(vstream2, vdata2, vleftright)); + vst1q_f32(stream+8, vmlaq_f32(vstream3, vdata3, vleftright)); + vst1q_f32(stream+12, vmlaq_f32(vstream4, vdata4, vleftright)); + } + for (i = 0; i < leftover; i++, stream += 2, data += 2) { + stream[0] += data[0] * left; + stream[1] += data[1] * right; + } + } +} +#endif + + +static void mix_buffer(const ALbuffer *buffer, const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes) +{ + const ALfloat left = panning[0]; + const ALfloat right = panning[1]; + FIXME("currently expects output to be stereo"); + if ((left != 0.0f) || (right != 0.0f)) { /* don't bother mixing in silence. */ + if (buffer->channels == 1) { + #ifdef __SSE__ + if (has_sse) { mix_float32_c1_sse(panning, data, stream, mixframes); } else + #elif defined(__ARM_NEON__) + if (has_neon) { mix_float32_c1_neon(panning, data, stream, mixframes); } else + #endif + { + #if NEED_SCALAR_FALLBACK + mix_float32_c1_scalar(panning, data, stream, mixframes); + #else + SDL_assert(!"uhoh, we didn't compile in enough mixers!"); + #endif + } + } else { + SDL_assert(buffer->channels == 2); + #ifdef __SSE__ + if (has_sse) { mix_float32_c2_sse(panning, data, stream, mixframes); } else + #elif defined(__ARM_NEON__) + if (has_neon) { mix_float32_c2_neon(panning, data, stream, mixframes); } else + #endif + { + #if NEED_SCALAR_FALLBACK + mix_float32_c2_scalar(panning, data, stream, mixframes); + #else + SDL_assert(!"uhoh, we didn't compile in enough mixers!"); + #endif + } + } + } +} + +static ALboolean mix_source_buffer(ALCcontext *ctx, ALsource *src, BufferQueueItem *queue, float **stream, int *len) +{ + const ALbuffer *buffer = queue ? queue->buffer : NULL; + ALboolean processed = AL_TRUE; + + /* you can legally queue or set a NULL buffer. */ + if (buffer && buffer->data && (buffer->len > 0)) { + const float *data = buffer->data + (src->offset / sizeof (float)); + const int bufferframesize = (int) (buffer->channels * sizeof (float)); + const int deviceframesize = ctx->device->framesize; + const int framesneeded = *len / deviceframesize; + + SDL_assert(src->offset < buffer->len); + + if (src->stream) { /* resampling? */ + int mixframes, mixlen, remainingmixframes; + while ( (((mixlen = SDL_AudioStreamAvailable(src->stream)) / bufferframesize) < framesneeded) && (src->offset < buffer->len) ) { + const int framesput = (buffer->len - src->offset) / bufferframesize; + const int bytesput = SDL_min(framesput, 1024) * bufferframesize; + FIXME("dynamically adjust frames here?"); /* we hardcode 1024 samples when opening the audio device, too. */ + SDL_AudioStreamPut(src->stream, data, bytesput); + src->offset += bytesput; + data += bytesput / sizeof (float); + } + + mixframes = SDL_min(mixlen / bufferframesize, framesneeded); + remainingmixframes = mixframes; + while (remainingmixframes > 0) { + float mixbuf[256]; + const int mixbuflen = sizeof (mixbuf); + const int mixbufframes = mixbuflen / bufferframesize; + const int getframes = SDL_min(remainingmixframes, mixbufframes); + SDL_AudioStreamGet(src->stream, mixbuf, getframes * bufferframesize); + mix_buffer(buffer, src->panning, mixbuf, *stream, getframes); + *len -= getframes * deviceframesize; + *stream += getframes * ctx->device->channels; + remainingmixframes -= getframes; + } + } else { + const int framesavail = (buffer->len - src->offset) / bufferframesize; + const int mixframes = SDL_min(framesneeded, framesavail); + mix_buffer(buffer, src->panning, data, *stream, mixframes); + src->offset += mixframes * bufferframesize; + *len -= mixframes * deviceframesize; + *stream += mixframes * ctx->device->channels; + } + + SDL_assert(src->offset <= buffer->len); + + processed = src->offset >= buffer->len; + if (processed) { + FIXME("does the offset have to represent the whole queue or just the current buffer?"); + src->offset = 0; + } + } + + return processed; +} + +static ALCboolean mix_source_buffer_queue(ALCcontext *ctx, ALsource *src, BufferQueueItem *queue, float *stream, int len) +{ + ALCboolean keep = ALC_TRUE; + + while ((len > 0) && (mix_source_buffer(ctx, src, queue, &stream, &len))) { + /* Finished this buffer! */ + BufferQueueItem *item = queue; + BufferQueueItem *next = queue ? queue->next : NULL; + void *ptr; + + if (queue) { + queue->next = NULL; + queue = next; + } + + SDL_assert((src->type == AL_STATIC) || (src->type == AL_STREAMING)); + if (src->type == AL_STREAMING) { /* mark buffer processed. */ + SDL_assert(item == src->buffer_queue.head); + FIXME("bubble out all these NULL checks"); /* these are only here because we check for looping/stopping in this loop, but we really shouldn't enter this loop at all if queue==NULL. */ + if (item != NULL) { + src->buffer_queue.head = next; + if (!next) { + src->buffer_queue.tail = NULL; + } + SDL_AtomicAdd(&src->buffer_queue.num_items, -1); + + /* Move it to the processed queue for alSourceUnqueueBuffers() to pick up. */ + do { + ptr = SDL_AtomicGetPtr(&src->buffer_queue_processed.just_queued); + SDL_AtomicSetPtr(&item->next, ptr); + } while (!SDL_AtomicCASPtr(&src->buffer_queue_processed.just_queued, ptr, item)); + + SDL_AtomicAdd(&src->buffer_queue_processed.num_items, 1); + } + } + + if (queue == NULL) { /* nothing else to play? */ + if (src->looping) { + FIXME("looping is supposed to move to AL_INITIAL then immediately to AL_PLAYING, but I'm not sure what side effect this is meant to trigger"); + if (src->type == AL_STREAMING) { + FIXME("what does looping do with the AL_STREAMING state?"); + } + } else { + SDL_AtomicSet(&src->state, AL_STOPPED); + keep = ALC_FALSE; + } + break; /* nothing else to mix here, so stop. */ + } + } + + return keep; +} + +/* All the 3D math here is way overcommented because I HAVE NO IDEA WHAT I'M + DOING and had to research the hell out of what are probably pretty simple + concepts. Pay attention in math class, kids. */ + +/* The scalar versions have explanitory comments and links. The SIMD versions don't. */ + +/* calculates cross product. https://en.wikipedia.org/wiki/Cross_product + Basically takes two vectors and gives you a vector that's perpendicular + to both. +*/ +#if NEED_SCALAR_FALLBACK +static void xyzzy(ALfloat *v, const ALfloat *a, const ALfloat *b) +{ + v[0] = (a[1] * b[2]) - (a[2] * b[1]); + v[1] = (a[2] * b[0]) - (a[0] * b[2]); + v[2] = (a[0] * b[1]) - (a[1] * b[0]); +} + +/* calculate dot product (multiply each element of two vectors, sum them) */ +static ALfloat dotproduct(const ALfloat *a, const ALfloat *b) +{ + return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); +} + +/* calculate distance ("magnitude") in 3D space: + https://math.stackexchange.com/questions/42640/calculate-distance-in-3d-space + assumes vector starts at (0,0,0). */ +static ALfloat magnitude(const ALfloat *v) +{ + /* technically, the inital part on this is just a dot product of itself. */ + return SDL_sqrtf((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2])); +} + +/* https://www.khanacademy.org/computing/computer-programming/programming-natural-simulations/programming-vectors/a/vector-magnitude-normalization */ +static void normalize(ALfloat *v) +{ + const ALfloat mag = magnitude(v); + if (mag == 0.0f) { + SDL_memset(v, '\0', sizeof (*v) * 3); + } else { + v[0] /= mag; + v[1] /= mag; + v[2] /= mag; + } +} +#endif + +#ifdef __SSE__ +static __m128 xyzzy_sse(const __m128 a, const __m128 b) +{ + /* http://fastcpp.blogspot.com/2011/04/vector-cross-product-using-sse-code.html + this is the "three shuffle" version in the comments, plus the variables swapped around for handedness in the later comment. */ + const __m128 v = _mm_sub_ps( + _mm_mul_ps(a, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1))), + _mm_mul_ps(b, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1))) + ); + return _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 0, 2, 1)); +} + +static ALfloat dotproduct_sse(const __m128 a, const __m128 b) +{ + const __m128 prod = _mm_mul_ps(a, b); + const __m128 sum1 = _mm_add_ps(prod, _mm_shuffle_ps(prod, prod, _MM_SHUFFLE(1, 0, 3, 2))); + const __m128 sum2 = _mm_add_ps(sum1, _mm_shuffle_ps(sum1, sum1, _MM_SHUFFLE(2, 2, 0, 0))); + FIXME("this can use _mm_hadd_ps in SSE3, or _mm_dp_ps in SSE4.1"); + return _mm_cvtss_f32(_mm_shuffle_ps(sum2, sum2, _MM_SHUFFLE(3, 3, 3, 3))); +} + +static ALfloat magnitude_sse(const __m128 v) +{ + return SDL_sqrtf(dotproduct_sse(v, v)); +} + +static __m128 normalize_sse(const __m128 v) +{ + const ALfloat mag = magnitude_sse(v); + if (mag == 0.0f) { + return _mm_setzero_ps(); + } + return _mm_div_ps(v, _mm_set_ps1(mag)); +} +#endif + +#ifdef __ARM_NEON__ +static float32x4_t xyzzy_neon(const float32x4_t a, const float32x4_t b) +{ + const float32x4_t shuf_a = { a[1], a[2], a[0], a[3] }; + const float32x4_t shuf_b = { b[1], b[2], b[0], b[3] }; + const float32x4_t v = vsubq_f32(vmulq_f32(a, shuf_b), vmulq_f32(b, shuf_a)); + const float32x4_t retval = { v[1], v[2], v[0], v[3] }; + FIXME("need a better permute"); + return retval; +} + +static ALfloat dotproduct_neon(const float32x4_t a, const float32x4_t b) +{ + const float32x4_t prod = vmulq_f32(a, b); + const float32x4_t sum1 = vaddq_f32(prod, vrev64q_f32(prod)); + const float32x4_t sum2 = vaddq_f32(sum1, vcombine_f32(vget_high_f32(sum1), vget_low_f32(sum1))); + return sum2[3]; +} + +static ALfloat magnitude_neon(const float32x4_t v) +{ + return SDL_sqrtf(dotproduct_neon(v, v)); +} + +static float32x4_t normalize_neon(const float32x4_t v) +{ + const ALfloat mag = magnitude_neon(v); + if (mag == 0.0f) { + return vdupq_n_f32(0.0f); + } + return vmulq_f32(v, vdupq_n_f32(1.0f / mag)); +} +#endif + + + +/* Get the sin(angle) and cos(angle) at the same time. Ideally, with one + instruction, like what is offered on the x86. + angle is in radians, not degrees. */ +static void calculate_sincos(const ALfloat angle, ALfloat *_sin, ALfloat *_cos) +{ + *_sin = SDL_sinf(angle); + *_cos = SDL_cosf(angle); +} + +static ALfloat calculate_distance_attenuation(const ALCcontext *ctx, const ALsource *src, ALfloat distance) +{ + /* AL SPEC: "With all the distance models, if the formula can not be + evaluated then the source will not be attenuated. For example, if a + linear model is being used with AL_REFERENCE_DISTANCE equal to + AL_MAX_DISTANCE, then the gain equation will have a divide-by-zero + error in it. In this case, there is no attenuation for that source." */ + FIXME("check divisions by zero"); + + switch (ctx->distance_model) { + case AL_INVERSE_DISTANCE_CLAMPED: + distance = SDL_min(SDL_max(distance, src->reference_distance), src->max_distance); + /* fallthrough */ + case AL_INVERSE_DISTANCE: + /* AL SPEC: "gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE))" */ + return src->reference_distance / (src->reference_distance + src->rolloff_factor * (distance - src->reference_distance)); + + case AL_LINEAR_DISTANCE_CLAMPED: + distance = SDL_max(distance, src->reference_distance); + /* fallthrough */ + case AL_LINEAR_DISTANCE: + /* AL SPEC: "distance = min(distance, AL_MAX_DISTANCE) // avoid negative gain + gain = (1 - AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE) / (AL_MAX_DISTANCE - AL_REFERENCE_DISTANCE))" */ + return 1.0f - src->rolloff_factor * (SDL_min(distance, src->max_distance) - src->reference_distance) / (src->max_distance - src->reference_distance); + + case AL_EXPONENT_DISTANCE_CLAMPED: + distance = SDL_min(SDL_max(distance, src->reference_distance), src->max_distance); + /* fallthrough */ + case AL_EXPONENT_DISTANCE: + /* AL SPEC: "gain = (distance / AL_REFERENCE_DISTANCE) ^ (- AL_ROLLOFF_FACTOR)" */ + return SDL_powf(distance / src->reference_distance, -src->rolloff_factor); + + default: break; + } + + SDL_assert(!"Unexpected distance model"); + return 1.0f; +} + +static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src, float *gains) +{ + /* rolloff==0.0f makes all distance models result in 1.0f, + and we never spatialize non-mono sources, per the AL spec. */ + const ALboolean spatialize = (ctx->distance_model != AL_NONE) && + (src->queue_channels == 1) && + (src->rolloff_factor != 0.0f); + + const ALfloat *at = &ctx->listener.orientation[0]; + const ALfloat *up = &ctx->listener.orientation[4]; + + ALfloat distance; + ALfloat gain; + ALfloat radians; + + #ifdef __SSE__ + __m128 position_sse; + #elif defined(__ARM_NEON__) + float32x4_t position_neon = vdupq_n_f32(0.0f); + #endif + + #if NEED_SCALAR_FALLBACK + ALfloat position[3]; + #endif + + /* this goes through the steps the AL spec dictates for gain and distance attenuation... */ + + if (!spatialize) { + /* simpler path through the same AL spec details if not spatializing. */ + gain = SDL_min(SDL_max(src->gain, src->min_gain), src->max_gain) * ctx->listener.gain; + gains[0] = gains[1] = gain; /* no spatialization, but AL_GAIN (etc) is still applied. */ + return; + } + + #ifdef __SSE__ + if (has_sse) { + position_sse = _mm_load_ps(src->position); + if (!src->source_relative) { + position_sse = _mm_sub_ps(position_sse, _mm_load_ps(ctx->listener.position)); + } + distance = magnitude_sse(position_sse); + } else + #elif defined(__ARM_NEON__) + if (has_neon) { + position_neon = vld1q_f32(src->position); + if (!src->source_relative) { + position_neon = vsubq_f32(position_neon, vld1q_f32(ctx->listener.position)); + } + distance = magnitude_neon(position_neon); + } else + #endif + + { + #if NEED_SCALAR_FALLBACK + SDL_memcpy(position, src->position, sizeof (position)); + /* if values aren't source-relative, then convert it to be so. */ + if (!src->source_relative) { + position[0] -= ctx->listener.position[0]; + position[1] -= ctx->listener.position[1]; + position[2] -= ctx->listener.position[2]; + } + distance = magnitude(position); + #endif + } + + /* AL SPEC: ""1. Distance attenuation is calculated first, including + minimum (AL_REFERENCE_DISTANCE) and maximum (AL_MAX_DISTANCE) + thresholds." */ + gain = calculate_distance_attenuation(ctx, src, distance); + + /* AL SPEC: "2. The result is then multiplied by source gain (AL_GAIN)." */ + gain *= src->gain; + + /* AL SPEC: "3. If the source is directional (AL_CONE_INNER_ANGLE less + than AL_CONE_OUTER_ANGLE), an angle-dependent attenuation is calculated + depending on AL_CONE_OUTER_GAIN, and multiplied with the distance + dependent attenuation. The resulting attenuation factor for the given + angle and distance between listener and source is multiplied with + source AL_GAIN." */ + if (src->cone_inner_angle < src->cone_outer_angle) { + FIXME("directional sources"); + } + + /* AL SPEC: "4. The effective gain computed this way is compared against + AL_MIN_GAIN and AL_MAX_GAIN thresholds." */ + gain = SDL_min(SDL_max(gain, src->min_gain), src->max_gain); + + /* AL SPEC: "5. The result is guaranteed to be clamped to [AL_MIN_GAIN, + AL_MAX_GAIN], and subsequently multiplied by listener gain which serves + as an overall volume control. The implementation is free to clamp + listener gain if necessary due to hardware or implementation + constraints." */ + gain *= ctx->listener.gain; + + /* now figure out positioning. Since we're aiming for stereo, we just + need a simple panning effect. We're going to do what's called + "constant power panning," as explained... + + https://dsp.stackexchange.com/questions/21691/algorithm-to-pan-audio + + Naturally, we'll need to know the angle between where our listener + is facing and where the source is to make that work... + + https://www.youtube.com/watch?v=S_568VZWFJo + + ...but to do that, we need to rotate so we have the correct side of + the listener, which isn't just a point in space, but has a definite + direction it is facing. More or less, this is what gluLookAt deals + with... + + http://www.songho.ca/opengl/gl_camera.html + + ...although I messed with the algorithm until it did what I wanted. + + XYZZY!! https://en.wikipedia.org/wiki/Cross_product#Mnemonic + */ + + #ifdef __SSE__ /* (the math is explained in the scalar version.) */ + if (has_sse) { + const __m128 at_sse = _mm_load_ps(at); + const __m128 U_sse = normalize_sse(xyzzy_sse(at_sse, _mm_load_ps(up))); + const __m128 V_sse = xyzzy_sse(at_sse, U_sse); + const __m128 N_sse = normalize_sse(at_sse); + const __m128 rotated_sse = { + dotproduct_sse(position_sse, U_sse), + -dotproduct_sse(position_sse, V_sse), + -dotproduct_sse(position_sse, N_sse), + 0.0f + }; + + const ALfloat mags = magnitude_sse(at_sse) * magnitude_sse(rotated_sse); + radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct_sse(at_sse, rotated_sse) / mags); + if (_mm_comilt_ss(rotated_sse, _mm_setzero_ps())) { + radians = -radians; + } + } else + #endif + + #ifdef __ARM_NEON__ /* (the math is explained in the scalar version.) */ + if (has_neon) { + const float32x4_t at_neon = vld1q_f32(at); + const float32x4_t U_neon = normalize_neon(xyzzy_neon(at_neon, vld1q_f32(up))); + const float32x4_t V_neon = xyzzy_neon(at_neon, U_neon); + const float32x4_t N_neon = normalize_neon(at_neon); + const float32x4_t rotated_neon = { + dotproduct_neon(position_neon, U_neon), + -dotproduct_neon(position_neon, V_neon), + -dotproduct_neon(position_neon, N_neon), + 0.0f + }; + + const ALfloat mags = magnitude_neon(at_neon) * magnitude_neon(rotated_neon); + radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct_neon(at_neon, rotated_neon) / mags); + if (rotated_neon[0] < 0.0f) { + radians = -radians; + } + } else + #endif + + { + #if NEED_SCALAR_FALLBACK + ALfloat U[3]; + ALfloat V[3]; + ALfloat N[3]; + ALfloat rotated[3]; + ALfloat mags; + + xyzzy(U, at, up); + normalize(U); + xyzzy(V, at, U); + SDL_memcpy(N, at, sizeof (N)); + normalize(N); + + /* we don't need the bottom row of the gluLookAt matrix, since we don't + translate. (Matrix * Vector) is just filling in each element of the + output vector with the dot product of a row of the matrix and the + vector. I made some of these negative to make it work for my purposes, + but that's not what GLU does here. + + (This says gluLookAt is left-handed, so maybe that's part of it?) + https://stackoverflow.com/questions/25933581/how-u-v-n-camera-coordinate-system-explained-with-opengl + */ + rotated[0] = dotproduct(position, U); + rotated[1] = -dotproduct(position, V); + rotated[2] = -dotproduct(position, N); + + /* At this point, we have rotated vector and we can calculate the angle + from 0 (directly in front of where the listener is facing) to 180 + degrees (directly behind) ... */ + + mags = magnitude(at) * magnitude(rotated); + radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct(at, rotated) / mags); + /* and we already have what we need to decide if those degrees are on the + listener's left or right... + https://gamedev.stackexchange.com/questions/43897/determining-if-something-is-on-the-right-or-left-side-of-an-object + ...we already did this dot product: it's in rotated[0]. */ + + /* make it negative to the left, positive to the right. */ + if (rotated[0] < 0.0f) { + radians = -radians; + } + #endif + } + + /* here comes the Constant Power Panning magic... */ + #define SQRT2_DIV2 0.7071067812f /* sqrt(2.0) / 2.0 ... */ + + /* this might be a terrible idea, which is totally my own doing here, + but here you go: Constant Power Panning only works from -45 to 45 + degrees in front of the listener. So we split this into 4 quadrants. + - from -45 to 45: standard panning. + - from 45 to 135: pan full right. + - from 135 to 225: flip angle so it works like standard panning. + - from 225 to -45: pan full left. */ + + #define RADIANS_45_DEGREES 0.7853981634f + #define RADIANS_135_DEGREES 2.3561944902f + if ((radians >= -RADIANS_45_DEGREES) && (radians <= RADIANS_45_DEGREES)) { + ALfloat sine, cosine; + calculate_sincos(radians, &sine, &cosine); + gains[0] = (SQRT2_DIV2 * (cosine - sine)); + gains[1] = (SQRT2_DIV2 * (cosine + sine)); + } else if ((radians >= RADIANS_45_DEGREES) && (radians <= RADIANS_135_DEGREES)) { + gains[0] = 0.0f; + gains[1] = 1.0f; + } else if ((radians >= -RADIANS_135_DEGREES) && (radians <= -RADIANS_45_DEGREES)) { + gains[0] = 1.0f; + gains[1] = 0.0f; + } else if (radians < 0.0f) { /* back left */ + ALfloat sine, cosine; + calculate_sincos((ALfloat) -(radians + M_PI), &sine, &cosine); + gains[0] = (SQRT2_DIV2 * (cosine - sine)); + gains[1] = (SQRT2_DIV2 * (cosine + sine)); + } else { /* back right */ + ALfloat sine, cosine; + calculate_sincos((ALfloat) -(radians - M_PI), &sine, &cosine); + gains[0] = (SQRT2_DIV2 * (cosine - sine)); + gains[1] = (SQRT2_DIV2 * (cosine + sine)); + } + + /* apply distance attenuation and gain to positioning. */ + gains[0] *= gain; + gains[1] *= gain; +} + + +static ALCboolean mix_source(ALCcontext *ctx, ALsource *src, float *stream, int len, const ALboolean force_recalc) +{ + ALCboolean keep; + + keep = (SDL_AtomicGet(&src->state) == AL_PLAYING); + if (keep) { + SDL_assert(src->allocated); + if (src->recalc || force_recalc) { + SDL_MemoryBarrierAcquire(); + src->recalc = AL_FALSE; + calculate_channel_gains(ctx, src, src->panning); + } + if (src->type == AL_STATIC) { + BufferQueueItem fakequeue = { src->buffer, NULL }; + keep = mix_source_buffer_queue(ctx, src, &fakequeue, stream, len); + } else if (src->type == AL_STREAMING) { + obtain_newly_queued_buffers(&src->buffer_queue); + keep = mix_source_buffer_queue(ctx, src, src->buffer_queue.head, stream, len); + } else if (src->type == AL_UNDETERMINED) { + keep = ALC_FALSE; /* this has AL_BUFFER set to 0; just dump it. */ + } else { + SDL_assert(!"unknown source type"); + } + } + + return keep; +} + +/* move new play requests over to the mixer thread. */ +static void migrate_playlist_requests(ALCcontext *ctx) +{ + SourcePlayTodo *todo; + SourcePlayTodo *todoend; + SourcePlayTodo *i; + + do { /* take the todo list atomically, now we own it. */ + todo = (SourcePlayTodo *) ctx->playlist_todo; + } while (!SDL_AtomicCASPtr(&ctx->playlist_todo, todo, NULL)); + + if (!todo) { + return; /* nothing new. */ + } + + todoend = todo; + + /* ctx->playlist and ALsource->playlist_next are only every touched + by the mixer thread, and source pointers live until context destruction. */ + for (i = todo; i != NULL; i = i->next) { + todoend = i; + if ((i->source != ctx->playlist_tail) && (!i->source->playlist_next)) { + i->source->playlist_next = ctx->playlist; + if (!ctx->playlist) { + ctx->playlist_tail = i->source; + } + ctx->playlist = i->source; + } + } + + /* put these objects back in the pool for reuse */ + do { + todoend->next = i = (SourcePlayTodo *) ctx->device->playback.source_todo_pool; + } while (!SDL_AtomicCASPtr(&ctx->device->playback.source_todo_pool, i, todo)); +} + +static void mix_context(ALCcontext *ctx, float *stream, int len) +{ + const ALboolean force_recalc = ctx->recalc; + ALsource *next = NULL; + ALsource *prev = NULL; + ALsource *i; + + if (force_recalc) { + SDL_MemoryBarrierAcquire(); + ctx->recalc = AL_FALSE; + } + + migrate_playlist_requests(ctx); + + for (i = ctx->playlist; i != NULL; i = next) { + next = i->playlist_next; /* save this to a local in case we leave the list. */ + + SDL_LockMutex(ctx->source_lock); + if (!mix_source(ctx, i, stream, len, force_recalc)) { + /* take it out of the playlist. It wasn't actually playing or it just finished. */ + i->playlist_next = NULL; + if (next == NULL) { + SDL_assert(i == ctx->playlist_tail); + ctx->playlist_tail = prev; + } + if (prev) { + prev->playlist_next = next; + } else { + SDL_assert(i == ctx->playlist); + ctx->playlist = next; + } + SDL_AtomicSet(&i->mixer_accessible, 0); + } else { + prev = i; + } + SDL_UnlockMutex(ctx->source_lock); + } +} + +/* Disconnected devices move all PLAYING sources to STOPPED, making their buffer queues processed. */ +static void mix_disconnected_context(ALCcontext *ctx) +{ + ALsource *next = NULL; + ALsource *i; + + migrate_playlist_requests(ctx); + + for (i = ctx->playlist; i != NULL; i = next) { + next = i->playlist_next; + + SDL_LockMutex(ctx->source_lock); + /* remove from playlist; all playing things got stopped, paused/initial/stopped shouldn't be listed. */ + if (SDL_AtomicGet(&i->state) == AL_PLAYING) { + SDL_assert(i->allocated); + SDL_AtomicSet(&i->state, AL_STOPPED); + source_mark_all_buffers_processed(i); + } + + i->playlist_next = NULL; + SDL_AtomicSet(&i->mixer_accessible, 0); + SDL_UnlockMutex(ctx->source_lock); + } + ctx->playlist = NULL; + ctx->playlist_tail = NULL; +} + +/* We process all unsuspended ALC contexts during this call, mixing their + output to (stream). SDL then plays this mixed audio to the hardware. */ +static void SDLCALL playback_device_callback(void *userdata, Uint8 *stream, int len) +{ + ALCdevice *device = (ALCdevice *) userdata; + ALCcontext *ctx; + ALCboolean connected = ALC_FALSE; + + SDL_memset(stream, '\0', len); + + if (SDL_AtomicGet(&device->connected)) { + if (SDL_GetAudioDeviceStatus(device->sdldevice) == SDL_AUDIO_STOPPED) { + SDL_AtomicSet(&device->connected, ALC_FALSE); + } else { + connected = ALC_TRUE; + } + } + + for (ctx = device->playback.contexts; ctx != NULL; ctx = ctx->next) { + if (SDL_AtomicGet(&ctx->processing)) { + if (connected) { + mix_context(ctx, (float *) stream, len); + } else { + mix_disconnected_context(ctx); + } + } + } +} + +static ALCcontext *_alcCreateContext(ALCdevice *device, const ALCint* attrlist) +{ + ALCcontext *retval = NULL; + ALCsizei attrcount = 0; + ALCint freq = 48000; + ALCboolean sync = ALC_FALSE; + ALCint refresh = 100; + /* we don't care about ALC_MONO_SOURCES or ALC_STEREO_SOURCES as we have no hardware limitation. */ + + if (!device) { + set_alc_error(NULL, ALC_INVALID_DEVICE); + return NULL; + } + + if (!SDL_AtomicGet(&device->connected)) { + set_alc_error(device, ALC_INVALID_DEVICE); + return NULL; + } + + if (attrlist != NULL) { + ALCint attr; + while ((attr = attrlist[attrcount++]) != 0) { + switch (attr) { + case ALC_FREQUENCY: freq = attrlist[attrcount++]; break; + case ALC_REFRESH: refresh = attrlist[attrcount++]; break; + case ALC_SYNC: sync = (attrlist[attrcount++] ? ALC_TRUE : ALC_FALSE); break; + default: FIXME("fail for unknown attributes?"); break; + } + } + } + + FIXME("use these variables at some point"); (void) refresh; (void) sync; + + retval = (ALCcontext *) calloc_simd_aligned(sizeof (ALCcontext)); + if (!retval) { + set_alc_error(device, ALC_OUT_OF_MEMORY); + return NULL; + } + + /* Make sure everything that wants to use SIMD is aligned for it. */ + SDL_assert( (((size_t) &retval->listener.position[0]) % 16) == 0 ); + SDL_assert( (((size_t) &retval->listener.orientation[0]) % 16) == 0 ); + SDL_assert( (((size_t) &retval->listener.velocity[0]) % 16) == 0 ); + + retval->source_lock = SDL_CreateMutex(); + if (!retval->source_lock) { + set_alc_error(device, ALC_OUT_OF_MEMORY); + free_simd_aligned(retval); + return NULL; + } + + retval->attributes = (ALCint *) SDL_malloc(attrcount * sizeof (ALCint)); + if (!retval->attributes) { + set_alc_error(device, ALC_OUT_OF_MEMORY); + SDL_DestroyMutex(retval->source_lock); + free_simd_aligned(retval); + return NULL; + } + SDL_memcpy(retval->attributes, attrlist, attrcount * sizeof (ALCint)); + retval->attributes_count = attrcount; + + if (!device->sdldevice) { + SDL_AudioSpec desired; + const char *devicename = device->name; + + if (SDL_strcmp(devicename, DEFAULT_PLAYBACK_DEVICE) == 0) { + devicename = NULL; /* tell SDL we want the best default */ + } + + /* we always want to work in float32, to keep our work simple and + let us use SIMD, and we'll let SDL convert when feeding the device. */ + SDL_zero(desired); + desired.freq = freq; + desired.format = AUDIO_F32SYS; + desired.channels = 2; FIXME("don't force channels?"); + desired.samples = 1024; FIXME("base this on refresh"); + desired.callback = playback_device_callback; + desired.userdata = device; + device->sdldevice = SDL_OpenAudioDevice(devicename, 0, &desired, NULL, 0); + if (!device->sdldevice) { + SDL_DestroyMutex(retval->source_lock); + SDL_free(retval->attributes); + free_simd_aligned(retval); + FIXME("What error do you set for this?"); + return NULL; + } + device->channels = 2; + device->frequency = freq; + device->framesize = sizeof (float) * device->channels; + SDL_PauseAudioDevice(device->sdldevice, 0); + } + + retval->distance_model = AL_INVERSE_DISTANCE_CLAMPED; + retval->doppler_factor = 1.0f; + retval->doppler_velocity = 1.0f; + retval->speed_of_sound = 343.3f; + retval->listener.gain = 1.0f; + retval->listener.orientation[2] = -1.0f; + retval->listener.orientation[5] = 1.0f; + retval->device = device; + context_needs_recalc(retval); + SDL_AtomicSet(&retval->processing, 1); /* contexts default to processing */ + + SDL_LockAudioDevice(device->sdldevice); + if (device->playback.contexts != NULL) { + SDL_assert(device->playback.contexts->prev == NULL); + device->playback.contexts->prev = retval; + } + retval->next = device->playback.contexts; + device->playback.contexts = retval; + SDL_UnlockAudioDevice(device->sdldevice); + + return retval; +} +ENTRYPOINT(ALCcontext *,alcCreateContext,(ALCdevice *device, const ALCint* attrlist),(device,attrlist)) + + +static SDL_INLINE ALCcontext *get_current_context(void) +{ + return (ALCcontext *) SDL_AtomicGetPtr(¤t_context); +} + +/* no api lock; it just sets an atomic pointer at the moment */ +ALCboolean alcMakeContextCurrent(ALCcontext *ctx) +{ + SDL_AtomicSetPtr(¤t_context, ctx); + FIXME("any reason this might return ALC_FALSE?"); + return ALC_TRUE; +} + +static void _alcProcessContext(ALCcontext *ctx) +{ + if (!ctx) { + set_alc_error(NULL, ALC_INVALID_CONTEXT); + return; + } + + SDL_assert(!ctx->device->iscapture); + SDL_AtomicSet(&ctx->processing, 1); +} +ENTRYPOINTVOID(alcProcessContext,(ALCcontext *ctx),(ctx)) + +static void _alcSuspendContext(ALCcontext *ctx) +{ + if (!ctx) { + set_alc_error(NULL, ALC_INVALID_CONTEXT); + } else { + SDL_assert(!ctx->device->iscapture); + SDL_AtomicSet(&ctx->processing, 0); + } +} +ENTRYPOINTVOID(alcSuspendContext,(ALCcontext *ctx),(ctx)) + +static void _alcDestroyContext(ALCcontext *ctx) +{ + ALsizei blocki; + + FIXME("Should NULL context be an error?"); + if (!ctx) return; + + /* The spec says it's illegal to delete the current context. */ + if (get_current_context() == ctx) { + set_alc_error(ctx->device, ALC_INVALID_CONTEXT); + return; + } + + /* do this first in case the mixer is running _right now_. */ + SDL_AtomicSet(&ctx->processing, 0); + + SDL_LockAudioDevice(ctx->device->sdldevice); + if (ctx->prev) { + ctx->prev->next = ctx->next; + } else { + SDL_assert(ctx == ctx->device->playback.contexts); + ctx->device->playback.contexts = ctx->next; + } + if (ctx->next) { + ctx->next->prev = ctx->prev; + } + SDL_UnlockAudioDevice(ctx->device->sdldevice); + + for (blocki = 0; blocki < ctx->num_source_blocks; blocki++) { + SourceBlock *sb = ctx->source_blocks[blocki]; + if (sb->used > 0) { + ALsizei i; + for (i = 0; i < SDL_arraysize(sb->sources); i++) { + ALsource *src = &sb->sources[i]; + if (!src->allocated) { + continue; + } + + SDL_FreeAudioStream(src->stream); + source_release_buffer_queue(ctx, src); + if (--sb->used == 0) { + break; + } + } + } + free_simd_aligned(sb); + } + + SDL_DestroyMutex(ctx->source_lock); + SDL_free(ctx->source_blocks); + SDL_free(ctx->attributes); + free_simd_aligned(ctx); +} +ENTRYPOINTVOID(alcDestroyContext,(ALCcontext *ctx),(ctx)) + +/* no api lock; atomic. */ +ALCcontext *alcGetCurrentContext(void) +{ + return get_current_context(); +} + +/* no api lock; immutable. */ +ALCdevice *alcGetContextsDevice(ALCcontext *context) +{ + return context ? context->device : NULL; +} + +static ALCenum _alcGetError(ALCdevice *device) +{ + ALCenum *perr = device ? &device->error : &null_device_error; + const ALCenum retval = *perr; + *perr = ALC_NO_ERROR; + return retval; +} +ENTRYPOINT(ALCenum,alcGetError,(ALCdevice *device),(device)) + +/* no api lock; immutable */ +ALCboolean alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname) +{ + #define ALC_EXTENSION_ITEM(ext) if (SDL_strcasecmp(extname, #ext) == 0) { return ALC_TRUE; } + ALC_EXTENSION_ITEMS + #undef ALC_EXTENSION_ITEM + return ALC_FALSE; +} + +/* no api lock; immutable */ +void *alcGetProcAddress(ALCdevice *device, const ALCchar *funcname) +{ + if (!funcname) { + set_alc_error(device, ALC_INVALID_VALUE); + return NULL; + } + + #define FN_TEST(fn) if (SDL_strcmp(funcname, #fn) == 0) return (void *) fn + FN_TEST(alcCreateContext); + FN_TEST(alcMakeContextCurrent); + FN_TEST(alcProcessContext); + FN_TEST(alcSuspendContext); + FN_TEST(alcDestroyContext); + FN_TEST(alcGetCurrentContext); + FN_TEST(alcGetContextsDevice); + FN_TEST(alcOpenDevice); + FN_TEST(alcCloseDevice); + FN_TEST(alcGetError); + FN_TEST(alcIsExtensionPresent); + FN_TEST(alcGetProcAddress); + FN_TEST(alcGetEnumValue); + FN_TEST(alcGetString); + FN_TEST(alcGetIntegerv); + FN_TEST(alcCaptureOpenDevice); + FN_TEST(alcCaptureCloseDevice); + FN_TEST(alcCaptureStart); + FN_TEST(alcCaptureStop); + FN_TEST(alcCaptureSamples); + #undef FN_TEST + + set_alc_error(device, ALC_INVALID_VALUE); + return NULL; +} + +/* no api lock; immutable */ +ALCenum alcGetEnumValue(ALCdevice *device, const ALCchar *enumname) +{ + if (!enumname) { + set_alc_error(device, ALC_INVALID_VALUE); + return (ALCenum) AL_NONE; + } + + #define ENUM_TEST(en) if (SDL_strcmp(enumname, #en) == 0) return en + ENUM_TEST(ALC_FALSE); + ENUM_TEST(ALC_TRUE); + ENUM_TEST(ALC_FREQUENCY); + ENUM_TEST(ALC_REFRESH); + ENUM_TEST(ALC_SYNC); + ENUM_TEST(ALC_MONO_SOURCES); + ENUM_TEST(ALC_STEREO_SOURCES); + ENUM_TEST(ALC_NO_ERROR); + ENUM_TEST(ALC_INVALID_DEVICE); + ENUM_TEST(ALC_INVALID_CONTEXT); + ENUM_TEST(ALC_INVALID_ENUM); + ENUM_TEST(ALC_INVALID_VALUE); + ENUM_TEST(ALC_OUT_OF_MEMORY); + ENUM_TEST(ALC_MAJOR_VERSION); + ENUM_TEST(ALC_MINOR_VERSION); + ENUM_TEST(ALC_ATTRIBUTES_SIZE); + ENUM_TEST(ALC_ALL_ATTRIBUTES); + ENUM_TEST(ALC_DEFAULT_DEVICE_SPECIFIER); + ENUM_TEST(ALC_DEVICE_SPECIFIER); + ENUM_TEST(ALC_EXTENSIONS); + ENUM_TEST(ALC_CAPTURE_DEVICE_SPECIFIER); + ENUM_TEST(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); + ENUM_TEST(ALC_CAPTURE_SAMPLES); + ENUM_TEST(ALC_DEFAULT_ALL_DEVICES_SPECIFIER); + ENUM_TEST(ALC_ALL_DEVICES_SPECIFIER); + ENUM_TEST(ALC_CONNECTED); + #undef ENUM_TEST + + set_alc_error(device, ALC_INVALID_VALUE); + return (ALCenum) AL_NONE; +} + +static const ALCchar *calculate_sdl_device_list(const int iscapture) +{ + /* alcGetString() has to return a const string that is not freed and might + continue to live even if we update this list in a later query, so we + just make a big static buffer and hope it's large enough and that other + race conditions don't bite us. The enumeration extension shouldn't have + reused entry points, or done this silly null-delimited string list. + Oh well. */ + #define DEVICE_LIST_BUFFER_SIZE 512 + static ALCchar playback_list[DEVICE_LIST_BUFFER_SIZE]; + static ALCchar capture_list[DEVICE_LIST_BUFFER_SIZE]; + ALCchar *final_list = iscapture ? capture_list : playback_list; + ALCchar *ptr = final_list; + int numdevs; + size_t avail = DEVICE_LIST_BUFFER_SIZE; + size_t cpy; + int i; + + /* default device is always available. */ + cpy = SDL_strlcpy(ptr, iscapture ? DEFAULT_CAPTURE_DEVICE : DEFAULT_PLAYBACK_DEVICE, avail); + SDL_assert((cpy+1) < avail); + ptr += cpy + 1; /* skip past null char. */ + avail -= cpy + 1; + + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { + return NULL; + } + + if (!init_api_lock()) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; + } + + grab_api_lock(); + + numdevs = SDL_GetNumAudioDevices(iscapture); + + for (i = 0; i < numdevs; i++) { + const char *devname = SDL_GetAudioDeviceName(i, iscapture); + const size_t devnamelen = SDL_strlen(devname); + /* if we're out of space, we just have to drop devices we can't cram in the buffer. */ + if (avail > (devnamelen + 2)) { + cpy = SDL_strlcpy(ptr, devname, avail); + SDL_assert(cpy == devnamelen); + SDL_assert((cpy+1) < avail); + ptr += cpy + 1; /* skip past null char. */ + avail -= cpy + 1; + } + } + + SDL_assert(avail >= 1); + *ptr = '\0'; + + ungrab_api_lock(); + + SDL_QuitSubSystem(SDL_INIT_AUDIO); + + return final_list; + + #undef DEVICE_LIST_BUFFER_SIZE +} + +/* no api lock; immutable (unless it isn't, then we manually lock). */ +const ALCchar *alcGetString(ALCdevice *device, ALCenum param) +{ + switch (param) { + case ALC_EXTENSIONS: { + #define ALC_EXTENSION_ITEM(ext) " " #ext + static ALCchar alc_extensions_string[] = ALC_EXTENSION_ITEMS; + #undef ALC_EXTENSION_ITEM + return alc_extensions_string + 1; /* skip that first space char */ + } + + /* You open the default SDL device with a NULL device name, but that is how OpenAL + reports an error here, so we give it a magic identifier here instead. */ + case ALC_DEFAULT_DEVICE_SPECIFIER: + return DEFAULT_PLAYBACK_DEVICE; + + case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: + return DEFAULT_CAPTURE_DEVICE; + + case ALC_DEVICE_SPECIFIER: + FIXME("should return NULL if device->iscapture?"); + return device ? device->name : calculate_sdl_device_list(0); + + case ALC_CAPTURE_DEVICE_SPECIFIER: + FIXME("should return NULL if !device->iscapture?"); + return device ? device->name : calculate_sdl_device_list(1); + + case ALC_NO_ERROR: return "ALC_NO_ERROR"; + case ALC_INVALID_DEVICE: return "ALC_INVALID_DEVICE"; + case ALC_INVALID_CONTEXT:return "ALC_INVALID_CONTEXT"; + case ALC_INVALID_ENUM: return "ALC_INVALID_ENUM"; + case ALC_INVALID_VALUE: return "ALC_INVALID_VALUE"; + case ALC_OUT_OF_MEMORY: return "ALC_OUT_OF_MEMORY"; + + default: break; + } + + FIXME("other enums that should report as strings?"); + set_alc_error(device, ALC_INVALID_ENUM); + return NULL; +} + +static void _alcGetIntegerv(ALCdevice *device, const ALCenum param, const ALCsizei size, ALCint *values) +{ + ALCcontext *ctx = NULL; + + if (!size || !values) { + return; /* "A NULL destination or a zero size parameter will cause ALC to ignore the query." */ + } + + switch (param) { + case ALC_CAPTURE_SAMPLES: + if (!device || !device->iscapture) { + set_alc_error(device, ALC_INVALID_DEVICE); + return; + } + + FIXME("make ring buffer atomic?"); + SDL_LockAudioDevice(device->sdldevice); + *values = (ALCint) (device->capture.ring.used / device->framesize); + SDL_UnlockAudioDevice(device->sdldevice); + return; + + case ALC_CONNECTED: + if (device) { + *values = SDL_AtomicGet(&device->connected) ? ALC_TRUE : ALC_FALSE; + } else { + *values = ALC_FALSE; + set_alc_error(device, ALC_INVALID_DEVICE); + } + return; + + case ALC_ATTRIBUTES_SIZE: + case ALC_ALL_ATTRIBUTES: + if (!device || device->iscapture) { + *values = 0; + set_alc_error(device, ALC_INVALID_DEVICE); + return; + } + + ctx = get_current_context(); + + FIXME("wants 'current context of specified device', but there isn't a current context per-device..."); + if ((!ctx) || (ctx->device != device)) { + *values = 0; + set_alc_error(device, ALC_INVALID_CONTEXT); + return; + } + + if (param == ALC_ALL_ATTRIBUTES) { + if (size < ctx->attributes_count) { + *values = 0; + set_alc_error(device, ALC_INVALID_VALUE); + return; + } + SDL_memcpy(values, ctx->attributes, ctx->attributes_count * sizeof (ALCint)); + } else { + *values = (ALCint) ctx->attributes_count; + } + return; + + case ALC_MAJOR_VERSION: + *values = OPENAL_VERSION_MAJOR; + return; + + case ALC_MINOR_VERSION: + *values = OPENAL_VERSION_MINOR; + return; + + default: break; + } + + set_alc_error(device, ALC_INVALID_ENUM); + *values = 0; +} +ENTRYPOINTVOID(alcGetIntegerv,(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values),(device,param,size,values)) + + +/* audio callback for capture devices just needs to move data into our + ringbuffer for later recovery by the app in alcCaptureSamples(). SDL + should have handled resampling and conversion for us to the expected + audio format. */ +static void SDLCALL capture_device_callback(void *userdata, Uint8 *stream, int len) +{ + ALCdevice *device = (ALCdevice *) userdata; + ALCboolean connected = ALC_FALSE; + SDL_assert(device->iscapture); + + if (SDL_AtomicGet(&device->connected)) { + if (SDL_GetAudioDeviceStatus(device->sdldevice) == SDL_AUDIO_STOPPED) { + SDL_AtomicSet(&device->connected, ALC_FALSE); + } else { + connected = ALC_TRUE; + } + } + + if (connected) { + ring_buffer_put(&device->capture.ring, stream, (ALCsizei) len); + } +} + +/* no api lock; this creates it and otherwise doesn't have any state that can race */ +ALCdevice *alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) +{ + SDL_AudioSpec desired; + ALCsizei framesize = 0; + const char *sdldevname = NULL; + ALCdevice *device = NULL; + ALCubyte *ringbuf = NULL; + + SDL_zero(desired); + if (!alcfmt_to_sdlfmt(format, &desired.format, &desired.channels, &framesize)) { + return NULL; + } + + if (!devicename) { + devicename = DEFAULT_CAPTURE_DEVICE; /* so ALC_CAPTURE_DEVICE_SPECIFIER is meaningful */ + } + + desired.freq = frequency; + desired.samples = 1024; FIXME("is this a reasonable value?"); + desired.callback = capture_device_callback; + + if (SDL_strcmp(devicename, DEFAULT_CAPTURE_DEVICE) != 0) { + sdldevname = devicename; /* we want NULL for the best SDL default unless app is explicit. */ + } + + device = prep_alc_device(devicename, ALC_TRUE); + if (!device) { + return NULL; + } + + device->frequency = frequency; + device->framesize = framesize; + device->capture.ring.size = framesize * buffersize; + + if (device->capture.ring.size >= buffersize) { + ringbuf = (ALCubyte *) SDL_malloc(device->capture.ring.size); + } + + if (!ringbuf) { + SDL_free(device->name); + SDL_free(device); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; + } + + device->capture.ring.buffer = ringbuf; + + desired.userdata = device; + + device->sdldevice = SDL_OpenAudioDevice(sdldevname, 1, &desired, NULL, 0); + if (!device->sdldevice) { + SDL_free(ringbuf); + SDL_free(device->name); + SDL_free(device); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return NULL; + } + + return device; +} + +/* no api lock; this requires you to not destroy a device that's still in use */ +ALCboolean alcCaptureCloseDevice(ALCdevice *device) +{ + if (!device || !device->iscapture) { + return ALC_FALSE; + } + + if (device->sdldevice) { + SDL_CloseAudioDevice(device->sdldevice); + } + + SDL_free(device->capture.ring.buffer); + SDL_free(device->name); + SDL_free(device); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + + return ALC_TRUE; +} + +static void _alcCaptureStart(ALCdevice *device) +{ + if (device && device->iscapture) { + /* alcCaptureStart() drops any previously-buffered data. */ + FIXME("does this clear the ring buffer if the device is already started?"); + SDL_LockAudioDevice(device->sdldevice); + device->capture.ring.read = 0; + device->capture.ring.write = 0; + device->capture.ring.used = 0; + SDL_UnlockAudioDevice(device->sdldevice); + SDL_PauseAudioDevice(device->sdldevice, 0); + } +} +ENTRYPOINTVOID(alcCaptureStart,(ALCdevice *device),(device)) + +static void _alcCaptureStop(ALCdevice *device) +{ + if (device && device->iscapture) { + SDL_PauseAudioDevice(device->sdldevice, 1); + } +} +ENTRYPOINTVOID(alcCaptureStop,(ALCdevice *device),(device)) + +static void _alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, const ALCsizei samples) +{ + ALCsizei requested_bytes; + if (!device || !device->iscapture) { + return; + } + + requested_bytes = samples * device->framesize; + + SDL_LockAudioDevice(device->sdldevice); + if (requested_bytes > device->capture.ring.used) { + SDL_UnlockAudioDevice(device->sdldevice); + FIXME("set error state?"); + return; /* this is an error state, according to the spec. */ + } + + ring_buffer_get(&device->capture.ring, buffer, requested_bytes); + SDL_UnlockAudioDevice(device->sdldevice); +} +ENTRYPOINTVOID(alcCaptureSamples,(ALCdevice *device, ALCvoid *buffer, ALCsizei samples),(device,buffer,samples)) + + +/* AL implementation... */ + +static ALenum null_context_error = AL_NO_ERROR; + +static void set_al_error(ALCcontext *ctx, const ALenum error) +{ + ALenum *perr = ctx ? &ctx->error : &null_context_error; + /* can't set a new error when the previous hasn't been cleared yet. */ + if (*perr == AL_NO_ERROR) { + *perr = error; + } +} + +/* !!! FIXME: buffers and sources use almost identical code for blocks */ +static ALsource *get_source(ALCcontext *ctx, const ALuint name, SourceBlock **_block) +{ + const ALsizei blockidx = (((ALsizei) name) - 1) / OPENAL_SOURCE_BLOCK_SIZE; + const ALsizei block_offset = (((ALsizei) name) - 1) % OPENAL_SOURCE_BLOCK_SIZE; + ALsource *source; + SourceBlock *block; + + /*printf("get_source(%d): blockidx=%d, block_offset=%d\n", (int) name, (int) blockidx, (int) block_offset);*/ + + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + if (_block) *_block = NULL; + return NULL; + } else if ((name == 0) || (blockidx >= ctx->num_source_blocks)) { + set_al_error(ctx, AL_INVALID_NAME); + if (_block) *_block = NULL; + return NULL; + } + + block = ctx->source_blocks[blockidx]; + source = &block->sources[block_offset]; + if (source->allocated) { + if (_block) *_block = block; + return source; + } + + if (_block) *_block = NULL; + set_al_error(ctx, AL_INVALID_NAME); + return NULL; +} + +/* !!! FIXME: buffers and sources use almost identical code for blocks */ +static ALbuffer *get_buffer(ALCcontext *ctx, const ALuint name, BufferBlock **_block) +{ + const ALsizei blockidx = (((ALsizei) name) - 1) / OPENAL_BUFFER_BLOCK_SIZE; + const ALsizei block_offset = (((ALsizei) name) - 1) % OPENAL_BUFFER_BLOCK_SIZE; + ALbuffer *buffer; + BufferBlock *block; + + /*printf("get_buffer(%d): blockidx=%d, block_offset=%d\n", (int) name, (int) blockidx, (int) block_offset);*/ + + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + if (_block) *_block = NULL; + return NULL; + } else if ((name == 0) || (blockidx >= ctx->device->playback.num_buffer_blocks)) { + set_al_error(ctx, AL_INVALID_NAME); + if (_block) *_block = NULL; + return NULL; + } + + block = ctx->device->playback.buffer_blocks[blockidx]; + buffer = &block->buffers[block_offset]; + if (buffer->allocated) { + if (_block) *_block = block; + return buffer; + } + + if (_block) *_block = NULL; + set_al_error(ctx, AL_INVALID_NAME); + return NULL; +} + +static void _alDopplerFactor(const ALfloat value) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + } else if (value < 0.0f) { + set_al_error(ctx, AL_INVALID_VALUE); + } else { + ctx->doppler_factor = value; + context_needs_recalc(ctx); + } +} +ENTRYPOINTVOID(alDopplerFactor,(ALfloat value),(value)) + +static void _alDopplerVelocity(const ALfloat value) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + } else if (value < 0.0f) { + set_al_error(ctx, AL_INVALID_VALUE); + } else { + ctx->doppler_velocity = value; + context_needs_recalc(ctx); + } +} +ENTRYPOINTVOID(alDopplerVelocity,(ALfloat value),(value)) + +static void _alSpeedOfSound(const ALfloat value) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + } else if (value < 0.0f) { + set_al_error(ctx, AL_INVALID_VALUE); + } else { + ctx->speed_of_sound = value; + context_needs_recalc(ctx); + } +} +ENTRYPOINTVOID(alSpeedOfSound,(ALfloat value),(value)) + +static void _alDistanceModel(const ALenum model) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + switch (model) { + case AL_NONE: + case AL_INVERSE_DISTANCE: + case AL_INVERSE_DISTANCE_CLAMPED: + case AL_LINEAR_DISTANCE: + case AL_LINEAR_DISTANCE_CLAMPED: + case AL_EXPONENT_DISTANCE: + case AL_EXPONENT_DISTANCE_CLAMPED: + ctx->distance_model = model; + context_needs_recalc(ctx); + return; + default: break; + } + set_al_error(ctx, AL_INVALID_ENUM); +} +ENTRYPOINTVOID(alDistanceModel,(ALenum model),(model)) + + +static void _alEnable(const ALenum capability) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alEnable,(ALenum capability),(capability)) + + +static void _alDisable(const ALenum capability) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alDisable,(ALenum capability),(capability)) + + +static ALboolean _alIsEnabled(const ALenum capability) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ + return AL_FALSE; +} +ENTRYPOINT(ALboolean,alIsEnabled,(ALenum capability),(capability)) + +static const ALchar *_alGetString(const ALenum param) +{ + switch (param) { + case AL_EXTENSIONS: { + #define AL_EXTENSION_ITEM(ext) " " #ext + static ALchar al_extensions_string[] = AL_EXTENSION_ITEMS; + #undef AL_EXTENSION_ITEM + return al_extensions_string + 1; /* skip that first space char */ + } + + case AL_VERSION: return OPENAL_VERSION_STRING; + case AL_RENDERER: return OPENAL_RENDERER_STRING; + case AL_VENDOR: return OPENAL_VENDOR_STRING; + case AL_NO_ERROR: return "AL_NO_ERROR"; + case AL_INVALID_NAME: return "AL_INVALID_NAME"; + case AL_INVALID_ENUM: return "AL_INVALID_ENUM"; + case AL_INVALID_VALUE: return "AL_INVALID_VALUE"; + case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION"; + case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY"; + + default: break; + } + + FIXME("other enums that should report as strings?"); + set_al_error(get_current_context(), AL_INVALID_ENUM); + + return NULL; +} +ENTRYPOINT(const ALchar *,alGetString,(const ALenum param),(param)) + +static void _alGetBooleanv(const ALenum param, ALboolean *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (!values) return; /* legal no-op */ + + /* nothing in core OpenAL 1.1 uses this */ + set_al_error(ctx, AL_INVALID_ENUM); +} +ENTRYPOINTVOID(alGetBooleanv,(ALenum param, ALboolean *values),(param,values)) + +static void _alGetIntegerv(const ALenum param, ALint *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (!values) return; /* legal no-op */ + + switch (param) { + case AL_DISTANCE_MODEL: *values = (ALint) ctx->distance_model; break; + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetIntegerv,(ALenum param, ALint *values),(param,values)) + +static void _alGetFloatv(const ALenum param, ALfloat *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (!values) return; /* legal no-op */ + + switch (param) { + case AL_DOPPLER_FACTOR: *values = ctx->doppler_factor; break; + case AL_DOPPLER_VELOCITY: *values = ctx->doppler_velocity; break; + case AL_SPEED_OF_SOUND: *values = ctx->speed_of_sound; break; + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetFloatv,(ALenum param, ALfloat *values),(param,values)) + +static void _alGetDoublev(const ALenum param, ALdouble *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (!values) return; /* legal no-op */ + + /* nothing in core OpenAL 1.1 uses this */ + set_al_error(ctx, AL_INVALID_ENUM); +} +ENTRYPOINTVOID(alGetDoublev,(ALenum param, ALdouble *values),(param,values)) + +/* no api lock; just passes through to the real api */ +ALboolean alGetBoolean(ALenum param) +{ + ALboolean retval = AL_FALSE; + alGetBooleanv(param, &retval); + return retval; +} + +/* no api lock; just passes through to the real api */ +ALint alGetInteger(ALenum param) +{ + ALint retval = 0; + alGetIntegerv(param, &retval); + return retval; +} + +/* no api lock; just passes through to the real api */ +ALfloat alGetFloat(ALenum param) +{ + ALfloat retval = 0.0f; + alGetFloatv(param, &retval); + return retval; +} + +/* no api lock; just passes through to the real api */ +ALdouble alGetDouble(ALenum param) +{ + ALdouble retval = 0.0f; + alGetDoublev(param, &retval); + return retval; +} + +static ALenum _alGetError(void) +{ + ALCcontext *ctx = get_current_context(); + ALenum *perr = ctx ? &ctx->error : &null_context_error; + const ALenum retval = *perr; + *perr = AL_NO_ERROR; + return retval; +} +ENTRYPOINT(ALenum,alGetError,(void),()) + +/* no api lock; immutable (unless we start having contexts with different extensions) */ +ALboolean alIsExtensionPresent(const ALchar *extname) +{ + #define AL_EXTENSION_ITEM(ext) if (SDL_strcasecmp(extname, #ext) == 0) { return AL_TRUE; } + AL_EXTENSION_ITEMS + #undef AL_EXTENSION_ITEM + return AL_FALSE; +} + +static void *_alGetProcAddress(const ALchar *funcname) +{ + ALCcontext *ctx = get_current_context(); + FIXME("fail if ctx == NULL?"); + if (!funcname) { + set_al_error(ctx, AL_INVALID_VALUE); + return NULL; + } + + #define FN_TEST(fn) if (SDL_strcmp(funcname, #fn) == 0) return (void *) fn + FN_TEST(alDopplerFactor); + FN_TEST(alDopplerVelocity); + FN_TEST(alSpeedOfSound); + FN_TEST(alDistanceModel); + FN_TEST(alEnable); + FN_TEST(alDisable); + FN_TEST(alIsEnabled); + FN_TEST(alGetString); + FN_TEST(alGetBooleanv); + FN_TEST(alGetIntegerv); + FN_TEST(alGetFloatv); + FN_TEST(alGetDoublev); + FN_TEST(alGetBoolean); + FN_TEST(alGetInteger); + FN_TEST(alGetFloat); + FN_TEST(alGetDouble); + FN_TEST(alGetError); + FN_TEST(alIsExtensionPresent); + FN_TEST(alGetProcAddress); + FN_TEST(alGetEnumValue); + FN_TEST(alListenerf); + FN_TEST(alListener3f); + FN_TEST(alListenerfv); + FN_TEST(alListeneri); + FN_TEST(alListener3i); + FN_TEST(alListeneriv); + FN_TEST(alGetListenerf); + FN_TEST(alGetListener3f); + FN_TEST(alGetListenerfv); + FN_TEST(alGetListeneri); + FN_TEST(alGetListener3i); + FN_TEST(alGetListeneriv); + FN_TEST(alGenSources); + FN_TEST(alDeleteSources); + FN_TEST(alIsSource); + FN_TEST(alSourcef); + FN_TEST(alSource3f); + FN_TEST(alSourcefv); + FN_TEST(alSourcei); + FN_TEST(alSource3i); + FN_TEST(alSourceiv); + FN_TEST(alGetSourcef); + FN_TEST(alGetSource3f); + FN_TEST(alGetSourcefv); + FN_TEST(alGetSourcei); + FN_TEST(alGetSource3i); + FN_TEST(alGetSourceiv); + FN_TEST(alSourcePlayv); + FN_TEST(alSourceStopv); + FN_TEST(alSourceRewindv); + FN_TEST(alSourcePausev); + FN_TEST(alSourcePlay); + FN_TEST(alSourceStop); + FN_TEST(alSourceRewind); + FN_TEST(alSourcePause); + FN_TEST(alSourceQueueBuffers); + FN_TEST(alSourceUnqueueBuffers); + FN_TEST(alGenBuffers); + FN_TEST(alDeleteBuffers); + FN_TEST(alIsBuffer); + FN_TEST(alBufferData); + FN_TEST(alBufferf); + FN_TEST(alBuffer3f); + FN_TEST(alBufferfv); + FN_TEST(alBufferi); + FN_TEST(alBuffer3i); + FN_TEST(alBufferiv); + FN_TEST(alGetBufferf); + FN_TEST(alGetBuffer3f); + FN_TEST(alGetBufferfv); + FN_TEST(alGetBufferi); + FN_TEST(alGetBuffer3i); + FN_TEST(alGetBufferiv); + #undef FN_TEST + + set_al_error(ctx, ALC_INVALID_VALUE); + return NULL; +} +ENTRYPOINT(void *,alGetProcAddress,(const ALchar *funcname),(funcname)) + +static ALenum _alGetEnumValue(const ALchar *enumname) +{ + ALCcontext *ctx = get_current_context(); + FIXME("fail if ctx == NULL?"); + if (!enumname) { + set_al_error(ctx, AL_INVALID_VALUE); + return AL_NONE; + } + + #define ENUM_TEST(en) if (SDL_strcmp(enumname, #en) == 0) return en + ENUM_TEST(AL_NONE); + ENUM_TEST(AL_FALSE); + ENUM_TEST(AL_TRUE); + ENUM_TEST(AL_SOURCE_RELATIVE); + ENUM_TEST(AL_CONE_INNER_ANGLE); + ENUM_TEST(AL_CONE_OUTER_ANGLE); + ENUM_TEST(AL_PITCH); + ENUM_TEST(AL_POSITION); + ENUM_TEST(AL_DIRECTION); + ENUM_TEST(AL_VELOCITY); + ENUM_TEST(AL_LOOPING); + ENUM_TEST(AL_BUFFER); + ENUM_TEST(AL_GAIN); + ENUM_TEST(AL_MIN_GAIN); + ENUM_TEST(AL_MAX_GAIN); + ENUM_TEST(AL_ORIENTATION); + ENUM_TEST(AL_SOURCE_STATE); + ENUM_TEST(AL_INITIAL); + ENUM_TEST(AL_PLAYING); + ENUM_TEST(AL_PAUSED); + ENUM_TEST(AL_STOPPED); + ENUM_TEST(AL_BUFFERS_QUEUED); + ENUM_TEST(AL_BUFFERS_PROCESSED); + ENUM_TEST(AL_REFERENCE_DISTANCE); + ENUM_TEST(AL_ROLLOFF_FACTOR); + ENUM_TEST(AL_CONE_OUTER_GAIN); + ENUM_TEST(AL_MAX_DISTANCE); + ENUM_TEST(AL_SEC_OFFSET); + ENUM_TEST(AL_SAMPLE_OFFSET); + ENUM_TEST(AL_BYTE_OFFSET); + ENUM_TEST(AL_SOURCE_TYPE); + ENUM_TEST(AL_STATIC); + ENUM_TEST(AL_STREAMING); + ENUM_TEST(AL_UNDETERMINED); + ENUM_TEST(AL_FORMAT_MONO8); + ENUM_TEST(AL_FORMAT_MONO16); + ENUM_TEST(AL_FORMAT_STEREO8); + ENUM_TEST(AL_FORMAT_STEREO16); + ENUM_TEST(AL_FREQUENCY); + ENUM_TEST(AL_BITS); + ENUM_TEST(AL_CHANNELS); + ENUM_TEST(AL_SIZE); + ENUM_TEST(AL_UNUSED); + ENUM_TEST(AL_PENDING); + ENUM_TEST(AL_PROCESSED); + ENUM_TEST(AL_NO_ERROR); + ENUM_TEST(AL_INVALID_NAME); + ENUM_TEST(AL_INVALID_ENUM); + ENUM_TEST(AL_INVALID_VALUE); + ENUM_TEST(AL_INVALID_OPERATION); + ENUM_TEST(AL_OUT_OF_MEMORY); + ENUM_TEST(AL_VENDOR); + ENUM_TEST(AL_VERSION); + ENUM_TEST(AL_RENDERER); + ENUM_TEST(AL_EXTENSIONS); + ENUM_TEST(AL_DOPPLER_FACTOR); + ENUM_TEST(AL_DOPPLER_VELOCITY); + ENUM_TEST(AL_SPEED_OF_SOUND); + ENUM_TEST(AL_DISTANCE_MODEL); + ENUM_TEST(AL_INVERSE_DISTANCE); + ENUM_TEST(AL_INVERSE_DISTANCE_CLAMPED); + ENUM_TEST(AL_LINEAR_DISTANCE); + ENUM_TEST(AL_LINEAR_DISTANCE_CLAMPED); + ENUM_TEST(AL_EXPONENT_DISTANCE); + ENUM_TEST(AL_EXPONENT_DISTANCE_CLAMPED); + ENUM_TEST(AL_FORMAT_MONO_FLOAT32); + ENUM_TEST(AL_FORMAT_STEREO_FLOAT32); + #undef ENUM_TEST + + set_al_error(ctx, AL_INVALID_VALUE); + return AL_NONE; +} +ENTRYPOINT(ALenum,alGetEnumValue,(const ALchar *enumname),(enumname)) + +static void _alListenerfv(const ALenum param, const ALfloat *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + } else if (!values) { + set_al_error(ctx, AL_INVALID_VALUE); + } else { + ALboolean recalc = AL_TRUE; + switch (param) { + case AL_GAIN: + ctx->listener.gain = *values; + break; + + case AL_POSITION: + SDL_memcpy(ctx->listener.position, values, sizeof (*values) * 3); + break; + + case AL_VELOCITY: + SDL_memcpy(ctx->listener.velocity, values, sizeof (*values) * 3); + break; + + case AL_ORIENTATION: + SDL_memcpy(&ctx->listener.orientation[0], &values[0], sizeof (*values) * 3); + SDL_memcpy(&ctx->listener.orientation[4], &values[3], sizeof (*values) * 3); + break; + + default: + recalc = AL_FALSE; + set_al_error(ctx, AL_INVALID_ENUM); + break; + } + + if (recalc) { + context_needs_recalc(ctx); + } + } +} +ENTRYPOINTVOID(alListenerfv,(ALenum param, const ALfloat *values),(param,values)) + +static void _alListenerf(const ALenum param, const ALfloat value) +{ + switch (param) { + case AL_GAIN: _alListenerfv(param, &value); break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alListenerf,(ALenum param, ALfloat value),(param,value)) + +static void _alListener3f(const ALenum param, const ALfloat value1, const ALfloat value2, const ALfloat value3) +{ + switch (param) { + case AL_POSITION: + case AL_VELOCITY: { + const ALfloat values[3] = { value1, value2, value3 }; + _alListenerfv(param, values); + break; + } + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alListener3f,(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3),(param,value1,value2,value3)) + +static void _alListeneriv(const ALenum param, const ALint *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + } else if (!values) { + set_al_error(ctx, AL_INVALID_VALUE); + } else { + ALboolean recalc = AL_TRUE; + FIXME("Not atomic vs the mixer thread"); /* maybe have a latching system? */ + switch (param) { + case AL_POSITION: + ctx->listener.position[0] = (ALfloat) values[0]; + ctx->listener.position[1] = (ALfloat) values[1]; + ctx->listener.position[2] = (ALfloat) values[2]; + break; + + case AL_VELOCITY: + ctx->listener.velocity[0] = (ALfloat) values[0]; + ctx->listener.velocity[1] = (ALfloat) values[1]; + ctx->listener.velocity[2] = (ALfloat) values[2]; + break; + + case AL_ORIENTATION: + ctx->listener.orientation[0] = (ALfloat) values[0]; + ctx->listener.orientation[1] = (ALfloat) values[1]; + ctx->listener.orientation[2] = (ALfloat) values[2]; + ctx->listener.orientation[4] = (ALfloat) values[3]; + ctx->listener.orientation[5] = (ALfloat) values[4]; + ctx->listener.orientation[6] = (ALfloat) values[5]; + break; + + default: + recalc = AL_FALSE; + set_al_error(ctx, AL_INVALID_ENUM); + break; + } + + if (recalc) { + context_needs_recalc(ctx); + } + } +} +ENTRYPOINTVOID(alListeneriv,(ALenum param, const ALint *values),(param,values)) + +static void _alListeneri(const ALenum param, const ALint value) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in AL 1.1 uses this */ +} +ENTRYPOINTVOID(alListeneri,(ALenum param, ALint value),(param,value)) + +static void _alListener3i(const ALenum param, const ALint value1, const ALint value2, const ALint value3) +{ + switch (param) { + case AL_POSITION: + case AL_VELOCITY: { + const ALint values[3] = { value1, value2, value3 }; + _alListeneriv(param, values); + break; + } + default: + set_al_error(get_current_context(), AL_INVALID_ENUM); + break; + } +} +ENTRYPOINTVOID(alListener3i,(ALenum param, ALint value1, ALint value2, ALint value3),(param,value1,value2,value3)) + +static void _alGetListenerfv(const ALenum param, ALfloat *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (!values) return; /* legal no-op */ + + switch (param) { + case AL_GAIN: + *values = ctx->listener.gain; + break; + + case AL_POSITION: + SDL_memcpy(values, ctx->listener.position, sizeof (ALfloat) * 3); + break; + + case AL_VELOCITY: + SDL_memcpy(values, ctx->listener.velocity, sizeof (ALfloat) * 3); + break; + + case AL_ORIENTATION: + SDL_memcpy(&values[0], &ctx->listener.orientation[0], sizeof (ALfloat) * 3); + SDL_memcpy(&values[3], &ctx->listener.orientation[4], sizeof (ALfloat) * 3); + break; + + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetListenerfv,(ALenum param, ALfloat *values),(param,values)) + +static void _alGetListenerf(const ALenum param, ALfloat *value) +{ + switch (param) { + case AL_GAIN: _alGetListenerfv(param, value); break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetListenerf,(ALenum param, ALfloat *value),(param,value)) + + +static void _alGetListener3f(const ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) +{ + ALfloat values[3]; + switch (param) { + case AL_POSITION: + case AL_VELOCITY: + _alGetListenerfv(param, values); + if (value1) *value1 = values[0]; + if (value2) *value2 = values[1]; + if (value3) *value3 = values[2]; + break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetListener3f,(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3),(param,value1,value2,value3)) + + +static void _alGetListeneri(const ALenum param, ALint *value) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in AL 1.1 uses this */ +} +ENTRYPOINTVOID(alGetListeneri,(ALenum param, ALint *value),(param,value)) + + +static void _alGetListeneriv(const ALenum param, ALint *values) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (!values) return; /* legal no-op */ + + switch (param) { + case AL_POSITION: + values[0] = (ALint) ctx->listener.position[0]; + values[1] = (ALint) ctx->listener.position[1]; + values[2] = (ALint) ctx->listener.position[2]; + break; + + case AL_VELOCITY: + values[0] = (ALint) ctx->listener.velocity[0]; + values[1] = (ALint) ctx->listener.velocity[1]; + values[2] = (ALint) ctx->listener.velocity[2]; + break; + + case AL_ORIENTATION: + values[0] = (ALint) ctx->listener.orientation[0]; + values[1] = (ALint) ctx->listener.orientation[1]; + values[2] = (ALint) ctx->listener.orientation[2]; + values[3] = (ALint) ctx->listener.orientation[4]; + values[4] = (ALint) ctx->listener.orientation[5]; + values[5] = (ALint) ctx->listener.orientation[6]; + break; + + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetListeneriv,(ALenum param, ALint *values),(param,values)) + +static void _alGetListener3i(const ALenum param, ALint *value1, ALint *value2, ALint *value3) +{ + ALint values[3]; + switch (param) { + case AL_POSITION: + case AL_VELOCITY: + _alGetListeneriv(param, values); + if (value1) *value1 = values[0]; + if (value2) *value2 = values[1]; + if (value3) *value3 = values[2]; + break; + + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetListener3i,(ALenum param, ALint *value1, ALint *value2, ALint *value3),(param,value1,value2,value3)) + +/* !!! FIXME: buffers and sources use almost identical code for blocks */ +static void _alGenSources(const ALsizei n, ALuint *names) +{ + ALCcontext *ctx = get_current_context(); + ALboolean out_of_memory = AL_FALSE; + ALsizei totalblocks; + ALsource *stackobjs[16]; + ALsource **objects = stackobjs; + ALsizei found = 0; + ALsizei block_offset = 0; + ALsizei blocki; + ALsizei i; + + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (n <= SDL_arraysize(stackobjs)) { + SDL_memset(stackobjs, '\0', sizeof (ALsource *) * n); + } else { + objects = (ALsource **) SDL_calloc(n, sizeof (ALsource *)); + if (!objects) { + set_al_error(ctx, AL_OUT_OF_MEMORY); + return; + } + } + + totalblocks = ctx->num_source_blocks; + for (blocki = 0; blocki < totalblocks; blocki++) { + SourceBlock *block = ctx->source_blocks[blocki]; + block->tmp = 0; + if (block->used < SDL_arraysize(block->sources)) { /* skip if full */ + for (i = 0; i < SDL_arraysize(block->sources); i++) { + /* if a playing source was deleted, it will still be marked mixer_accessible + until the mixer thread shuffles it out. Until then, the source isn't + available for reuse. */ + if (!block->sources[i].allocated && !SDL_AtomicGet(&block->sources[i].mixer_accessible)) { + block->tmp++; + objects[found] = &block->sources[i]; + names[found++] = (i + block_offset) + 1; /* +1 so it isn't zero. */ + if (found == n) { + break; + } + } + } + + if (found == n) { + break; + } + } + + block_offset += SDL_arraysize(block->sources); + } + + while (found < n) { /* out of blocks? Add new ones. */ + /* ctx->source_blocks is only accessed on the API thread under a mutex, so it's safe to realloc. */ + void *ptr = SDL_realloc(ctx->source_blocks, sizeof (SourceBlock *) * (totalblocks + 1)); + SourceBlock *block; + + if (!ptr) { + out_of_memory = AL_TRUE; + break; + } + ctx->source_blocks = (SourceBlock **) ptr; + + block = (SourceBlock *) calloc_simd_aligned(sizeof (SourceBlock)); + if (!block) { + out_of_memory = AL_TRUE; + break; + } + ctx->source_blocks[totalblocks] = block; + totalblocks++; + ctx->num_source_blocks++; + + for (i = 0; i < SDL_arraysize(block->sources); i++) { + block->tmp++; + objects[found] = &block->sources[i]; + names[found++] = (i + block_offset) + 1; /* +1 so it isn't zero. */ + if (found == n) { + break; + } + } + block_offset += SDL_arraysize(block->sources); + } + + if (out_of_memory) { + if (objects != stackobjs) SDL_free(objects); + SDL_memset(names, '\0', sizeof (*names) * n); + set_al_error(ctx, AL_OUT_OF_MEMORY); + return; + } + + SDL_assert(found == n); /* we should have either gotten space or bailed on alloc failure */ + + /* update the "used" field in blocks with items we are taking now. */ + found = 0; + for (blocki = 0; found < n; blocki++) { + SourceBlock *block = ctx->source_blocks[blocki]; + SDL_assert(blocki < totalblocks); + const int foundhere = block->tmp; + if (foundhere) { + block->used += foundhere; + found += foundhere; + block->tmp = 0; + } + } + + SDL_assert(found == n); + + for (i = 0; i < n; i++) { + ALsource *src = objects[i]; + + /*printf("Generated source %u\n", (unsigned int) names[i]);*/ + + SDL_assert(!src->allocated); + + /* Make sure everything that wants to use SIMD is aligned for it. */ + SDL_assert( (((size_t) &src->position[0]) % 16) == 0 ); + SDL_assert( (((size_t) &src->velocity[0]) % 16) == 0 ); + SDL_assert( (((size_t) &src->direction[0]) % 16) == 0 ); + + SDL_zerop(src); + SDL_AtomicSet(&src->state, AL_INITIAL); + src->name = names[i]; + src->type = AL_UNDETERMINED; + src->recalc = AL_TRUE; + src->gain = 1.0f; + src->max_gain = 1.0f; + src->reference_distance = 1.0f; + src->max_distance = FLT_MAX; + src->rolloff_factor = 1.0f; + src->pitch = 1.0f; + src->cone_inner_angle = 360.0f; + src->cone_outer_angle = 360.0f; + source_needs_recalc(src); + src->allocated = AL_TRUE; /* we officially own it. */ + } + + if (objects != stackobjs) SDL_free(objects); +} +ENTRYPOINTVOID(alGenSources,(ALsizei n, ALuint *names),(n,names)) + + +static void _alDeleteSources(const ALsizei n, const ALuint *names) +{ + ALCcontext *ctx = get_current_context(); + ALsizei i; + + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + for (i = 0; i < n; i++) { + const ALuint name = names[i]; + if (name == 0) { + /* ignore it. */ FIXME("Spec says alDeleteBuffers() can have a zero name as a legal no-op, but this text isn't included in alDeleteSources..."); + } else { + ALsource *source = get_source(ctx, name, NULL); + if (!source) { + /* "If one or more of the specified names is not valid, an AL_INVALID_NAME error will be recorded, and no objects will be deleted." */ + set_al_error(ctx, AL_INVALID_NAME); + return; + } + } + } + + for (i = 0; i < n; i++) { + const ALuint name = names[i]; + if (name != 0) { + SourceBlock *block; + ALsource *source = get_source(ctx, name, &block); + SDL_assert(source != NULL); + + /* "A playing source can be deleted--the source will be stopped automatically and then deleted." */ + if (!SDL_AtomicGet(&source->mixer_accessible)) { + SDL_AtomicSet(&source->state, AL_STOPPED); + } else { + SDL_LockMutex(ctx->source_lock); + SDL_AtomicSet(&source->state, AL_STOPPED); /* mixer will drop from playlist next time it sees this. */ + SDL_UnlockMutex(ctx->source_lock); + } + source->allocated = AL_FALSE; + source_release_buffer_queue(ctx, source); + if (source->buffer) { + SDL_assert(source->type == AL_STATIC); + (void) SDL_AtomicDecRef(&source->buffer->refcount); + source->buffer = NULL; + } + if (source->stream) { + SDL_FreeAudioStream(source->stream); + source->stream = NULL; + } + block->used--; + } + } +} +ENTRYPOINTVOID(alDeleteSources,(ALsizei n, const ALuint *names),(n,names)) + +static ALboolean _alIsSource(const ALuint name) +{ + ALCcontext *ctx = get_current_context(); + return (ctx && (get_source(ctx, name, NULL) != NULL)) ? AL_TRUE : AL_FALSE; +} +ENTRYPOINT(ALboolean,alIsSource,(ALuint name),(name)) + +static void _alSourcefv(const ALuint name, const ALenum param, const ALfloat *values) +{ + ALCcontext *ctx = get_current_context(); + ALsource *src = get_source(ctx, name, NULL); + if (!src) return; + + switch (param) { + case AL_GAIN: src->gain = *values; break; + case AL_POSITION: SDL_memcpy(src->position, values, sizeof (ALfloat) * 3); break; + case AL_VELOCITY: SDL_memcpy(src->velocity, values, sizeof (ALfloat) * 3); break; + case AL_DIRECTION: SDL_memcpy(src->direction, values, sizeof (ALfloat) * 3); break; + case AL_MIN_GAIN: src->min_gain = *values; break; + case AL_MAX_GAIN: src->max_gain = *values; break; + case AL_REFERENCE_DISTANCE: src->reference_distance = *values; break; + case AL_ROLLOFF_FACTOR: src->rolloff_factor = *values; break; + case AL_MAX_DISTANCE: src->max_distance = *values; break; + case AL_PITCH: src->pitch = *values; break; + case AL_CONE_INNER_ANGLE: src->cone_inner_angle = *values; break; + case AL_CONE_OUTER_ANGLE: src->cone_outer_angle = *values; break; + case AL_CONE_OUTER_GAIN: src->cone_outer_gain = *values; break; + + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + source_set_offset(src, param, *values); + break; + + default: set_al_error(ctx, AL_INVALID_ENUM); return; + + } + + source_needs_recalc(src); +} +ENTRYPOINTVOID(alSourcefv,(ALuint name, ALenum param, const ALfloat *values),(name,param,values)) + +static void _alSourcef(const ALuint name, const ALenum param, const ALfloat value) +{ + switch (param) { + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_MAX_DISTANCE: + case AL_PITCH: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + _alSourcefv(name, param, &value); + break; + + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alSourcef,(ALuint name, ALenum param, ALfloat value),(name,param,value)) + +static void _alSource3f(const ALuint name, const ALenum param, const ALfloat value1, const ALfloat value2, const ALfloat value3) +{ + switch (param) { + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: { + const ALfloat values[3] = { value1, value2, value3 }; + _alSourcefv(name, param, values); + break; + } + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alSource3f,(ALuint name, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3),(name,param,value1,value2,value3)) + +static void set_source_static_buffer(ALCcontext *ctx, ALsource *src, const ALuint bufname) +{ + const ALenum state = (const ALenum) SDL_AtomicGet(&src->state); + if ((state == AL_PLAYING) || (state == AL_PAUSED)) { + set_al_error(ctx, AL_INVALID_OPERATION); /* can't change buffer on playing/paused sources */ + } else { + ALbuffer *buffer = NULL; + if (bufname && ((buffer = get_buffer(ctx, bufname, NULL)) == NULL)) { + set_al_error(ctx, AL_INVALID_VALUE); + } else { + const ALboolean must_lock = SDL_AtomicGet(&src->mixer_accessible) ? AL_TRUE : AL_FALSE; + SDL_AudioStream *stream = NULL; + SDL_AudioStream *freestream = NULL; + /* We only use the stream for resampling, not for channel conversion. */ + FIXME("keep the existing stream if formats match?"); + if (buffer && (ctx->device->frequency != buffer->frequency)) { + stream = SDL_NewAudioStream(AUDIO_F32SYS, buffer->channels, buffer->frequency, AUDIO_F32SYS, buffer->channels, ctx->device->frequency); + if (!stream) { + set_al_error(ctx, AL_OUT_OF_MEMORY); + return; + } + FIXME("need a way to prealloc space in the stream, so the mixer doesn't have to malloc"); + } + + /* this can happen if you alSource(AL_BUFFER) while the exact source is in the middle of mixing */ + FIXME("Double-check this lock; we shouldn't be able to reach this if the source is playing."); + if (must_lock) { + SDL_LockMutex(ctx->source_lock); + } + + if (src->buffer != buffer) { + if (src->buffer) { + (void) SDL_AtomicDecRef(&src->buffer->refcount); + } + if (buffer) { + SDL_AtomicIncRef(&buffer->refcount); + } + src->buffer = buffer; + } + + src->type = buffer ? AL_STATIC : AL_UNDETERMINED; + src->queue_channels = buffer ? buffer->channels : 0; + src->queue_frequency = 0; + + source_release_buffer_queue(ctx, src); + + if (src->stream != stream) { + freestream = src->stream; /* free this after unlocking. */ + src->stream = stream; + } + + if (must_lock) { + SDL_UnlockMutex(ctx->source_lock); + } + + if (freestream) { + SDL_FreeAudioStream(freestream); + } + } + } +} + +static void _alSourceiv(const ALuint name, const ALenum param, const ALint *values) +{ + ALCcontext *ctx = get_current_context(); + ALsource *src = get_source(ctx, name, NULL); + if (!src) return; + + switch (param) { + case AL_BUFFER: set_source_static_buffer(ctx, src, (ALuint) *values); break; + case AL_SOURCE_RELATIVE: src->source_relative = *values ? AL_TRUE : AL_FALSE; break; + case AL_LOOPING: src->looping = *values ? AL_TRUE : AL_FALSE; break; + case AL_REFERENCE_DISTANCE: src->reference_distance = (ALfloat) *values; break; + case AL_ROLLOFF_FACTOR: src->rolloff_factor = (ALfloat) *values; break; + case AL_MAX_DISTANCE: src->max_distance = (ALfloat) *values; break; + case AL_CONE_INNER_ANGLE: src->cone_inner_angle = (ALfloat) *values; break; + case AL_CONE_OUTER_ANGLE: src->cone_outer_angle = (ALfloat) *values; break; + + case AL_DIRECTION: + src->direction[0] = (ALfloat) values[0]; + src->direction[1] = (ALfloat) values[1]; + src->direction[2] = (ALfloat) values[2]; + break; + + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + source_set_offset(src, param, (ALfloat)*values); + break; + + default: set_al_error(ctx, AL_INVALID_ENUM); return; + } + + source_needs_recalc(src); +} +ENTRYPOINTVOID(alSourceiv,(ALuint name, ALenum param, const ALint *values),(name,param,values)) + +static void _alSourcei(const ALuint name, const ALenum param, const ALint value) +{ + switch (param) { + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_BUFFER: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_MAX_DISTANCE: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + _alSourceiv(name, param, &value); + break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alSourcei,(ALuint name, ALenum param, ALint value),(name,param,value)) + +static void _alSource3i(const ALuint name, const ALenum param, const ALint value1, const ALint value2, const ALint value3) +{ + switch (param) { + case AL_DIRECTION: { + const ALint values[3] = { (ALint) value1, (ALint) value2, (ALint) value3 }; + _alSourceiv(name, param, values); + break; + } + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alSource3i,(ALuint name, ALenum param, ALint value1, ALint value2, ALint value3),(name,param,value1,value2,value3)) + +static void _alGetSourcefv(const ALuint name, const ALenum param, ALfloat *values) +{ + ALCcontext *ctx = get_current_context(); + ALsource *src = get_source(ctx, name, NULL); + if (!src) return; + + switch (param) { + case AL_GAIN: *values = src->gain; break; + case AL_POSITION: SDL_memcpy(values, src->position, sizeof (ALfloat) * 3); break; + case AL_VELOCITY: SDL_memcpy(values, src->velocity, sizeof (ALfloat) * 3); break; + case AL_DIRECTION: SDL_memcpy(values, src->direction, sizeof (ALfloat) * 3); break; + case AL_MIN_GAIN: *values = src->min_gain; break; + case AL_MAX_GAIN: *values = src->max_gain; break; + case AL_REFERENCE_DISTANCE: *values = src->reference_distance; break; + case AL_ROLLOFF_FACTOR: *values = src->rolloff_factor; break; + case AL_MAX_DISTANCE: *values = src->max_distance; break; + case AL_PITCH: *values = src->pitch; break; + case AL_CONE_INNER_ANGLE: *values = src->cone_inner_angle; break; + case AL_CONE_OUTER_ANGLE: *values = src->cone_outer_angle; break; + case AL_CONE_OUTER_GAIN: *values = src->cone_outer_gain; break; + + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + *values = source_get_offset(src, param); + break; + + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetSourcefv,(ALuint name, ALenum param, ALfloat *values),(name,param,values)) + +static void _alGetSourcef(const ALuint name, const ALenum param, ALfloat *value) +{ + switch (param) { + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_MAX_DISTANCE: + case AL_PITCH: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + _alGetSourcefv(name, param, value); + break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetSourcef,(ALuint name, ALenum param, ALfloat *value),(name,param,value)) + +static void _alGetSource3f(const ALuint name, const ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) +{ + switch (param) { + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: { + ALfloat values[3]; + _alGetSourcefv(name, param, values); + if (value1) *value1 = values[0]; + if (value2) *value2 = values[1]; + if (value3) *value3 = values[2]; + break; + } + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetSource3f,(ALuint name, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3),(name,param,value1,value2,value3)) + +static void _alGetSourceiv(const ALuint name, const ALenum param, ALint *values) +{ + ALCcontext *ctx = get_current_context(); + ALsource *src = get_source(ctx, name, NULL); + if (!src) return; + + switch (param) { + case AL_SOURCE_STATE: *values = (ALint) SDL_AtomicGet(&src->state); break; + case AL_SOURCE_TYPE: *values = (ALint) src->type; break; + case AL_BUFFER: *values = (ALint) (src->buffer ? src->buffer->name : 0); break; + /* !!! FIXME: AL_BUFFERS_QUEUED is the total number of buffers pending, playing, and processed, so this is wrong. It might also have to be 1 if there's a static buffer, but I'm not sure. */ + case AL_BUFFERS_QUEUED: *values = (ALint) SDL_AtomicGet(&src->buffer_queue.num_items); break; + case AL_BUFFERS_PROCESSED: *values = (ALint) SDL_AtomicGet(&src->buffer_queue_processed.num_items); break; + case AL_SOURCE_RELATIVE: *values = (ALint) src->source_relative; break; + case AL_LOOPING: *values = (ALint) src->looping; break; + case AL_REFERENCE_DISTANCE: *values = (ALint) src->reference_distance; break; + case AL_ROLLOFF_FACTOR: *values = (ALint) src->rolloff_factor; break; + case AL_MAX_DISTANCE: *values = (ALint) src->max_distance; break; + case AL_CONE_INNER_ANGLE: *values = (ALint) src->cone_inner_angle; break; + case AL_CONE_OUTER_ANGLE: *values = (ALint) src->cone_outer_angle; break; + case AL_DIRECTION: + values[0] = (ALint) src->direction[0]; + values[1] = (ALint) src->direction[1]; + values[2] = (ALint) src->direction[2]; + break; + + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + *values = (ALint) source_get_offset(src, param); + break; + + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetSourceiv,(ALuint name, ALenum param, ALint *values),(name,param,values)) + +static void _alGetSourcei(const ALuint name, const ALenum param, ALint *value) +{ + switch (param) { + case AL_SOURCE_STATE: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_BUFFER: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_MAX_DISTANCE: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + _alGetSourceiv(name, param, value); + break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetSourcei,(ALuint name, ALenum param, ALint *value),(name,param,value)) + +static void _alGetSource3i(const ALuint name, const ALenum param, ALint *value1, ALint *value2, ALint *value3) +{ + switch (param) { + case AL_DIRECTION: { + ALint values[3]; + _alGetSourceiv(name, param, values); + if (value1) *value1 = values[0]; + if (value2) *value2 = values[1]; + if (value3) *value3 = values[2]; + break; + } + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetSource3i,(ALuint name, ALenum param, ALint *value1, ALint *value2, ALint *value3),(name,param,value1,value2,value3)) + +static void source_play(ALCcontext *ctx, const ALsizei n, const ALuint *names) +{ + ALboolean failed = AL_FALSE; + SourcePlayTodo todo; + SourcePlayTodo *todoend = &todo; + SourcePlayTodo *todoptr; + void *ptr; + ALsizei i; + + if (n == 0) { + return; + } else if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + SDL_zero(todo); + + /* Obtain our SourcePlayTodo items upfront; if this runs out of + memory, we won't have changed any state. The mixer thread will + put items back in the pool when done with them, so this handoff needs + to be atomic. */ + for (i = 0; i < n; i++) { + SourcePlayTodo *item; + do { + ptr = SDL_AtomicGetPtr(&ctx->device->playback.source_todo_pool); + item = (SourcePlayTodo *) ptr; + if (!item) break; + ptr = item->next; + } while (!SDL_AtomicCASPtr(&ctx->device->playback.source_todo_pool, item, ptr)); + + if (!item) { /* allocate a new item */ + item = (SourcePlayTodo *) SDL_calloc(1, sizeof (SourcePlayTodo)); + if (!item) { + set_al_error(ctx, AL_OUT_OF_MEMORY); + failed = AL_TRUE; + break; + } + } + + item->next = NULL; + todoend->next = item; + todoend = item; + } + + if (failed) { + /* put the whole new queue back in the pool for reuse later. */ + if (todo.next) { + do { + ptr = SDL_AtomicGetPtr(&ctx->device->playback.source_todo_pool); + todoend->next = (SourcePlayTodo *) ptr; + } while (!SDL_AtomicCASPtr(&ctx->device->playback.source_todo_pool, ptr, todo.next)); + } + return; + } + + FIXME("What do we do if there's an invalid source in the middle of the names vector?"); + for (i = 0, todoptr = todo.next; i < n; i++) { + const ALuint name = names[i]; + ALsource *src = get_source(ctx, name, NULL); + if (src) { + if (src->offset_latched) { + src->offset_latched = AL_FALSE; + } else if (SDL_AtomicGet(&src->state) != AL_PAUSED) { + src->offset = 0; + } + + /* this used to move right to AL_STOPPED if the device is + disconnected, but now we let the mixer thread handle that to + avoid race conditions with marking the buffer queue + processed, etc. Strictly speaking, ALC_EXT_disconnect + says playing a source on a disconnected device should + "immediately" progress to STOPPED, but I'm willing to + say that the mixer will "immediately" move it as opposed to + it stopping when the source would be done mixing (or worse: + hang there forever). */ + SDL_AtomicSet(&src->state, AL_PLAYING); + + /* Mark this as visible to the mixer. This will be set back to zero by the mixer thread when it is done with the source. */ + SDL_AtomicSet(&src->mixer_accessible, 1); + + todoptr->source = src; + todoptr = todoptr->next; + } + } + + /* Send the list to the mixer atomically, so all sources start playing in sync! + We're going to put these on a linked list called playlist_todo + The mixer does an atomiccasptr to grab the current list, swapping + in a NULL. Once it has the list, it's safe to do what it likes + with it, as nothing else owns the pointers in that list. */ + do { + ptr = SDL_AtomicGetPtr(&ctx->playlist_todo); + todoend->next = ptr; + } while (!SDL_AtomicCASPtr(&ctx->playlist_todo, ptr, todo.next)); +} + +static void _alSourcePlay(const ALuint name) +{ + source_play(get_current_context(), 1, &name); +} +ENTRYPOINTVOID(alSourcePlay,(ALuint name),(name)) + +static void _alSourcePlayv(ALsizei n, const ALuint *names) +{ + source_play(get_current_context(), n, names); +} +ENTRYPOINTVOID(alSourcePlayv,(ALsizei n, const ALuint *names),(n, names)) + + +static void source_stop(ALCcontext *ctx, const ALuint name) +{ + ALsource *src = get_source(ctx, name, NULL); + if (src) { + if (SDL_AtomicGet(&src->state) != AL_INITIAL) { + const ALboolean must_lock = SDL_AtomicGet(&src->mixer_accessible) ? AL_TRUE : AL_FALSE; + if (must_lock) { + SDL_LockMutex(ctx->source_lock); + } + SDL_AtomicSet(&src->state, AL_STOPPED); + source_mark_all_buffers_processed(src); + if (must_lock) { + SDL_UnlockMutex(ctx->source_lock); + } + } + } +} + +static void source_rewind(ALCcontext *ctx, const ALuint name) +{ + ALsource *src = get_source(ctx, name, NULL); + if (src) { + const ALboolean must_lock = SDL_AtomicGet(&src->mixer_accessible) ? AL_TRUE : AL_FALSE; + if (must_lock) { + SDL_LockMutex(ctx->source_lock); + } + SDL_AtomicSet(&src->state, AL_INITIAL); + src->offset = 0; + if (must_lock) { + SDL_UnlockMutex(ctx->source_lock); + } + } +} + +static void source_pause(ALCcontext *ctx, const ALuint name) +{ + ALsource *src = get_source(ctx, name, NULL); + if (src) { + SDL_AtomicCAS(&src->state, AL_PLAYING, AL_PAUSED); + } +} + +static int source_get_offset(ALsource *src, ALenum param) +{ + int offset = 0; + int framesize = sizeof(float); + int freq = 1; + if (src->type == AL_STREAMING) { + /* streaming: the offset counts from the first processed buffer in the queue. */ + BufferQueueItem *item = src->buffer_queue.head; + if (item) { + framesize = (int)(item->buffer->channels * sizeof(float)); + freq = (int)(item->buffer->frequency); + int proc_buf = SDL_AtomicGet(&src->buffer_queue_processed.num_items); + offset = (proc_buf * item->buffer->len + src->offset); + } + } else { + framesize = (int)(src->buffer->channels * sizeof(float)); + freq = (int)src->buffer->frequency; + offset = src->offset; + } + switch(param) { + case AL_SAMPLE_OFFSET: return offset / framesize; break; + case AL_SEC_OFFSET: return (offset / framesize) / freq; break; + case AL_BYTE_OFFSET: return offset; break; + default: return 0; break; + } +} + +static void source_set_offset(ALsource *src, ALenum param, ALfloat value) +{ + ALCcontext *ctx = get_current_context(); + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + int bufflen = 0; + int framesize = sizeof(float); + int freq = 1; + + if (src->type == AL_STREAMING) { + FIXME("set_offset for streaming sources not implemented"); + return; + } else { + bufflen = (int)src->buffer->len; + framesize = (int)(src->buffer->channels * sizeof(float)); + freq = (int)src->buffer->frequency; + } + + int offset = -1; + switch(param) { + case AL_SAMPLE_OFFSET: + offset = value * framesize; + break; + case AL_SEC_OFFSET: + offset = value * freq * framesize; + break; + case AL_BYTE_OFFSET: + offset = ((int)value / framesize) * framesize; + break; + } + if (offset < 0 || offset > bufflen) { + set_al_error(ctx, AL_INVALID_VALUE); + return; + } + + if (!SDL_AtomicGet(&src->mixer_accessible)) { + src->offset = offset; + } else { + SDL_LockMutex(ctx->source_lock); + src->offset = offset; + SDL_UnlockMutex(ctx->source_lock); + } +} + +/* deal with alSourcePlay and alSourcePlayv (etc) boiler plate... */ +#define SOURCE_STATE_TRANSITION_OP(alfn, fn) \ + void alSource##alfn(ALuint name) { source_##fn(get_current_context(), name); } \ + void alSource##alfn##v(ALsizei n, const ALuint *sources) { \ + ALCcontext *ctx = get_current_context(); \ + if (!ctx) { \ + set_al_error(ctx, AL_INVALID_OPERATION); \ + } else { \ + ALsizei i; \ + if (n > 1) { \ + FIXME("Can we do this without a full device lock?"); \ + SDL_LockAudioDevice(ctx->device->sdldevice); /* lock the SDL device so these all start mixing in the same callback. */ \ + for (i = 0; i < n; i++) { \ + source_##fn(ctx, sources[i]); \ + } \ + SDL_UnlockAudioDevice(ctx->device->sdldevice); \ + } else if (n == 1) { \ + source_##fn(ctx, *sources); \ + } \ + } \ + } + +SOURCE_STATE_TRANSITION_OP(Stop, stop) +SOURCE_STATE_TRANSITION_OP(Rewind, rewind) +SOURCE_STATE_TRANSITION_OP(Pause, pause) + + +static void _alSourceQueueBuffers(const ALuint name, const ALsizei nb, const ALuint *bufnames) +{ + BufferQueueItem *queue = NULL; + BufferQueueItem *queueend = NULL; + void *ptr; + ALsizei i; + ALCcontext *ctx = get_current_context(); + ALsource *src = get_source(ctx, name, NULL); + ALint queue_channels = 0; + ALsizei queue_frequency = 0; + ALboolean failed = AL_FALSE; + SDL_AudioStream *stream = NULL; + + if (!src) { + return; + } + + if (src->type == AL_STATIC) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (nb == 0) { + return; /* nothing to do. */ + } + + for (i = nb; i > 0; i--) { /* build list in reverse */ + BufferQueueItem *item = NULL; + const ALuint bufname = bufnames[i-1]; + ALbuffer *buffer = bufname ? get_buffer(ctx, bufname, NULL) : NULL; + if (!buffer && bufname) { /* uhoh, bad buffer name! */ + set_al_error(ctx, AL_INVALID_VALUE); + failed = AL_TRUE; + break; + } + + if (buffer) { + if (queue_channels == 0) { + SDL_assert(queue_frequency == 0); + queue_channels = buffer->channels; + queue_frequency = buffer->frequency; + } else if ((queue_channels != buffer->channels) || (queue_frequency != buffer->frequency)) { + /* the whole queue must be the same format. */ + set_al_error(ctx, AL_INVALID_VALUE); + failed = AL_TRUE; + break; + } + } + + item = ctx->device->playback.buffer_queue_pool; + if (item) { + ctx->device->playback.buffer_queue_pool = item->next; + } else { /* allocate a new item */ + item = (BufferQueueItem *) SDL_calloc(1, sizeof (BufferQueueItem)); + if (!item) { + set_al_error(ctx, AL_OUT_OF_MEMORY); + failed = AL_TRUE; + break; + } + } + + if (buffer) { + SDL_AtomicIncRef(&buffer->refcount); /* mark it as in-use. */ + } + item->buffer = buffer; + + SDL_assert((queue != NULL) == (queueend != NULL)); + if (queueend) { + queueend->next = item; + } else { + queue = item; + } + queueend = item; + } + + if (!failed) { + if (src->queue_frequency && queue_frequency) { /* could be zero if we only queued AL name 0. */ + SDL_assert(src->queue_channels); + SDL_assert(queue_channels); + if ((src->queue_channels != queue_channels) || (src->queue_frequency != queue_frequency)) { + set_al_error(ctx, AL_INVALID_VALUE); + failed = AL_TRUE; + } + } + } + + if (!src->queue_frequency) { + SDL_assert(!src->queue_channels); + SDL_assert(!src->stream); + /* We only use the stream for resampling, not for channel conversion. */ + if (ctx->device->frequency != queue_frequency) { + stream = SDL_NewAudioStream(AUDIO_F32SYS, queue_channels, queue_frequency, AUDIO_F32SYS, queue_channels, ctx->device->frequency); + if (!stream) { + set_al_error(ctx, AL_OUT_OF_MEMORY); + failed = AL_TRUE; + } + FIXME("need a way to prealloc space in the stream, so the mixer doesn't have to malloc"); + } + } + + if (failed) { + if (queue) { + /* Drop our claim on any buffers we planned to queue. */ + BufferQueueItem *item; + for (item = queue; item != NULL; item = item->next) { + if (item->buffer) { + (void) SDL_AtomicDecRef(&item->buffer->refcount); + } + } + + /* put the whole new queue back in the pool for reuse later. */ + queueend->next = ctx->device->playback.buffer_queue_pool; + ctx->device->playback.buffer_queue_pool = queue; + } + if (stream) { + SDL_FreeAudioStream(stream); + } + return; + } + + FIXME("this needs to be set way sooner"); + + FIXME("this used to have a source lock, think this one through"); + src->type = AL_STREAMING; + + if (!src->queue_channels) { + src->queue_channels = queue_channels; + src->queue_frequency = queue_frequency; + src->stream = stream; + } + + /* so we're going to put these on a linked list called just_queued, + where things build up in reverse order, to keep this on a single + pointer. The theory is we'll atomicgetptr the pointer, set that + pointer as the "next" for our list, and then atomiccasptr our new + list against the original pointer. If the CAS succeeds, we have + a complete list, atomically set. If it fails, try again with + the new pointer we found, updating our next pointer again. If it + failed, it's because the pointer became NULL when the mixer thread + grabbed the existing list. + + The mixer does an atomiccasptr to grab the current list, swapping + in a NULL. Once it has the list, it's safe to do what it likes + with it, as nothing else owns the pointers in that list. */ + + do { + ptr = SDL_AtomicGetPtr(&src->buffer_queue.just_queued); + SDL_AtomicSetPtr(&queueend->next, ptr); + } while (!SDL_AtomicCASPtr(&src->buffer_queue.just_queued, ptr, queue)); + + SDL_AtomicAdd(&src->buffer_queue.num_items, (int) nb); +} +ENTRYPOINTVOID(alSourceQueueBuffers,(ALuint name, ALsizei nb, const ALuint *bufnames),(name,nb,bufnames)) + +static void _alSourceUnqueueBuffers(const ALuint name, const ALsizei nb, ALuint *bufnames) +{ + BufferQueueItem *queueend = NULL; + BufferQueueItem *queue; + BufferQueueItem *item; + ALsizei i; + ALCcontext *ctx = get_current_context(); + ALsource *src = get_source(ctx, name, NULL); + if (!src) { + return; + } + + if (src->type == AL_STATIC) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (nb == 0) { + return; /* nothing to do. */ + } + + if (((ALsizei) SDL_AtomicGet(&src->buffer_queue_processed.num_items)) < nb) { + set_al_error(ctx, AL_INVALID_VALUE); + return; + } + + SDL_AtomicAdd(&src->buffer_queue_processed.num_items, -((int) nb)); + + obtain_newly_queued_buffers(&src->buffer_queue_processed); + + item = queue = src->buffer_queue_processed.head; + for (i = 0; i < nb; i++) { + /* buffer_queue_processed.num_items said list was long enough. */ + SDL_assert(item != NULL); + item = item->next; + } + src->buffer_queue_processed.head = item; + if (!item) { + src->buffer_queue_processed.tail = NULL; + } + + item = queue; + for (i = 0; i < nb; i++) { + if (item->buffer) { + (void) SDL_AtomicDecRef(&item->buffer->refcount); + } + bufnames[i] = item->buffer ? item->buffer->name : 0; + queueend = item; + item = item->next; + } + + /* put the whole new queue back in the pool for reuse later. */ + SDL_assert(queueend != NULL); + queueend->next = ctx->device->playback.buffer_queue_pool; + ctx->device->playback.buffer_queue_pool = queue; +} +ENTRYPOINTVOID(alSourceUnqueueBuffers,(ALuint name, ALsizei nb, ALuint *bufnames),(name,nb,bufnames)) + +/* !!! FIXME: buffers and sources use almost identical code for blocks */ +static void _alGenBuffers(const ALsizei n, ALuint *names) +{ + ALCcontext *ctx = get_current_context(); + ALboolean out_of_memory = AL_FALSE; + ALsizei totalblocks; + ALbuffer *stackobjs[16]; + ALbuffer **objects = stackobjs; + ALsizei found = 0; + ALsizei block_offset = 0; + ALsizei blocki; + ALsizei i; + + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + if (n <= SDL_arraysize(stackobjs)) { + SDL_memset(stackobjs, '\0', sizeof (ALbuffer *) * n); + } else { + objects = (ALbuffer **) SDL_calloc(n, sizeof (ALbuffer *)); + if (!objects) { + set_al_error(ctx, AL_OUT_OF_MEMORY); + return; + } + } + + totalblocks = ctx->device->playback.num_buffer_blocks; + for (blocki = 0; blocki < totalblocks; blocki++) { + BufferBlock *block = ctx->device->playback.buffer_blocks[blocki]; + block->tmp = 0; + if (block->used < SDL_arraysize(block->buffers)) { /* skip if full */ + for (i = 0; i < SDL_arraysize(block->buffers); i++) { + if (!block->buffers[i].allocated) { + block->tmp++; + objects[found] = &block->buffers[i]; + names[found++] = (i + block_offset) + 1; /* +1 so it isn't zero. */ + if (found == n) { + break; + } + } + } + + if (found == n) { + break; + } + } + + block_offset += SDL_arraysize(block->buffers); + } + + while (found < n) { /* out of blocks? Add new ones. */ + /* ctx->buffer_blocks is only accessed on the API thread under a mutex, so it's safe to realloc. */ + void *ptr = SDL_realloc(ctx->device->playback.buffer_blocks, sizeof (BufferBlock *) * (totalblocks + 1)); + BufferBlock *block; + + if (!ptr) { + out_of_memory = AL_TRUE; + break; + } + ctx->device->playback.buffer_blocks = (BufferBlock **) ptr; + + block = (BufferBlock *) SDL_calloc(1, sizeof (BufferBlock)); + if (!block) { + out_of_memory = AL_TRUE; + break; + } + ctx->device->playback.buffer_blocks[totalblocks] = block; + totalblocks++; + ctx->device->playback.num_buffer_blocks++; + + for (i = 0; i < SDL_arraysize(block->buffers); i++) { + block->tmp++; + objects[found] = &block->buffers[i]; + names[found++] = (i + block_offset) + 1; /* +1 so it isn't zero. */ + if (found == n) { + break; + } + } + block_offset += SDL_arraysize(block->buffers); + } + + if (out_of_memory) { + if (objects != stackobjs) SDL_free(objects); + SDL_memset(names, '\0', sizeof (*names) * n); + set_al_error(ctx, AL_OUT_OF_MEMORY); + return; + } + + SDL_assert(found == n); /* we should have either gotten space or bailed on alloc failure */ + + /* update the "used" field in blocks with items we are taking now. */ + found = 0; + for (blocki = 0; found < n; blocki++) { + BufferBlock *block = ctx->device->playback.buffer_blocks[blocki]; + SDL_assert(blocki < totalblocks); + const int foundhere = block->tmp; + if (foundhere) { + block->used += foundhere; + found += foundhere; + block->tmp = 0; + } + } + + SDL_assert(found == n); + + for (i = 0; i < n; i++) { + ALbuffer *buffer = objects[i]; + /*printf("Generated buffer %u\n", (unsigned int) names[i]);*/ + SDL_assert(!buffer->allocated); + SDL_zerop(buffer); + buffer->name = names[i]; + buffer->channels = 1; + buffer->bits = 16; + buffer->allocated = AL_TRUE; /* we officially own it. */ + } + + if (objects != stackobjs) SDL_free(objects); +} +ENTRYPOINTVOID(alGenBuffers,(ALsizei n, ALuint *names),(n,names)) + +static void _alDeleteBuffers(const ALsizei n, const ALuint *names) +{ + ALCcontext *ctx = get_current_context(); + ALsizei i; + + if (!ctx) { + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + for (i = 0; i < n; i++) { + const ALuint name = names[i]; + if (name == 0) { + /* ignore it. */ + } else { + ALbuffer *buffer = get_buffer(ctx, name, NULL); + if (!buffer) { + /* "If one or more of the specified names is not valid, an AL_INVALID_NAME error will be recorded, and no objects will be deleted." */ + set_al_error(ctx, AL_INVALID_NAME); + return; + } else if (SDL_AtomicGet(&buffer->refcount) != 0) { + set_al_error(ctx, AL_INVALID_OPERATION); /* still in use */ + return; + } + } + } + + for (i = 0; i < n; i++) { + const ALuint name = names[i]; + if (name != 0) { + BufferBlock *block; + ALbuffer *buffer = get_buffer(ctx, name, &block); + void *data; + SDL_assert(buffer != NULL); + data = (void *) buffer->data; + buffer->allocated = AL_FALSE; + buffer->data = NULL; + free_simd_aligned(data); + block->used--; + } + } +} +ENTRYPOINTVOID(alDeleteBuffers,(ALsizei n, const ALuint *names),(n,names)) + +static ALboolean _alIsBuffer(ALuint name) +{ + ALCcontext *ctx = get_current_context(); + return (ctx && (get_buffer(ctx, name, NULL) != NULL)) ? AL_TRUE : AL_FALSE; +} +ENTRYPOINT(ALboolean,alIsBuffer,(ALuint name),(name)) + +static void _alBufferData(const ALuint name, const ALenum alfmt, const ALvoid *data, const ALsizei size, const ALsizei freq) +{ + ALCcontext *ctx = get_current_context(); + ALbuffer *buffer = get_buffer(ctx, name, NULL); + SDL_AudioCVT sdlcvt; + Uint8 channels; + SDL_AudioFormat sdlfmt; + ALCsizei framesize; + int rc; + int prevrefcount; + + if (!buffer) return; + + if (!alcfmt_to_sdlfmt(alfmt, &sdlfmt, &channels, &framesize)) { + set_al_error(ctx, AL_INVALID_VALUE); + return; + } + + /* increment refcount so this can't be deleted or alBufferData'd from another thread */ + prevrefcount = SDL_AtomicIncRef(&buffer->refcount); + SDL_assert(prevrefcount >= 0); + if (prevrefcount != 0) { + /* this buffer is being used by some source. Unqueue it first. */ + (void) SDL_AtomicDecRef(&buffer->refcount); + set_al_error(ctx, AL_INVALID_OPERATION); + return; + } + + /* This check was from the wild west of lock-free programming, now we shouldn't pass get_buffer() if not allocated. */ + SDL_assert(buffer->allocated); + + /* right now we take a moment to convert the data to float32, since that's + the format we want to work in, but we don't resample or change the channels */ + SDL_zero(sdlcvt); + rc = SDL_BuildAudioCVT(&sdlcvt, sdlfmt, channels, (int) freq, AUDIO_F32SYS, channels, (int) freq); + if (rc == -1) { + (void) SDL_AtomicDecRef(&buffer->refcount); + set_al_error(ctx, AL_OUT_OF_MEMORY); /* not really, but oh well. */ + return; + } + + sdlcvt.len = sdlcvt.len_cvt = size; + sdlcvt.buf = (Uint8 *) calloc_simd_aligned(size * sdlcvt.len_mult); + if (!sdlcvt.buf) { + (void) SDL_AtomicDecRef(&buffer->refcount); + set_al_error(ctx, AL_OUT_OF_MEMORY); + return; + } + SDL_memcpy(sdlcvt.buf, data, size); + + if (rc == 1) { /* conversion necessary */ + rc = SDL_ConvertAudio(&sdlcvt); + SDL_assert(rc == 0); /* this shouldn't fail. */ + if (sdlcvt.len_cvt < (size * sdlcvt.len_mult)) { /* maybe shrink buffer */ + void *ptr = SDL_realloc(sdlcvt.buf, sdlcvt.len_cvt); + if (ptr) { + sdlcvt.buf = (Uint8 *) ptr; + } + } + } + + free_simd_aligned((void *) buffer->data); /* nuke any previous data. */ + buffer->data = (const float *) sdlcvt.buf; + buffer->channels = (ALint) channels; + buffer->bits = (ALint) SDL_AUDIO_BITSIZE(sdlfmt); /* we're in float32, though. */ + buffer->frequency = freq; + buffer->len = (ALsizei) sdlcvt.len_cvt; + (void) SDL_AtomicDecRef(&buffer->refcount); /* ready to go! */ +} +ENTRYPOINTVOID(alBufferData,(ALuint name, ALenum alfmt, const ALvoid *data, ALsizei size, ALsizei freq),(name,alfmt,data,size,freq)) + +static void _alBufferfv(const ALuint name, const ALenum param, const ALfloat *values) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alBufferfv,(ALuint name, ALenum param, const ALfloat *values),(name,param,values)) + +static void _alBufferf(const ALuint name, const ALenum param, const ALfloat value) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alBufferf,(ALuint name, ALenum param, ALfloat value),(name,param,value)) + +static void _alBuffer3f(const ALuint name, const ALenum param, const ALfloat value1, const ALfloat value2, const ALfloat value3) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alBuffer3f,(ALuint name, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3),(name,param,value1,value2,value3)) + +static void _alBufferiv(const ALuint name, const ALenum param, const ALint *values) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alBufferiv,(ALuint name, ALenum param, const ALint *values),(name,param,values)) + +static void _alBufferi(const ALuint name, const ALenum param, const ALint value) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alBufferi,(ALuint name, ALenum param, ALint value),(name,param,value)) + +static void _alBuffer3i(const ALuint name, const ALenum param, const ALint value1, const ALint value2, const ALint value3) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alBuffer3i,(ALuint name, ALenum param, ALint value1, ALint value2, ALint value3),(name,param,value1,value2,value3)) + +static void _alGetBufferfv(const ALuint name, const ALenum param, const ALfloat *values) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alGetBufferfv,(ALuint name, ALenum param, ALfloat *values),(name,param,values)) + +static void _alGetBufferf(const ALuint name, const ALenum param, ALfloat *value) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alGetBufferf,(ALuint name, ALenum param, ALfloat *value),(name,param,value)) + +static void _alGetBuffer3f(const ALuint name, const ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alGetBuffer3f,(ALuint name, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3),(name,param,value1,value2,value3)) + +static void _alGetBufferi(const ALuint name, const ALenum param, ALint *value) +{ + switch (param) { + case AL_FREQUENCY: + case AL_SIZE: + case AL_BITS: + case AL_CHANNELS: + alGetBufferiv(name, param, value); + break; + default: set_al_error(get_current_context(), AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetBufferi,(ALuint name, ALenum param, ALint *value),(name,param,value)) + +static void _alGetBuffer3i(const ALuint name, const ALenum param, ALint *value1, ALint *value2, ALint *value3) +{ + set_al_error(get_current_context(), AL_INVALID_ENUM); /* nothing in core OpenAL 1.1 uses this */ +} +ENTRYPOINTVOID(alGetBuffer3i,(ALuint name, ALenum param, ALint *value1, ALint *value2, ALint *value3),(name,param,value1,value2,value3)) + +static void _alGetBufferiv(const ALuint name, const ALenum param, ALint *values) +{ + ALCcontext *ctx = get_current_context(); + ALbuffer *buffer = get_buffer(ctx, name, NULL); + if (!buffer) return; + + switch (param) { + case AL_FREQUENCY: *values = (ALint) buffer->frequency; break; + case AL_SIZE: *values = (ALint) buffer->len; break; + case AL_BITS: *values = (ALint) buffer->bits; break; + case AL_CHANNELS: *values = (ALint) buffer->channels; break; + default: set_al_error(ctx, AL_INVALID_ENUM); break; + } +} +ENTRYPOINTVOID(alGetBufferiv,(ALuint name, ALenum param, ALint *values),(name,param,values)) + +/* end of mojoal.c ... */ + From e75b560c6eee7f882abf01beff35e26dc9979880 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Wed, 30 Sep 2020 02:43:54 +0300 Subject: [PATCH 02/41] Imported OpenALDecoder and Audio Core module Based on the work of @sonneveld (Nick Sonneveld); only relevant code, plus tidied up a little. --- Engine/media/audio/audio_core.cpp | 265 +++++++++++++++++++ Engine/media/audio/audio_core.h | 56 +++++ Engine/media/audio/audio_core_defs.h | 32 +++ Engine/media/audio/openal.h | 14 ++ Engine/media/audio/openaldecoder.cpp | 322 ++++++++++++++++++++++++ Engine/media/audio/openaldecoder.h | 77 ++++++ Solutions/Engine.App/Engine.App.vcxproj | 6 + 7 files changed, 772 insertions(+) create mode 100644 Engine/media/audio/audio_core.cpp create mode 100644 Engine/media/audio/audio_core.h create mode 100644 Engine/media/audio/audio_core_defs.h create mode 100644 Engine/media/audio/openal.h create mode 100644 Engine/media/audio/openaldecoder.cpp create mode 100644 Engine/media/audio/openaldecoder.h diff --git a/Engine/media/audio/audio_core.cpp b/Engine/media/audio/audio_core.cpp new file mode 100644 index 00000000000..360537979da --- /dev/null +++ b/Engine/media/audio/audio_core.cpp @@ -0,0 +1,265 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +// [sonneveld] +// TODO: +// sound caching ([IKM] please, not right here in this backend module) +// slot id generation id +// pre-determine music sizes +// safer slot look ups (with gen id) +// generate/load mod/midi offsets + +#include "media/audio/audio_core.h" +#include +#include "debug/out.h" +#include "media/audio/openaldecoder.h" + +namespace ags = AGS::Common; +namespace agsdbg = AGS::Common::Debug; + +const auto GlobalGainScaling = 0.7f; + +static void audio_core_entry(); + +struct AudioCoreSlot +{ + AudioCoreSlot(int handle, ALuint source, OpenALDecoder decoder) : handle_(handle), source_(source), decoder_(std::move(decoder)) {} + + int handle_ = -1; + std::atomic source_ {0}; + + OpenALDecoder decoder_; +}; + + + +static struct +{ + ALCdevice *alcDevice = nullptr; + ALCcontext *alcContext = nullptr; + + std::thread audio_core_thread; + bool audio_core_thread_running = false; + + // slot ids + int nextId = 0; + + // One mutex to lock them all... any operation on individual decoders + // is done under this only mutex, which means that they are currently + // polled one by one, any action like pause/resume is also synced. + std::mutex mixer_mutex_m; + std::condition_variable mixer_cv; + std::unordered_map> slots_; +} g_acore; + + +// ------------------------------------------------------------------------------------------------- +// INIT / SHUTDOWN +// ------------------------------------------------------------------------------------------------- + +void audio_core_init() +{ + /* InitAL opens a device and sets up a context using default attributes, making + * the program ready to call OpenAL functions. */ + + /* Open and initialize a device */ + g_acore.alcDevice = alcOpenDevice(nullptr); + if (!g_acore.alcDevice) { throw std::runtime_error("PlayStateError opening device"); } + + g_acore.alcContext = alcCreateContext(g_acore.alcDevice, nullptr); + if (!g_acore.alcContext) { throw std::runtime_error("PlayStateError creating context"); } + + if (alcMakeContextCurrent(g_acore.alcContext) == ALC_FALSE) { throw std::runtime_error("PlayStateError setting context"); } + + const ALCchar *name = nullptr; + if (alcIsExtensionPresent(g_acore.alcDevice, "ALC_ENUMERATE_ALL_EXT")) + name = alcGetString(g_acore.alcDevice, ALC_ALL_DEVICES_SPECIFIER); + if (!name || alcGetError(g_acore.alcDevice) != AL_NO_ERROR) + name = alcGetString(g_acore.alcDevice, ALC_DEVICE_SPECIFIER); + printf("Opened \"%s\"\n", name); + + // SDL_Sound + Sound_Init(); + + g_acore.audio_core_thread_running = true; + g_acore.audio_core_thread = std::thread(audio_core_entry); +} + +void audio_core_shutdown() +{ + g_acore.audio_core_thread_running = false; + g_acore.audio_core_thread.join(); + + // SDL_Sound + Sound_Quit(); + + alcMakeContextCurrent(nullptr); + if(g_acore.alcContext) { + alcDestroyContext(g_acore.alcContext); + g_acore.alcContext = nullptr; + } + + if (g_acore.alcDevice) { + alcCloseDevice(g_acore.alcDevice); + g_acore.alcDevice = nullptr; + } +} + + +// ------------------------------------------------------------------------------------------------- +// SLOTS +// ------------------------------------------------------------------------------------------------- + +static int avail_slot_id() +{ + auto result = g_acore.nextId; + g_acore.nextId += 1; + return result; +} + +int audio_core_slot_init(const std::vector &data, const ags::String &extension_hint, bool repeat) +{ + auto handle = avail_slot_id(); + + ALuint source_; + alGenSources(1, &source_); + dump_al_errors(); + + auto promise = std::promise>(); + promise.set_value(std::move(data)); + + auto decoder = OpenALDecoder(source_, promise.get_future(), extension_hint, repeat); + + std::lock_guard lk(g_acore.mixer_mutex_m); + g_acore.slots_[handle] = std::make_unique(handle, source_, std::move(decoder)); + g_acore.mixer_cv.notify_all(); + + return handle; +} + +// ------------------------------------------------------------------------------------------------- +// SLOT CONTROL +// ------------------------------------------------------------------------------------------------- + +void audio_core_slot_play(int slot_handle) +{ + std::lock_guard lk(g_acore.mixer_mutex_m); + g_acore.slots_[slot_handle]->decoder_.Play(); + g_acore.mixer_cv.notify_all(); +} + +void audio_core_slot_pause(int slot_handle) +{ + std::lock_guard lk(g_acore.mixer_mutex_m); + g_acore.slots_[slot_handle]->decoder_.Pause(); + g_acore.mixer_cv.notify_all(); +} + +void audio_core_slot_stop(int slot_handle) +{ + std::lock_guard lk(g_acore.mixer_mutex_m); + g_acore.slots_[slot_handle]->decoder_.Stop(); + g_acore.mixer_cv.notify_all(); +} + +void audio_core_slot_seek_ms(int slot_handle, float pos_ms) +{ + std::lock_guard lk(g_acore.mixer_mutex_m); + g_acore.slots_[slot_handle]->decoder_.Seek(pos_ms); + g_acore.mixer_cv.notify_all(); +} + + +// ------------------------------------------------------------------------------------------------- +// SLOT CONFIG +// ------------------------------------------------------------------------------------------------- + +void audio_core_set_master_volume(float newvol) +{ + alListenerf(AL_GAIN, newvol*GlobalGainScaling); + dump_al_errors(); +} + +void audio_core_slot_configure(int slot_handle, float volume, float speed, float panning) +{ + ALuint source_ = g_acore.slots_[slot_handle]->source_; + + alSourcef(source_, AL_GAIN, volume*0.7f); + dump_al_errors(); + + alSourcef(source_, AL_PITCH, speed); + dump_al_errors(); + + if (panning != 0.0f) { + // https://github.com/kcat/openal-soft/issues/194 + alSourcef(source_, AL_ROLLOFF_FACTOR, 0.0f); + dump_al_errors(); + alSourcei(source_, AL_SOURCE_RELATIVE, AL_TRUE); + dump_al_errors(); + alSource3f(source_, AL_POSITION, panning, 0.0f, 0.0f); + dump_al_errors(); + } + else { + alSourcef(source_, AL_ROLLOFF_FACTOR, 1.0f); + dump_al_errors(); + alSourcei(source_, AL_SOURCE_RELATIVE, AL_FALSE); + dump_al_errors(); + alSource3f(source_, AL_POSITION, 0.0f, 0.0f, 0.0f); + dump_al_errors(); + } +} + +// ------------------------------------------------------------------------------------------------- +// SLOT STATUS +// ------------------------------------------------------------------------------------------------- + +float audio_core_slot_get_pos_ms(int slot_handle) +{ + std::lock_guard lk(g_acore.mixer_mutex_m); + return g_acore.slots_[slot_handle]->decoder_.GetPositionMs(); + g_acore.mixer_cv.notify_all(); +} +AudioCorePlayState audio_core_slot_get_play_state(int slot_handle) +{ + std::lock_guard lk(g_acore.mixer_mutex_m); + return g_acore.slots_[slot_handle]->decoder_.GetPlayState(); + g_acore.mixer_cv.notify_all(); +} + + +// ------------------------------------------------------------------------------------------------- +// AUDIO PROCESSING +// ------------------------------------------------------------------------------------------------- + +static void audio_core_entry() +{ + std::unique_lock lk(g_acore.mixer_mutex_m); + + while (g_acore.audio_core_thread_running) { + + // burn off any errors for new loop + dump_al_errors(); + + for (auto &entry : g_acore.slots_) { + auto &slot = entry.second; + + try { + slot->decoder_.Poll(); + } catch (const std::exception& e) { + agsdbg::Printf(ags::kDbgMsg_Error, "OpenALDecoder poll exception %s", e.what()); + } + } + + g_acore.mixer_cv.wait_for(lk, std::chrono::milliseconds(50)); + } +} diff --git a/Engine/media/audio/audio_core.h b/Engine/media/audio/audio_core.h new file mode 100644 index 00000000000..5ccf939f3b3 --- /dev/null +++ b/Engine/media/audio/audio_core.h @@ -0,0 +1,56 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +// +// Audio Core: an audio backend interface. +// +//============================================================================= +#ifndef __AGS_EE_MEDIA__AUDIOCORE_H +#define __AGS_EE_MEDIA__AUDIOCORE_H +#include +#include "media/audio/audio_core_defs.h" +#include "util/string.h" + +// Initializes audio core system; +// starts polling on a background thread. +void audio_core_init(/*config, soundlib*/); +// Shut downs audio core system; +// stops any associated threads. +void audio_core_shutdown(); + +// Audio slot controls: slots are abstract holders for a playback. +// +// Initializes playback on a free playback slot (reuses spare one or allocates new if there's none). +// Data array must contain full wave data to play. +// TODO: this method requires having full sound in memory; +// should we add a streaming method later? is this of any priority for regular builds? +int audio_core_slot_init(const std::vector &data, const AGS::Common::String &extension_hint, bool repeat); +// Start playback on a slot +void audio_core_slot_play(int slot_handle); +// Pause playback on a slot, resume with 'audio_core_slot_play' +void audio_core_slot_pause(int slot_handle); +// Stop playback on a slot, disposes sound data, frees a slot +void audio_core_slot_stop(int slot_handle); +// Seek on a slot, new position in milliseconds +void audio_core_slot_seek_ms(int slot_handle, float pos_ms); + +// Audio core config +// Set new master volume, affects all slots +void audio_core_set_master_volume(float newvol); +// Sets up single playback parameters +void audio_core_slot_configure(int slot_handle, float volume, float speed, float panning); + +AudioCorePlayState audio_core_slot_get_play_state(int slot_handle); +float audio_core_slot_get_pos_ms(int slot_handle); + +#endif // __AGS_EE_MEDIA__AUDIOCORE_H diff --git a/Engine/media/audio/audio_core_defs.h b/Engine/media/audio/audio_core_defs.h new file mode 100644 index 00000000000..b11d126e92d --- /dev/null +++ b/Engine/media/audio/audio_core_defs.h @@ -0,0 +1,32 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +// +// Common definitions for audio core system. +// +//============================================================================= +#ifndef __AGS_EE_MEDIA__AUDIOCOREDEFS_H +#define __AGS_EE_MEDIA__AUDIOCOREDEFS_H + +// Audio slot (playback status +enum AudioCorePlayState +{ + PlayStateInitial, + PlayStatePlaying, + PlayStatePaused, + PlayStateStopped, + PlayStateFinished, + PlayStateError +}; + +#endif // __AGS_EE_MEDIA__AUDIOCOREDEFS_H diff --git a/Engine/media/audio/openal.h b/Engine/media/audio/openal.h new file mode 100644 index 00000000000..b38b1cd1d84 --- /dev/null +++ b/Engine/media/audio/openal.h @@ -0,0 +1,14 @@ +#ifndef __AGS_EE_MEDIA_OPENAL_H__ +#define __AGS_EE_MEDIA_OPENAL_H__ +#include "core/platform.h" + +#if AGS_PLATFORM_OS_MACOS + #include +#else + #include + #include + // [sonneveld] disabled until I add extension detection + // #include "alext.h" +#endif + +#endif // __AGS_EE_MEDIA_OPENAL_H__ diff --git a/Engine/media/audio/openaldecoder.cpp b/Engine/media/audio/openaldecoder.cpp new file mode 100644 index 00000000000..c96183c5883 --- /dev/null +++ b/Engine/media/audio/openaldecoder.cpp @@ -0,0 +1,322 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +#include "media/audio/openaldecoder.h" +#include +#include "debug/out.h" + +namespace ags = AGS::Common; +namespace agsdbg = AGS::Common::Debug; + + +void dump_al_errors() +{ + bool errorFound = false; + for (;;) { + auto err = alGetError(); + if (err == AL_NO_ERROR) { break; } + errorFound = true; + agsdbg::Printf(ags::kDbgMsg_Error, "error: %s", alGetString(err)); + } + assert(!errorFound); +} + + +const auto SourceMinimumQueuedBuffers = 2; +const auto SampleDefaultBufferSize = 64 * 1024; + +static struct +{ + std::vector freeBuffers; +} g_oaldec; + + +float OpenALDecoder::buffer_duration_ms(ALuint bufferID) { + ALint sizeInBytes; + ALint channels; + ALint bits; + ALint frequency; + + alGetBufferi(bufferID, AL_SIZE, &sizeInBytes); + alGetBufferi(bufferID, AL_CHANNELS, &channels); + alGetBufferi(bufferID, AL_BITS, &bits); + alGetBufferi(bufferID, AL_FREQUENCY, &frequency); + + auto lengthInSamples = sizeInBytes * 8 / (channels * bits); + return 1000.0f * (float)lengthInSamples / (float)frequency; +} + + +ALenum OpenALDecoder::openalFormatFromSample(const SoundSampleUniquePtr &sample) { + if (sample->desired.channels == 1) { + switch (sample->desired.format) { + case AUDIO_U8: + return AL_FORMAT_MONO8; + case AUDIO_S16SYS: + return AL_FORMAT_MONO16; + case AUDIO_F32SYS: + if (alIsExtensionPresent("AL_EXT_float32")) { + return alGetEnumValue("AL_FORMAT_MONO_FLOAT32"); + } + } + } + else if (sample->desired.channels == 2) { + switch (sample->desired.format) { + case AUDIO_U8: + return AL_FORMAT_STEREO8; + case AUDIO_S16SYS: + return AL_FORMAT_STEREO16; + case AUDIO_F32SYS: + if (alIsExtensionPresent("AL_EXT_float32")) { + return alGetEnumValue("AL_FORMAT_STEREO_FLOAT32"); + } + } + } + +#ifdef AUDIO_CORE_DEBUG + agsdbg::Printf(ags::kDbgMsg_Debug, "openalFormatFromSample: bad format chan:%d format: %d", sample->actual.channels, sample->actual.format); +#endif + + return 0; +} + +void OpenALDecoder::DecoderUnqueueProcessedBuffers() +{ + for (;;) { + ALint buffersProcessed = -1; + alGetSourcei(source_, AL_BUFFERS_PROCESSED, &buffersProcessed); + dump_al_errors(); + if (buffersProcessed <= 0) { break; } + + ALuint b; + alSourceUnqueueBuffers(source_, 1, &b); + dump_al_errors(); + + processedBuffersDurationMs_ += buffer_duration_ms(b); + + g_oaldec.freeBuffers.push_back(b); + } +} + + + +OpenALDecoder::OpenALDecoder(ALuint source, std::future> sampleBufFuture, AGS::Common::String sampleExt, bool repeat) + : source_(source), sampleBufFuture_(std::move(sampleBufFuture)), sampleExt_(sampleExt), repeat_(repeat) { + +} + +void OpenALDecoder::Poll() +{ + if (playState_ == AudioCorePlayState::PlayStateError) { return; } + + if (playState_ == AudioCorePlayState::PlayStateInitial) { + + if (sampleBufFuture_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) { return; } + + sampleData_ = std::move(sampleBufFuture_.get()); + + auto sample = SoundSampleUniquePtr(Sound_NewSampleFromMem((uint8_t *)sampleData_.data(), sampleData_.size(), sampleExt_.GetCStr(), nullptr, SampleDefaultBufferSize)); + if (!sample) { playState_ = AudioCorePlayState::PlayStateError; return; } + + auto bufferFormat = openalFormatFromSample(sample); + + if (bufferFormat <= 0) { +#ifdef AUDIO_CORE_DEBUG + agsdbg::Printf(ags::kDbgMsg_Debug, "audio_core_sample_load: RESAMPLING"); +#endif + auto desired = Sound_AudioInfo{ AUDIO_S16SYS, sample->actual.channels, sample->actual.rate }; + + Sound_FreeSample(sample.get()); + sample = SoundSampleUniquePtr(Sound_NewSampleFromMem((uint8_t *)sampleData_.data(), sampleData_.size(), sampleExt_.GetCStr(), &desired, SampleDefaultBufferSize)); + + if (!sample) { playState_ = AudioCorePlayState::PlayStateError; return; } + + bufferFormat = openalFormatFromSample(sample); + } + + if (bufferFormat <= 0) { playState_ = AudioCorePlayState::PlayStateError; return; } + + sample_ = std::move(sample); + sampleOpenAlFormat_ = bufferFormat; + + playState_ = onLoadPlayState_; + if (onLoadPositionMs >= 0.0f) { + Seek(onLoadPositionMs); + } + + } + + + if (playState_ != PlayStatePlaying) { return; } + + // buffer management + DecoderUnqueueProcessedBuffers(); + + // generate extra buffers if none are free + if (g_oaldec.freeBuffers.size() < SourceMinimumQueuedBuffers) { + std::array genbufs; + alGenBuffers(genbufs.size(), genbufs.data()); + dump_al_errors(); + for (const auto &b : genbufs) { + g_oaldec.freeBuffers.push_back(b); + } + } + + // decode and attach buffers + while (!EOS_) { + ALint buffersQueued = -1; + alGetSourcei(source_, AL_BUFFERS_QUEUED, &buffersQueued); + dump_al_errors(); + + if (buffersQueued >= SourceMinimumQueuedBuffers) { break; } + + assert(g_oaldec.freeBuffers.size() > 0); + auto it = std::prev(g_oaldec.freeBuffers.end()); + auto b = *it; + + auto sz = Sound_Decode(sample_.get()); + + if (sz <= 0) { + EOS_ = true; + // if repeat, then seek to start. + if (repeat_) { + auto res = Sound_Rewind(sample_.get()); + auto success = (res != 0); + EOS_ = !success; + } + continue; + } + + alBufferData(b, sampleOpenAlFormat_, sample_->buffer, sz, sample_->desired.rate); + dump_al_errors(); + + alSourceQueueBuffers(source_, 1, &b); + dump_al_errors(); + + g_oaldec.freeBuffers.erase(it); + } + + + // setup play state + + ALint state = AL_INITIAL; + alGetSourcei(source_, AL_SOURCE_STATE, &state); + dump_al_errors(); + + if (state != AL_PLAYING) { + alSourcePlay(source_); + dump_al_errors(); + } + + // if end of stream and still not playing, we done here. + ALint buffersRemaining = 0; + alGetSourcei(source_, AL_BUFFERS_QUEUED, &buffersRemaining); + dump_al_errors(); + if (EOS_ && buffersRemaining <= 0) { + playState_ = PlayStateFinished; + } + +} + +void OpenALDecoder::Play() +{ + switch (playState_) { + case PlayStateError: + break; + case PlayStateInitial: + onLoadPlayState_ = PlayStatePlaying; + break; + case PlayStateStopped: + Seek(0.0f); + case PlayStatePaused: + playState_ = AudioCorePlayState::PlayStatePlaying; + alSourcePlay(source_); + dump_al_errors(); + break; + default: + break; + } +} + +void OpenALDecoder::Pause() +{ + switch (playState_) { + case PlayStateError: + break; + case PlayStateInitial: + onLoadPlayState_ = PlayStatePaused; + break; + case PlayStatePlaying: + playState_ = AudioCorePlayState::PlayStatePaused; + alSourcePause(source_); + dump_al_errors(); + break; + default: + break; + } +} + +void OpenALDecoder::Stop() +{ + switch (playState_) { + case PlayStateError: + break; + case PlayStateInitial: + onLoadPlayState_ = PlayStateStopped; + break; + case PlayStatePlaying: + playState_ = AudioCorePlayState::PlayStateStopped; + alSourceStop(source_); + dump_al_errors(); + break; + default: + break; + } +} + +void OpenALDecoder::Seek(float pos_ms) +{ + switch (playState_) { + case PlayStateError: + break; + case PlayStateInitial: + onLoadPositionMs = pos_ms; + break; + default: + alSourceStop(source_); + dump_al_errors(); + DecoderUnqueueProcessedBuffers(); + Sound_Seek(sample_.get(), pos_ms); + processedBuffersDurationMs_ = pos_ms; + // will play when buffers are added in poll + } +} + +AudioCorePlayState OpenALDecoder::GetPlayState() +{ + return playState_; +} + +float OpenALDecoder::GetPositionMs() +{ + float alSecOffset = 0.0f; + // disabled with mojoal + // if source available: + alGetSourcef(source_, AL_SEC_OFFSET, &alSecOffset); + dump_al_errors(); + auto positionMs_ = processedBuffersDurationMs_ + alSecOffset*1000.0f; +#ifdef AUDIO_CORE_DEBUG + printf("proc:%f plus:%f = %f\n", processedBuffersDurationMs_, alSecOffset*1000.0f, positionMs_); +#endif + return positionMs_; +} diff --git a/Engine/media/audio/openaldecoder.h b/Engine/media/audio/openaldecoder.h new file mode 100644 index 00000000000..f20d2edd9f3 --- /dev/null +++ b/Engine/media/audio/openaldecoder.h @@ -0,0 +1,77 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +// +// OpenAL Decoder. +// +//============================================================================= +#ifndef __AGS_EE_MEDIA__OPENALDECODER_H +#define __AGS_EE_MEDIA__OPENALDECODER_H +#include +#include "media/audio/openal.h" +#include +#include "media/audio/audio_core_defs.h" +#include "util/string.h" + +struct SoundSampleDeleterFunctor { + void operator()(Sound_Sample* p) { + Sound_FreeSample(p); +#ifdef AUDIO_CORE_DEBUG + agsdbg::Printf(ags::kDbgMsg_Init, "SoundSampleDeleterFunctor"); +#endif + } +}; + +using SoundSampleUniquePtr = std::unique_ptr; + +class OpenALDecoder +{ +public: + OpenALDecoder(ALuint source, std::future> sampleBufFuture, AGS::Common::String sampleExt, bool repeat); + void Poll(); + void Play(); + void Pause(); + void Stop(); + void Seek(float pos_ms); + AudioCorePlayState GetPlayState(); + float GetPositionMs(); + +private: + ALuint source_; + + bool repeat_; + + AudioCorePlayState playState_ = PlayStateInitial; + + std::future> sampleBufFuture_{}; + std::vector sampleData_{}; + AGS::Common::String sampleExt_ = ""; + ALenum sampleOpenAlFormat_ = 0; + SoundSampleUniquePtr sample_ = nullptr; + + AudioCorePlayState onLoadPlayState_ = PlayStatePaused; + float onLoadPositionMs = 0.0f; + + float processedBuffersDurationMs_ = 0.0f; + + bool EOS_ = false; + + static float buffer_duration_ms(ALuint bufferID); + static ALenum openalFormatFromSample(const SoundSampleUniquePtr &sample); + void DecoderUnqueueProcessedBuffers(); +}; + + +void dump_al_errors(); + +#endif // __AGS_EE_MEDIA__OPENALDECODER_H diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 2e510665736..b31b2e03ba4 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -483,6 +483,7 @@ + @@ -491,6 +492,7 @@ + @@ -773,6 +775,8 @@ + + @@ -782,6 +786,8 @@ + + From 92411a3fe8c7a2cfab27884151c26db37de33d0e Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Wed, 30 Sep 2020 23:01:05 +0300 Subject: [PATCH 03/41] Imported OPENAL_SOUNDCLIP module Based on the work of @sonneveld (Nick Sonneveld); only relevant code, plus tidied up a little. --- Common/util/path.cpp | 10 + Common/util/path.h | 2 + Engine/ac/asset_helper.h | 2 + Engine/media/audio/audio_core.cpp | 15 ++ Engine/media/audio/audio_core.h | 4 + Engine/media/audio/clip_openal.cpp | 207 ++++++++++++++++++ Engine/media/audio/clip_openal.h | 73 ++++++ Engine/media/audio/soundclip.h | 2 +- Solutions/Engine.App/Engine.App.vcxproj | 2 + .../Engine.App/Engine.App.vcxproj.filters | 6 + 10 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 Engine/media/audio/clip_openal.cpp create mode 100644 Engine/media/audio/clip_openal.h diff --git a/Common/util/path.cpp b/Common/util/path.cpp index 88e305f05f6..bf42c684aff 100644 --- a/Common/util/path.cpp +++ b/Common/util/path.cpp @@ -39,6 +39,16 @@ bool IsFileOrDir(const String &filename) return ags_path_exists(fixed_path.GetCStr()) != 0; } +String GetFileExtension(const String &path) +{ + const auto pathComponents = path.Split('/'); + if (pathComponents.size() <= 0) { return ""; } + const String baseName = pathComponents[pathComponents.size() - 1]; + const int at = baseName.FindCharReverse('.'); + if (at < 0) { return ""; } + return baseName.Mid(at + 1); +} + int ComparePaths(const String &path1, const String &path2) { // Make minimal absolute paths diff --git a/Common/util/path.h b/Common/util/path.h index edcb82d1da9..41d938975fc 100644 --- a/Common/util/path.h +++ b/Common/util/path.h @@ -34,6 +34,8 @@ namespace Path // Tells if the given path is file or directory; // may be used to check if it's valid to use bool IsFileOrDir(const String &filename); + // Returns file's extension; file may be a fully qualified path too + String GetFileExtension(const String &path); // Makes a platform-dependant path comparison. // This takes into consideration platform's filename case (in)sensivity and diff --git a/Engine/ac/asset_helper.h b/Engine/ac/asset_helper.h index 9c6c442166c..076b8762219 100644 --- a/Engine/ac/asset_helper.h +++ b/Engine/ac/asset_helper.h @@ -47,6 +47,8 @@ AssetPath get_audio_clip_assetpath(int bundling_type, const String &filename); // Returns the path to the voice-over asset AssetPath get_voice_over_assetpath(const String &filename); +// Locates asset among known locations, on success returns open stream and asset's size. +Stream *LocateAsset(const AssetPath &path, size_t &asset_size); // Custom AGS PACKFILE user object // TODO: it is preferrable to let our Stream define custom readable window instead, // keeping this as simple as possible for now (we may require a stream classes overhaul). diff --git a/Engine/media/audio/audio_core.cpp b/Engine/media/audio/audio_core.cpp index 360537979da..d086cd0af2b 100644 --- a/Engine/media/audio/audio_core.cpp +++ b/Engine/media/audio/audio_core.cpp @@ -263,3 +263,18 @@ static void audio_core_entry() g_acore.mixer_cv.wait_for(lk, std::chrono::milliseconds(50)); } } + + +// ------------------------------------------------------------------------------------------------- +// UTILITY +// ------------------------------------------------------------------------------------------------- +// TODO: originally written by [sonneveld] for OpenAL sound impl, +// investigate if it's possible to avoid using full sound data here, +// maybe by letting decoder read a header from stream and find out format. +float audio_core_get_sound_length_ms(const std::vector &data, const char *extension_hint) +{ + auto sample = SoundSampleUniquePtr(Sound_NewSampleFromMem((Uint8 *)data.data(), data.size(), extension_hint, nullptr, 32 * 1024)); + if (sample == nullptr) { return -1; } + + return Sound_GetDuration(sample.get()); +} diff --git a/Engine/media/audio/audio_core.h b/Engine/media/audio/audio_core.h index 5ccf939f3b3..3b7d7084f3c 100644 --- a/Engine/media/audio/audio_core.h +++ b/Engine/media/audio/audio_core.h @@ -53,4 +53,8 @@ void audio_core_slot_configure(int slot_handle, float volume, float speed, float AudioCorePlayState audio_core_slot_get_play_state(int slot_handle); float audio_core_slot_get_pos_ms(int slot_handle); +// Utility methods +// Calculate sound clip length in milliseconds +float audio_core_get_sound_length_ms(const std::vector &data, const char *extension_hint); + #endif // __AGS_EE_MEDIA__AUDIOCORE_H diff --git a/Engine/media/audio/clip_openal.cpp b/Engine/media/audio/clip_openal.cpp new file mode 100644 index 00000000000..b31bba6caa9 --- /dev/null +++ b/Engine/media/audio/clip_openal.cpp @@ -0,0 +1,207 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +#include "media/audio/clip_openal.h" +#include "media/audio/audio_core.h" +#include "media/audio/audiodefines.h" +#include "util/path.h" +#include "util/stream.h" + + +OPENAL_SOUNDCLIP::OPENAL_SOUNDCLIP() : SOUNDCLIP(), slot_(-1) {} +OPENAL_SOUNDCLIP::~OPENAL_SOUNDCLIP() { destroy(); } + +void OPENAL_SOUNDCLIP::destroy() +{ + if (slot_ < 0) { return; } + audio_core_slot_stop(slot_); + slot_ = -1; +} + +int OPENAL_SOUNDCLIP::play() +{ + return play_from(0); +} + +int OPENAL_SOUNDCLIP::play_from(int position) +{ + if (slot_ < 0) { return 0; } + + configure_slot(); // volume, speed, panning, repeat + audio_core_slot_seek_ms(slot_, (float)position); + audio_core_slot_play(slot_); + return 1; +} + +void OPENAL_SOUNDCLIP::pause() +{ + if (slot_ < 0) { return; } + audio_core_slot_pause(slot_); +} +void OPENAL_SOUNDCLIP::resume() +{ + if (slot_ < 0) { return; } + audio_core_slot_play(slot_); +} + +bool OPENAL_SOUNDCLIP::is_playing() const +{ + if (slot_ < 0) { return false; } + auto status = audio_core_slot_get_play_state(slot_); + switch (status) { + case PlayStateInitial: + case PlayStatePlaying: + case PlayStatePaused: + return true; + } + return false; +} + +void OPENAL_SOUNDCLIP::seek(int pos_ms) +{ + if (slot_ < 0) { return; } + audio_core_slot_seek_ms(slot_, (float)pos_ms); +} + +void OPENAL_SOUNDCLIP::poll() { } + + +void OPENAL_SOUNDCLIP::configure_slot() +{ + if (slot_ < 0) { return; } + + auto vol_f = static_cast(get_final_volume()) / 255.0f; + if (vol_f < 0.0f) { vol_f = 0.0f; } + if (vol_f > 1.0f) { vol_f = 1.0f; } + + auto speed_f = static_cast(speed) / 1000.0f; + if (speed_f <= 0.0) { speed_f = 1.0f; } + + /* Sets the pan position, ranging from 0 (left) to 255 (right). 128 is considered centre */ + auto panning_f = (static_cast(panning-128) / 255.0f) * 2.0f; + if (panning_f < -1.0f) { panning_f = -1.0f; } + if (panning_f > 1.0f) { panning_f = 1.0f; } + + audio_core_slot_configure(slot_, vol_f, speed_f, panning_f); +} + +void OPENAL_SOUNDCLIP::set_volume(int newvol) +{ + vol = newvol; + adjust_volume(); +} + +void OPENAL_SOUNDCLIP::set_speed(int new_speed) +{ + speed = new_speed; + configure_slot(); +} + +void OPENAL_SOUNDCLIP::set_panning(int newPanning) +{ + panning = newPanning; + configure_slot(); +} + +void OPENAL_SOUNDCLIP::adjust_volume() +{ + configure_slot(); +} + +int OPENAL_SOUNDCLIP::get_pos() +{ + // until we can figure out other details, pos will always be in milliseconds + return get_pos_ms(); +} + +int OPENAL_SOUNDCLIP::get_pos_ms() +{ + if (slot_ < 0) { return -1; } + // given how unaccurate mp3 length is, maybe we should do differently here + // on the other hand, if on repeat, maybe better to just return an infinitely increasing position? + // but on the other other hand, then we can't always seek to that position. + if (lengthMs <= 0.0f) { + return (int)std::round(audio_core_slot_get_pos_ms(slot_)); + } + return (int)std::round(fmod(audio_core_slot_get_pos_ms(slot_), lengthMs)); +} + +int OPENAL_SOUNDCLIP::get_length_ms() +{ + return lengthMs; +} + + +// ------------------------------------------------------------------------------------------------- +// FACTORY METHODS +// ------------------------------------------------------------------------------------------------- + +int GuessSoundTypeFromExt(const String &extension) +{ + if (extension.CompareNoCase("mp3") == 0) { + return MUS_MP3; + } + else if (extension.CompareNoCase("ogg") == 0) { + return MUS_OGG; + } + else if (extension.CompareNoCase("mid") == 0) { + return MUS_MIDI; + } + else if (extension.CompareNoCase("wav") == 0) { + return MUS_WAVE; + } + else if (extension.CompareNoCase("voc") == 0) { + return MUS_WAVE; + } + else if (extension.CompareNoCase("mod") == 0) { + return MUS_MOD; + } + else if (extension.CompareNoCase("s3m") == 0) { + return MUS_MOD; + } + else if (extension.CompareNoCase("it") == 0) { + return MUS_MOD; + } + else if (extension.CompareNoCase("xm") == 0) { + return MUS_MOD; + } + return 0; +} + +SOUNDCLIP *my_load_openal(const AssetPath &asset_name, const char *extension_hint, int voll, bool loop) +{ + size_t asset_size; + auto *s = LocateAsset(asset_name, asset_size); + if (!s) + return nullptr; + + std::vector data(asset_size); + s->Read(data.data(), asset_size); + delete s; + + const auto asset_ext = AGS::Common::Path::GetFileExtension(asset_name.second); + const auto ext_hint = asset_ext.IsEmpty() ? String(extension_hint) : asset_ext; + const auto sound_type = GuessSoundTypeFromExt(asset_ext); + const auto lengthMs = (int)std::round(audio_core_get_sound_length_ms(data, asset_ext)); + + auto slot = audio_core_slot_init(data, asset_ext, loop); + if (slot < 0) { return nullptr; } + + auto clip = new OPENAL_SOUNDCLIP(); + clip->slot_ = slot; + clip->vol = voll; + clip->repeat = loop; + clip->soundType = sound_type; + clip->lengthMs = lengthMs; + return clip; +} diff --git a/Engine/media/audio/clip_openal.h b/Engine/media/audio/clip_openal.h new file mode 100644 index 00000000000..f4379ca1588 --- /dev/null +++ b/Engine/media/audio/clip_openal.h @@ -0,0 +1,73 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +// +// SOUNDCLIP implementation using OpenAL. +// Supports following formats: +// - MIDI (?) +// - MOD (?) +// - MP3 +// - OGG +// - WAV +// +//============================================================================= +#ifndef __AGS_EE_MEDIA__CLIP_OPENAL_H__ +#define __AGS_EE_MEDIA__CLIP_OPENAL_H__ +#include "media/audio/soundclip.h" +#include "ac/asset_helper.h" + +struct OPENAL_SOUNDCLIP final : public SOUNDCLIP +{ +public: + OPENAL_SOUNDCLIP(); + ~OPENAL_SOUNDCLIP(); + void destroy() override; + + virtual int get_sound_type() override { return soundType; } + + int play() override; + virtual int play_from(int position) override; + void pause() override; + void resume() override; + bool is_playing() const override; + + void seek(int pos) override; + + void poll() override; + + void set_volume(int newvol) override; + void set_speed(int new_speed) override; + void set_panning(int newPanning) override; + + int get_pos() override; + int get_pos_ms() override; + int get_length_ms() override; + + // TODO: make these private + int slot_ = -1; + int lengthMs = -1; + int soundType = 0; + +protected: + void adjust_volume() override; + int get_voice() override { return 0; } // only for Allegro-specific implementations + +private: + void configure_slot(); +}; + + +// Factory methods +SOUNDCLIP *my_load_openal(const AssetPath &asset_name, const char *extension_hint, int voll, bool loop); + +#endif // __AGS_EE_MEDIA__CLIP_OPENAL_H__ diff --git a/Engine/media/audio/soundclip.h b/Engine/media/audio/soundclip.h index 36a1166929d..3909ec47057 100644 --- a/Engine/media/audio/soundclip.h +++ b/Engine/media/audio/soundclip.h @@ -71,7 +71,7 @@ struct SOUNDCLIP virtual void pause(); virtual void resume(); - inline bool is_playing() const { return state_ == SoundClipPlaying || state_ == SoundClipPaused; } + virtual bool is_playing() const { return state_ == SoundClipPlaying || state_ == SoundClipPaused; } inline int get_speed() const { diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index b31b2e03ba4..eeffde15c9b 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -492,6 +492,7 @@ + @@ -786,6 +787,7 @@ + diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index c5a8046a04e..add45ef5a67 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -1041,6 +1041,9 @@ Library Sources\MojoAL + + Source Files\media\audio + @@ -1925,6 +1928,9 @@ Library Sources\MojoAL\AL + + Header Files\media\audio + From 62d39e3f394619c5ae8b219b085c4554feea1062 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 1 Oct 2020 03:27:50 +0300 Subject: [PATCH 04/41] Replaced allegro audio with new OpenAL audio core Based on the work of @sonneveld (Nick Sonneveld). Audio now plays only on a separate thread, unconditionally. Removed: * Allegro4-based SOUNDCLIP implementations; * old audio thread (now implemented in audio core module); * obsolete config settings; * PSP sound cache (may be reimplemented later). --- Engine/ac/draw.cpp | 1 - Engine/ac/event.cpp | 1 - Engine/ac/gamesetup.cpp | 1 - Engine/ac/gamesetup.h | 1 - Engine/ac/global_audio.cpp | 5 +- Engine/ac/global_debug.cpp | 2 - Engine/ac/system.cpp | 17 +- Engine/debug/debug.cpp | 1 - Engine/main/config.cpp | 19 +- Engine/main/engine.cpp | 193 +---------- Engine/main/game_run.cpp | 4 - Engine/main/main.cpp | 6 +- Engine/main/main.h | 6 +- Engine/main/quit.cpp | 11 +- Engine/media/audio/audio.cpp | 58 +--- Engine/media/audio/audio.h | 8 - Engine/media/audio/audio_system.h | 2 - Engine/media/audio/audiodefines.h | 4 - Engine/media/audio/clip_mydumbmod.cpp | 163 --------- Engine/media/audio/clip_mydumbmod.h | 69 ---- Engine/media/audio/clip_myjgmod.cpp | 89 ----- Engine/media/audio/clip_myjgmod.h | 49 --- Engine/media/audio/clip_mymidi.cpp | 111 ------ Engine/media/audio/clip_mymidi.h | 55 --- Engine/media/audio/clip_mymp3.cpp | 173 ---------- Engine/media/audio/clip_mymp3.h | 50 --- Engine/media/audio/clip_myogg.cpp | 203 ----------- Engine/media/audio/clip_myogg.h | 60 ---- Engine/media/audio/clip_mystaticmp3.cpp | 156 --------- Engine/media/audio/clip_mystaticmp3.h | 57 ---- Engine/media/audio/clip_mystaticogg.cpp | 205 ----------- Engine/media/audio/clip_mystaticogg.h | 63 ---- Engine/media/audio/clip_mywave.cpp | 116 ------- Engine/media/audio/clip_mywave.h | 50 --- Engine/media/audio/clip_openal.h | 1 - Engine/media/audio/sound.cpp | 321 +----------------- Engine/media/audio/sound.h | 4 +- Engine/media/audio/soundcache.cpp | 234 ------------- Engine/media/audio/soundcache.h | 48 --- Engine/media/audio/soundclip.cpp | 41 --- Engine/media/audio/soundclip.h | 27 +- Engine/platform/base/agsplatformdriver.cpp | 1 - Engine/platform/windows/acplwin.cpp | 11 - Engine/plugin/agsplugin.cpp | 6 +- Engine/script/script.cpp | 4 - Solutions/Engine.App/Engine.App.vcxproj | 18 - .../Engine.App/Engine.App.vcxproj.filters | 54 --- 47 files changed, 36 insertions(+), 2743 deletions(-) delete mode 100644 Engine/media/audio/clip_mydumbmod.cpp delete mode 100644 Engine/media/audio/clip_mydumbmod.h delete mode 100644 Engine/media/audio/clip_myjgmod.cpp delete mode 100644 Engine/media/audio/clip_myjgmod.h delete mode 100644 Engine/media/audio/clip_mymidi.cpp delete mode 100644 Engine/media/audio/clip_mymidi.h delete mode 100644 Engine/media/audio/clip_mymp3.cpp delete mode 100644 Engine/media/audio/clip_mymp3.h delete mode 100644 Engine/media/audio/clip_myogg.cpp delete mode 100644 Engine/media/audio/clip_myogg.h delete mode 100644 Engine/media/audio/clip_mystaticmp3.cpp delete mode 100644 Engine/media/audio/clip_mystaticmp3.h delete mode 100644 Engine/media/audio/clip_mystaticogg.cpp delete mode 100644 Engine/media/audio/clip_mystaticogg.h delete mode 100644 Engine/media/audio/clip_mywave.cpp delete mode 100644 Engine/media/audio/clip_mywave.h delete mode 100644 Engine/media/audio/soundcache.cpp delete mode 100644 Engine/media/audio/soundcache.h diff --git a/Engine/ac/draw.cpp b/Engine/ac/draw.cpp index c07fe267432..14374d16973 100644 --- a/Engine/ac/draw.cpp +++ b/Engine/ac/draw.cpp @@ -2391,7 +2391,6 @@ void construct_game_scene(bool full_redraw) if (displayed_room >= 0) { construct_room_view(); - update_polled_mp3(); } else if (!gfxDriver->RequiresFullRedrawEachFrame()) { diff --git a/Engine/ac/event.cpp b/Engine/ac/event.cpp index dc3bf6f6f84..17c57d9e6b3 100644 --- a/Engine/ac/event.cpp +++ b/Engine/ac/event.cpp @@ -291,7 +291,6 @@ void process_event(EventHappened*evp) { temp_scr->Blit(saved_backbuf, lxp, lyp, lxp, lyp, boxwid, boxhit); render_to_screen(); - update_polled_mp3(); WaitForNextFrame(); } gfxDriver->SetMemoryBackBuffer(saved_backbuf); diff --git a/Engine/ac/gamesetup.cpp b/Engine/ac/gamesetup.cpp index 88a22f4fcee..c55cdce483c 100644 --- a/Engine/ac/gamesetup.cpp +++ b/Engine/ac/gamesetup.cpp @@ -19,7 +19,6 @@ GameSetup::GameSetup() { digicard=DIGI_AUTODETECT; midicard=MIDI_AUTODETECT; - mod_player=1; no_speech_pack = false; textheight = 0; enable_antialiasing = false; diff --git a/Engine/ac/gamesetup.h b/Engine/ac/gamesetup.h index 672eb66d912..13b5b8faf0c 100644 --- a/Engine/ac/gamesetup.h +++ b/Engine/ac/gamesetup.h @@ -48,7 +48,6 @@ using AGS::Common::String; struct GameSetup { int digicard; int midicard; - int mod_player; int textheight; // text height used on the certain built-in GUI // TODO: move out to game class? bool no_speech_pack; bool enable_antialiasing; diff --git a/Engine/ac/global_audio.cpp b/Engine/ac/global_audio.cpp index cf232e91f55..a418928e28f 100644 --- a/Engine/ac/global_audio.cpp +++ b/Engine/ac/global_audio.cpp @@ -24,6 +24,7 @@ #include "debug/debugger.h" #include "game/roomstruct.h" #include "main/engine.h" +#include "media/audio/audio_core.h" #include "media/audio/audio_system.h" #include "ac/timer.h" #include "util/string_compat.h" @@ -357,7 +358,8 @@ void SetDigitalMasterVolume (int newvol) { if ((newvol<0) | (newvol>100)) quit("!SetDigitalMasterVolume: invalid volume - must be from 0-100"); play.digital_master_volume = newvol; - set_volume ((newvol * 255) / 100, -1); + auto newvol_f = static_cast(newvol) / 100.0; + audio_core_set_master_volume(newvol_f); } int GetCurrentMusic() { @@ -432,7 +434,6 @@ void PlaySilentMIDI (int mnum) { if (current_music_type == MUS_MIDI) quit("!PlaySilentMIDI: proper midi music is in progress"); - set_volume (-1, 0); play.silent_midi = mnum; play.silent_midi_channel = SCHAN_SPEECH; stop_and_destroy_channel(play.silent_midi_channel); diff --git a/Engine/ac/global_debug.cpp b/Engine/ac/global_debug.cpp index 582e1d20094..ee7cb312b3b 100644 --- a/Engine/ac/global_debug.cpp +++ b/Engine/ac/global_debug.cpp @@ -80,8 +80,6 @@ String GetRuntimeInfo() runtimeInfo.Append("[Using translation "); runtimeInfo.Append(transFileName); } - if (usetup.mod_player == 0) - runtimeInfo.Append("[(mod/xm player discarded)"); return runtimeInfo; } diff --git a/Engine/ac/system.cpp b/Engine/ac/system.cpp index 69a42f48b98..ceb82fd1c66 100644 --- a/Engine/ac/system.cpp +++ b/Engine/ac/system.cpp @@ -28,6 +28,7 @@ #include "ac/dynobj/cc_audiochannel.h" #include "main/graphics_mode.h" #include "ac/global_debug.h" +#include "media/audio/audio_core.h" #include "media/audio/audio_system.h" #include "util/string_compat.h" @@ -190,21 +191,9 @@ void System_SetVolume(int newvol) if ((newvol < 0) || (newvol > 100)) quit("!System.Volume: invalid volume - must be from 0-100"); - if (newvol == play.digital_master_volume) - return; - play.digital_master_volume = newvol; - set_volume((newvol * 255) / 100, (newvol * 255) / 100); - - // allegro's set_volume can lose the volumes of all the channels - // if it was previously set low; so restore them - AudioChannelsLock lock; - for (int i = 0; i <= MAX_SOUND_CHANNELS; i++) - { - auto* ch = lock.GetChannelIfPlaying(i); - if (ch) - ch->adjust_volume(); - } + auto newvol_f = static_cast(newvol) / 100.0; + audio_core_set_master_volume(newvol_f); } const char* System_GetRuntimeInfo() diff --git a/Engine/debug/debug.cpp b/Engine/debug/debug.cpp index 3be876c3830..3268fcab18c 100644 --- a/Engine/debug/debug.cpp +++ b/Engine/debug/debug.cpp @@ -536,7 +536,6 @@ bool send_exception_to_editor(const char *qmsg) while ((check_for_messages_from_editor() == 0) && (want_exit == 0)) { - update_polled_mp3(); platform->Delay(10); } #endif diff --git a/Engine/main/config.cpp b/Engine/main/config.cpp index 558d67ca923..a6b166d1cf6 100644 --- a/Engine/main/config.cpp +++ b/Engine/main/config.cpp @@ -423,8 +423,6 @@ extern int psp_gfx_scaling; extern int psp_gfx_super_sampling; extern int psp_gfx_smoothing; extern int psp_gfx_smooth_sprites; -extern int psp_audio_enabled; -extern int psp_midi_enabled; extern char psp_translation[]; void override_config_ext(ConfigTree &cfg) @@ -486,21 +484,8 @@ void apply_config(const ConfigTree &cfg) // Legacy settings has to be translated into new options; // they must be read first, to let newer options override them, if ones are present read_legacy_audio_config(cfg); - if (psp_audio_enabled) - { - usetup.digicard = read_driverid(cfg, "sound", "digiid", usetup.digicard); - if (psp_midi_enabled) - usetup.midicard = read_driverid(cfg, "sound", "midiid", usetup.midicard); - else - usetup.midicard = MIDI_NONE; - } - else - { - usetup.digicard = DIGI_NONE; - usetup.midicard = MIDI_NONE; - } - - psp_audio_multithreaded = INIreadint(cfg, "sound", "threaded", psp_audio_multithreaded); + usetup.digicard = read_driverid(cfg, "sound", "digiid", usetup.digicard); + usetup.midicard = read_driverid(cfg, "sound", "midiid", usetup.midicard); // Legacy graphics settings has to be translated into new options; // they must be read first, to let newer options override them, if ones are present diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index 4532275d40b..a38fe060643 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -64,7 +64,7 @@ #include "main/graphics_mode.h" #include "main/main.h" #include "main/main_allegro.h" -#include "media/audio/audio_system.h" +#include "media/audio/audio_core.h" #include "platform/util/pe.h" #include "util/directory.h" #include "util/error.h" @@ -438,130 +438,11 @@ void engine_init_timer() skipMissedTicks(); } -bool try_install_sound(int digi_id, int midi_id, String *p_err_msg = nullptr) -{ - Debug::Printf(kDbgMsg_Info, "Trying to init: digital driver ID: '%s' (0x%x), MIDI driver ID: '%s' (0x%x)", - AlIDToChars(digi_id).s, digi_id, AlIDToChars(midi_id).s, midi_id); - - if (install_sound(digi_id, midi_id, nullptr) == 0) - return true; - // Allegro does not let you try digital and MIDI drivers separately, - // and does not indicate which driver failed by return value. - // Therefore we try to guess. - if (p_err_msg) - *p_err_msg = get_allegro_error(); - if (midi_id != MIDI_NONE) - { - Debug::Printf(kDbgMsg_Error, "Failed to init one of the drivers; Error: '%s'.\nWill try to start without MIDI", get_allegro_error()); - if (install_sound(digi_id, MIDI_NONE, nullptr) == 0) - return true; - } - if (digi_id != DIGI_NONE) - { - Debug::Printf(kDbgMsg_Error, "Failed to init one of the drivers; Error: '%s'.\nWill try to start without DIGI", get_allegro_error()); - if (install_sound(DIGI_NONE, midi_id, nullptr) == 0) - return true; - } - Debug::Printf(kDbgMsg_Error, "Failed to init sound drivers. Error: %s", get_allegro_error()); - return false; -} - -// Attempts to predict a digital driver Allegro would chose, and get its maximal voices -std::pair autodetect_driver(_DRIVER_INFO *driver_list, int (*detect_audio_driver)(int), const char *type) -{ - for (int i = 0; driver_list[i].driver; ++i) - { - if (driver_list[i].autodetect) - { - int voices = detect_audio_driver(driver_list[i].id); - if (voices != 0) - return std::make_pair(driver_list[i].id, voices); - Debug::Printf(kDbgMsg_Warn, "Failed to detect %s driver %s; Error: '%s'.", - type, AlIDToChars(driver_list[i].id).s, get_allegro_error()); - } - } - return std::make_pair(0, 0); -} - -// Decides which audio driver to request from Allegro. -// Returns a pair of audio card ID and max available voices. -std::pair decide_audiodriver(int try_id, _DRIVER_INFO *driver_list, - int(*detect_audio_driver)(int), int &al_drv_id, const char *type) -{ - if (try_id == 0) // no driver - return std::make_pair(0, 0); - al_drv_id = 0; // the driver id will be set by library if one was found - if (try_id > 0) - { - int voices = detect_audio_driver(try_id); - if (al_drv_id == try_id && voices != 0) // found and detected - return std::make_pair(try_id, voices); - if (voices == 0) // found in list but detect failed - Debug::Printf(kDbgMsg_Error, "Failed to detect %s driver %s; Error: '%s'.", type, AlIDToChars(try_id).s, get_allegro_error()); - else // not found at all - Debug::Printf(kDbgMsg_Error, "Unknown %s driver: %s, will try to find suitable one.", type, AlIDToChars(try_id).s); - } - return autodetect_driver(driver_list, detect_audio_driver, type); -} - void engine_init_audio() { Debug::Printf("Initializing sound drivers"); - int digi_id = usetup.digicard; - int midi_id = usetup.midicard; - int digi_voices = -1; - int midi_voices = -1; - // MOD player would need certain minimal number of voices - // TODO: find out if this is still relevant? - if (usetup.mod_player) - digi_voices = NUM_DIGI_VOICES; - - Debug::Printf(kDbgMsg_Info, "Sound settings: digital driver ID: '%s' (0x%x), MIDI driver ID: '%s' (0x%x)", - AlIDToChars(digi_id).s, digi_id, AlIDToChars(midi_id).s, midi_id); - - // First try if drivers are supported, and switch to autodetect if explicit option failed - _DRIVER_INFO *digi_drivers = system_driver->digi_drivers ? system_driver->digi_drivers() : _digi_driver_list; - std::pair digi_drv = decide_audiodriver(digi_id, digi_drivers, detect_digi_driver, digi_card, "digital"); - _DRIVER_INFO *midi_drivers = system_driver->midi_drivers ? system_driver->midi_drivers() : _midi_driver_list; - std::pair midi_drv = decide_audiodriver(midi_id, midi_drivers, detect_midi_driver, midi_card, "MIDI"); - - // Now, knowing which drivers we suppose to install, decide on which voices we reserve - digi_id = digi_drv.first; - midi_id = midi_drv.first; - const int max_digi_voices = digi_drv.second; - const int max_midi_voices = midi_drv.second; - if (digi_voices > max_digi_voices) - digi_voices = max_digi_voices; - // NOTE: we do not specify number of MIDI voices, so don't have to calculate available here - - reserve_voices(digi_voices, midi_voices); - // maybe this line will solve the sound volume? [??? wth is this] - set_volume_per_voice(1); - - String err_msg; - bool sound_res = try_install_sound(digi_id, midi_id, &err_msg); - if (!sound_res) - { - Debug::Printf(kDbgMsg_Error, "Everything failed, disabling sound."); - reserve_voices(0, 0); - install_sound(DIGI_NONE, MIDI_NONE, nullptr); - } - // Only display a warning if they wanted a sound card - const bool digi_failed = usetup.digicard != DIGI_NONE && digi_card == DIGI_NONE; - const bool midi_failed = usetup.midicard != MIDI_NONE && midi_card == MIDI_NONE; - if (digi_failed || midi_failed) - { - platform->DisplayAlert("Warning: cannot enable %s.\nProblem: %s.\n\nYou may supress this message by disabling %s in the game setup.", - (digi_failed && midi_failed ? "game audio" : (digi_failed ? "digital audio" : "MIDI audio") ), - (err_msg.IsEmpty() ? "No compatible drivers found in the system" : err_msg.GetCStr()), - (digi_failed && midi_failed ? "sound" : (digi_failed ? "digital sound" : "MIDI sound") )); - } - - usetup.digicard = digi_card; - usetup.midicard = midi_card; - - Debug::Printf(kDbgMsg_Info, "Installed digital driver ID: '%s' (0x%x), MIDI driver ID: '%s' (0x%x)", - AlIDToChars(digi_card).s, digi_card, AlIDToChars(midi_card).s, midi_card); + audio_core_init(); // audio core system + our_eip = -181; if (digi_card == DIGI_NONE) { @@ -571,25 +452,10 @@ void engine_init_audio() play.want_speech = -2; play.separate_music_lib = 0; } - if (usetup.mod_player && digi_driver->voices < NUM_DIGI_VOICES) - { - // disable MOD player if there's not enough digital voices - // TODO: find out if this is still relevant? - usetup.mod_player = 0; - } - -#if AGS_PLATFORM_OS_WINDOWS - if (digi_card == DIGI_DIRECTX(0)) - { - // DirectX mixer seems to buffer an extra sample itself - use_extra_sound_offset = 1; - } -#endif } void engine_init_debug() { - //set_volume(255,-1); if ((debug_flags & (~DBG_DEBUGMODE)) >0) { platform->DisplayAlert("Engine debugging enabled.\n" "\nNOTE: You have selected to enable one or more engine debugging options.\n" @@ -789,26 +655,6 @@ int engine_check_font_was_loaded() return 0; } -void engine_init_modxm_player() -{ -#ifndef PSP_NO_MOD_PLAYBACK - if (game.options[OPT_NOMODMUSIC]) - usetup.mod_player = 0; - - if (usetup.mod_player) { - Debug::Printf(kDbgMsg_Info, "Initializing MOD/XM player"); - - if (init_mod_player(NUM_MOD_DIGI_VOICES) < 0) { - platform->DisplayAlert("Warning: install_mod: MOD player failed to initialize."); - usetup.mod_player=0; - } - } -#else - usetup.mod_player = 0; - Debug::Printf(kDbgMsg_Info, "Compiled without MOD/XM player"); -#endif -} - // Do the preload graphic if available void show_preload() { @@ -1136,42 +982,11 @@ void engine_setup_scsystem_auxiliary() } } -void engine_update_mp3_thread() -{ - update_mp3_thread(); - platform->Delay(50); -} - -void engine_start_multithreaded_audio() -{ - // PSP: Initialize the sound cache. - clear_sound_cache(); - - // Create sound update thread. This is a workaround for sound stuttering. - if (psp_audio_multithreaded) - { - if (!audioThread.CreateAndStart(engine_update_mp3_thread, true)) - { - Debug::Printf(kDbgMsg_Info, "Failed to start audio thread, audio will be processed on the main thread"); - psp_audio_multithreaded = 0; - } - else - { - Debug::Printf(kDbgMsg_Info, "Audio thread started"); - } - } - else - { - Debug::Printf(kDbgMsg_Info, "Audio is processed on the main thread"); - } -} - void engine_prepare_to_start_game() { Debug::Printf("Prepare to start game"); engine_setup_scsystem_auxiliary(); - engine_start_multithreaded_audio(); #if AGS_PLATFORM_OS_ANDROID if (psp_load_latest_savegame) @@ -1553,8 +1368,6 @@ int initialize_engine(const ConfigTree &startup_opts) our_eip = -179; - engine_init_modxm_player(); - engine_init_resolution_settings(game.GetGameRes()); // Attempt to initialize graphics mode diff --git a/Engine/main/game_run.cpp b/Engine/main/game_run.cpp index 1baf504d526..ed2eb114eaf 100644 --- a/Engine/main/game_run.cpp +++ b/Engine/main/game_run.cpp @@ -748,8 +748,6 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int int res; - update_polled_mp3(); - numEventsAtStartOfFunction = numevents; if (want_exit) { @@ -1037,8 +1035,6 @@ void update_polled_stuff_if_runtime() quit("||exit!"); } - update_polled_mp3(); - if (editor_debugging_initialized) check_for_messages_from_editor(); } diff --git a/Engine/main/main.cpp b/Engine/main/main.cpp index abe98495a50..da9296a9462 100644 --- a/Engine/main/main.cpp +++ b/Engine/main/main.cpp @@ -91,13 +91,9 @@ const char *loadSaveGameOnStartup = nullptr; #if ! AGS_PLATFORM_DEFINES_PSP_VARS int psp_video_framedrop = 1; -int psp_audio_enabled = 1; -int psp_midi_enabled = 1; int psp_ignore_acsetup_cfg_file = 0; -int psp_clear_cache_on_room_change = 0; +int psp_clear_cache_on_room_change = 0; // clear --sprite cache-- when room is unloaded -int psp_midi_preload_patches = 0; -int psp_audio_cachesize = 10; char psp_game_file_name[] = ""; char psp_translation[] = "default"; diff --git a/Engine/main/main.h b/Engine/main/main.h index 1f5116d342b..27f7412f76c 100644 --- a/Engine/main/main.h +++ b/Engine/main/main.h @@ -48,13 +48,9 @@ extern bool justTellInfo; extern const char *loadSaveGameOnStartup; extern int psp_video_framedrop; -extern int psp_audio_enabled; -extern int psp_midi_enabled; extern int psp_ignore_acsetup_cfg_file; -extern int psp_clear_cache_on_room_change; +extern int psp_clear_cache_on_room_change; // clear --sprite cache-- when room is unloaded -extern int psp_midi_preload_patches; -extern int psp_audio_cachesize; extern char psp_game_file_name[]; extern char psp_translation[]; diff --git a/Engine/main/quit.cpp b/Engine/main/quit.cpp index 678b376eef2..3c8f6b40306 100644 --- a/Engine/main/quit.cpp +++ b/Engine/main/quit.cpp @@ -116,16 +116,7 @@ void quit_shutdown_audio() { our_eip = 9917; game.options[OPT_CROSSFADEMUSIC] = 0; - stopmusic(); -#ifndef PSP_NO_MOD_PLAYBACK - if (usetup.mod_player) - remove_mod_player(); -#endif - - // Quit the sound thread. - audioThread.Stop(); - - remove_sound(); + shutdown_sound(); } QuitReason quit_check_for_error_state(const char *&qmsg, String &alertis) diff --git a/Engine/media/audio/audio.cpp b/Engine/media/audio/audio.cpp index 2a0a7d073c7..83e91c3efbe 100644 --- a/Engine/media/audio/audio.cpp +++ b/Engine/media/audio/audio.cpp @@ -38,6 +38,7 @@ #include "core/assetmanager.h" #include "ac/timer.h" #include "main/game_run.h" +#include "media/audio/audio_core.h" using namespace AGS::Common; using namespace AGS::Engine; @@ -109,16 +110,10 @@ extern CharacterInfo*playerchar; extern volatile int switching_away_from_game; -#if ! AGS_PLATFORM_OS_IOS && ! AGS_PLATFORM_OS_ANDROID -volatile int psp_audio_multithreaded = 0; -#endif - ScriptAudioChannel scrAudioChannel[MAX_SOUND_CHANNELS + 1]; char acaudio_buffer[256]; int reserved_channel_count = 0; -AGS::Engine::Thread audioThread; - void calculate_reserved_channel_count() { int reservedChannels = 0; @@ -269,11 +264,7 @@ SOUNDCLIP *load_sound_clip(ScriptAudioClip *audioClip, bool repeat) soundClip = my_load_midi(asset_name, repeat); break; case eAudioFileMOD: -#ifndef PSP_NO_MOD_PLAYBACK soundClip = my_load_mod(asset_name, repeat); -#else - soundClip = NULL; -#endif break; default: quitprintf("AudioClip.Play: invalid audio file type encountered: %d", audioClip->fileType); @@ -394,8 +385,6 @@ static void queue_audio_clip_to_play(ScriptAudioClip *clip, int priority, int re play.new_music_queue[play.new_music_queue_size].cachedClip = cachedClip; play.new_music_queue_size++; } - - update_polled_mp3(); } ScriptAudioChannel* play_audio_clip_on_channel(int channel, ScriptAudioClip *clip, int priority, int repeat, int fromOffset, SOUNDCLIP *soundfx) @@ -604,12 +593,6 @@ SOUNDCLIP *load_sound_clip_from_old_style_number(bool isMusic, int indexNumber, //============================================================================= -void force_audiostream_include() { - // This should never happen, but the call is here to make it - // link the audiostream libraries - stop_audio_stream(nullptr); -} - // TODO: double check that ambient sounds array actually needs +1 std::array ambient; @@ -714,25 +697,19 @@ SOUNDCLIP *load_sound_and_play(ScriptAudioClip *aclip, bool repeat) void stop_all_sound_and_music() { - int a; stopmusic(); stop_voice_nonblocking(); // make sure it doesn't start crossfading when it comes back crossFading = 0; // any ambient sound will be aborted - for (a = 0; a <= MAX_SOUND_CHANNELS; a++) - stop_and_destroy_channel(a); + for (int i = 0; i <= MAX_SOUND_CHANNELS; ++i) + stop_and_destroy_channel(i); } void shutdown_sound() { - stop_all_sound_and_music(); - -#ifndef PSP_NO_MOD_PLAYBACK - if (usetup.mod_player) - remove_mod_player(); -#endif - remove_sound(); + stop_all_sound_and_music(); // game logic + audio_core_shutdown(); // audio core system } // the sound will only be played if there is a free channel or @@ -917,31 +894,6 @@ void update_volume_drop_if_voiceover() apply_volume_drop_modifier(play.speech_has_voice); } -extern volatile char want_exit; - -void update_mp3_thread() -{ - if (switching_away_from_game) { return; } - - AudioChannelsLock lock; - - for(int i = 0; i <= MAX_SOUND_CHANNELS; ++i) - { - auto* ch = lock.GetChannel(i); - if (ch) - ch->poll(); - } -} - -//this is called at various points to give streaming logic a chance to update -//it seems those calls have been littered around and points where it ameliorated skipping -//a better solution would be to forcibly thread the streaming logic -void update_polled_mp3() -{ - if (psp_audio_multithreaded) { return; } - update_mp3_thread(); -} - // Update the music, and advance the crossfade on a step // (this should only be called once per game loop) void update_audio_system_on_game_loop () diff --git a/Engine/media/audio/audio.h b/Engine/media/audio/audio.h index 05600c9d53d..793002af9ce 100644 --- a/Engine/media/audio/audio.h +++ b/Engine/media/audio/audio.h @@ -87,9 +87,6 @@ SOUNDCLIP * load_sound_clip_from_old_style_number(bool isMusic, int indexNumber, //============================================================================= -int init_mod_player(int numVoices); -void remove_mod_player(); -void force_audiostream_include(); int get_volume_adjusted_for_distance(int volume, int sndX, int sndY, int sndMaxDist); void update_directional_sound_vol(); void update_ambient_sound_vol (); @@ -129,12 +126,7 @@ ScriptAudioClip *get_audio_clip_for_music(int mnum); SOUNDCLIP * load_music_from_disk(int mnum, bool doRepeat); void newmusic(int mnum); -extern AGS::Engine::Thread audioThread; extern volatile bool _audio_doing_crossfade; -extern volatile int psp_audio_multithreaded; - -void update_polled_mp3(); -void update_mp3_thread(); extern void cancel_scheduled_music_update(); extern void schedule_music_update_at(AGS_Clock::time_point); diff --git a/Engine/media/audio/audio_system.h b/Engine/media/audio/audio_system.h index 4cb910c6572..ddb378f3379 100644 --- a/Engine/media/audio/audio_system.h +++ b/Engine/media/audio/audio_system.h @@ -6,8 +6,6 @@ #include "media/audio/audio.h" -#include "media/audio/soundcache.h" - #include "media/audio/soundclip.h" #include "media/audio/sound.h" diff --git a/Engine/media/audio/audiodefines.h b/Engine/media/audio/audiodefines.h index 13effae234b..45434d10a1d 100644 --- a/Engine/media/audio/audiodefines.h +++ b/Engine/media/audio/audiodefines.h @@ -21,10 +21,6 @@ #define MUS_MOD 4 #define MUS_OGG 5 -#ifndef PSP_NO_MOD_PLAYBACK -#define DUMB_MOD_PLAYER -#endif - #define MAX_SOUND_CHANNELS 8 #define SPECIAL_CROSSFADE_CHANNEL 8 diff --git a/Engine/media/audio/clip_mydumbmod.cpp b/Engine/media/audio/clip_mydumbmod.cpp deleted file mode 100644 index 8c040626588..00000000000 --- a/Engine/media/audio/clip_mydumbmod.cpp +++ /dev/null @@ -1,163 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" - -#ifdef DUMB_MOD_PLAYER - -#include "media/audio/clip_mydumbmod.h" -#include "media/audio/audiointernaldefs.h" - -void al_duh_set_loop(AL_DUH_PLAYER *dp, int loop) { - DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(dp); - DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr); - if (itsr == nullptr) - return; - - if (loop) - dumb_it_set_loop_callback(itsr, nullptr, nullptr); - else - dumb_it_set_loop_callback(itsr, dumb_it_callback_terminate, itsr); -} - -void MYMOD::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - if (al_poll_duh(duhPlayer)) { - state_ = SoundClipStopped; - } -} - -void MYMOD::adjust_volume() -{ - if (!is_playing()) { return; } - al_duh_set_volume(duhPlayer, VOLUME_TO_DUMB_VOL(get_final_volume())); -} - -void MYMOD::set_volume(int newvol) -{ - vol = newvol; - adjust_volume(); -} - -void MYMOD::destroy() -{ - if (duhPlayer) { - al_stop_duh(duhPlayer); - } - duhPlayer = nullptr; - - if (tune) { - unload_duh(tune); - } - tune = nullptr; - - state_ = SoundClipStopped; -} - -void MYMOD::seek(int patnum) -{ - if (!is_playing()) { return; } - - al_stop_duh(duhPlayer); - state_ = SoundClipInitial; - - DUH_SIGRENDERER *sr = dumb_it_start_at_order(tune, 2, patnum); - duhPlayer = al_duh_encapsulate_sigrenderer(sr, VOLUME_TO_DUMB_VOL(vol), 8192, 22050); - if (!duhPlayer) { - duh_end_sigrenderer(sr); - return; - } - - al_duh_set_loop(duhPlayer, repeat); - state_ = SoundClipPlaying; -} - -int MYMOD::get_pos() -{ - if (!is_playing()) { return -1; } - - // determine the current track number (DUMB calls them 'orders') - DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(duhPlayer); - DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr); - if (itsr == nullptr) - return -1; - - return dumb_it_sr_get_current_order(itsr); -} - -int MYMOD::get_real_mod_pos() -{ - if (!is_playing()) { return -1; } - return al_duh_get_position(duhPlayer); -} - -int MYMOD::get_pos_ms() -{ - if (!is_playing()) { return -1; } - return (get_real_mod_pos() * 10) / 655; -} - -int MYMOD::get_length_ms() -{ - if (tune == nullptr) - return 0; - - // duh_get_length represents time as 65536ths of a second - return (duh_get_length(tune) * 10) / 655; -} - -int MYMOD::get_voice() -{ - // MOD uses so many different voices it's not practical to keep track - return -1; -} - -void MYMOD::pause() { - if (state_ != SoundClipPlaying) { return; } - al_pause_duh(duhPlayer); - state_ = SoundClipPaused; -} - -void MYMOD::resume() { - if (state_ != SoundClipPaused) { return; } - al_resume_duh(duhPlayer); - state_ = SoundClipPlaying; -} - -int MYMOD::get_sound_type() { - return MUS_MOD; -} - -int MYMOD::play() { - if (tune == nullptr) { return 0; } - - duhPlayer = al_start_duh(tune, 2, 0, 1.0, 8192, 22050); - if (!duhPlayer) { - return 0; - } - al_duh_set_loop(duhPlayer, repeat); - set_volume(vol); - - state_ = SoundClipPlaying; - return 1; -} - -MYMOD::MYMOD() : SOUNDCLIP() { - tune = nullptr; - duhPlayer = nullptr; -} - -#endif // DUMB_MOD_PLAYER \ No newline at end of file diff --git a/Engine/media/audio/clip_mydumbmod.h b/Engine/media/audio/clip_mydumbmod.h deleted file mode 100644 index 193c7f4567c..00000000000 --- a/Engine/media/audio/clip_mydumbmod.h +++ /dev/null @@ -1,69 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYDUMBMOD_H -#define __AC_MYDUMBMOD_H - -#include "aldumb.h" -#include "media/audio/soundclip.h" - -#define VOLUME_TO_DUMB_VOL(vol) ((float)vol) / 256.0 - -void al_duh_set_loop(AL_DUH_PLAYER *dp, int loop); - -// MOD/XM (DUMB) -struct MYMOD : public SOUNDCLIP -{ - DUH *tune; - AL_DUH_PLAYER *duhPlayer; - - void poll() override; - - void set_volume(int newvol) override; - - void destroy() override; - - void seek(int patnum) override; - - // NOTE: this implementation of the virtual function returns a MOD/XM - // "order" index, not actual playing position; - // this does not make much sense in the context of the interface itself, - // and, as it seems, was implemented so solely for the purpose of emulating - // deprecated "GetMODPattern" script function. - // (see Game_GetMODPattern(), and documentation for AudioChannel.Position property) - // TODO: find a way to redesign this behavior - int get_pos() override; - - int get_pos_ms() override; - - int get_length_ms() override; - - void pause() override; - - void resume() override; - - int get_sound_type() override; - - int play() override; - - MYMOD(); - -protected: - int get_voice() override; - void adjust_volume() override; - // Returns real MOD/XM playing position - int get_real_mod_pos(); -}; - -#endif // __AC_MYDUMBMOD_H \ No newline at end of file diff --git a/Engine/media/audio/clip_myjgmod.cpp b/Engine/media/audio/clip_myjgmod.cpp deleted file mode 100644 index 45209551e7d..00000000000 --- a/Engine/media/audio/clip_myjgmod.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" - -#ifdef JGMOD_MOD_PLAYER - -#include "media/audio/clip_myjgmod.h" -#include "media/audio/audiointernaldefs.h" - -int MYMOD::poll() -{ - if (done) - return done; - - if (is_mod_playing() == 0) - done = 1; - - return done; -} - -void MYMOD::set_volume(int newvol) -{ - vol = newvol; - if (!done) - set_mod_volume(newvol); -} - -void MYMOD::destroy() -{ - stop_mod(); - destroy_mod(tune); - tune = NULL; -} - -void MYMOD::seek(int patnum) -{ - if (is_mod_playing() != 0) - goto_mod_track(patnum); -} - -int MYMOD::get_pos() -{ - if (!is_mod_playing()) - return -1; - return mi.trk; -} - -int MYMOD::get_pos_ms() -{ - return 0; // we don't know ms offset -} - -int MYMOD::get_length_ms() -{ // we don't know ms - return 0; -} - -int MYMOD::get_voice() -{ - // MOD uses so many different voices it's not practical to keep track - return -1; -} - -int MYMOD::get_sound_type() { - return MUS_MOD; -} - -int MYMOD::play() { - play_mod(tune, repeat); - - return 1; -} - -MYMOD::MYMOD() : SOUNDCLIP() { -} - -#endif // #ifdef JGMOD_MOD_PLAYER \ No newline at end of file diff --git a/Engine/media/audio/clip_myjgmod.h b/Engine/media/audio/clip_myjgmod.h deleted file mode 100644 index 6870b67503c..00000000000 --- a/Engine/media/audio/clip_myjgmod.h +++ /dev/null @@ -1,49 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYJGMOD_H -#define __AC_MYJGMOD_H - -#include "jgmod.h" -#include "media/audio/soundclip.h" - -// MOD/XM (JGMOD) -struct MYMOD:public SOUNDCLIP -{ - JGMOD *tune; - - int poll(); - - void set_volume(int newvol); - - void destroy(); - - void seek(int patnum); - - int get_pos(); - - int get_pos_ms(); - - int get_length_ms(); - - int get_voice(); - - int get_sound_type(); - - int play(); - - MYMOD(); -}; - -#endif // __AC_MYJGMOD_H \ No newline at end of file diff --git a/Engine/media/audio/clip_mymidi.cpp b/Engine/media/audio/clip_mymidi.cpp deleted file mode 100644 index 1175bab306d..00000000000 --- a/Engine/media/audio/clip_mymidi.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" -#include "util/wgt2allg.h" -#include "media/audio/clip_mymidi.h" -#include "media/audio/audiointernaldefs.h" - -void MYMIDI::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - if (midi_pos < 0) - state_ = SoundClipStopped; -} - -void MYMIDI::adjust_volume() -{ - if (!is_playing()) { return; } - ::set_volume(-1, get_final_volume()); -} - -void MYMIDI::set_volume(int newvol) -{ - vol = newvol; - adjust_volume(); -} - -void MYMIDI::destroy() -{ - stop_midi(); - - if (tune) { - destroy_midi(tune); - } - tune = nullptr; - - state_ = SoundClipStopped; -} - -void MYMIDI::seek(int pos) -{ - if (!is_playing()) { return; } - midi_seek(pos); -} - -int MYMIDI::get_pos() -{ - if (!is_playing()) { return -1; } - return midi_pos; -} - -int MYMIDI::get_pos_ms() -{ - return 0; // we don't know ms with midi -} - -int MYMIDI::get_length_ms() -{ - return lengthInSeconds * 1000; -} - -int MYMIDI::get_voice() -{ - // voice is N/A for midi - return -1; -} - -void MYMIDI::pause() { - if (state_ != SoundClipPlaying) { return; } - midi_pause(); - state_ = SoundClipPaused; -} - -void MYMIDI::resume() { - if (state_ != SoundClipPaused) { return; } - midi_resume(); - state_ = SoundClipPlaying; -} - -int MYMIDI::get_sound_type() { - return MUS_MIDI; -} - -int MYMIDI::play() { - if (tune == nullptr) { return 0; } - - lengthInSeconds = get_midi_length(tune); - if (::play_midi(tune, repeat)) { - return 0; - } - - state_ = SoundClipPlaying; - return 1; -} - -MYMIDI::MYMIDI() : SOUNDCLIP() { - tune = nullptr; - lengthInSeconds = 0; -} diff --git a/Engine/media/audio/clip_mymidi.h b/Engine/media/audio/clip_mymidi.h deleted file mode 100644 index 5799f5ab88e..00000000000 --- a/Engine/media/audio/clip_mymidi.h +++ /dev/null @@ -1,55 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYMIDI_H -#define __AC_MYMIDI_H - -#include "media/audio/soundclip.h" - -// MIDI -struct MYMIDI:public SOUNDCLIP -{ - MIDI *tune; - int lengthInSeconds; - - void poll() override; - - void set_volume(int newvol) override; - - void destroy() override; - - void seek(int pos) override; - - int get_pos() override; - - int get_pos_ms() override; - - int get_length_ms() override; - - void pause() override; - - void resume() override; - - int get_sound_type() override; - - int play() override; - - MYMIDI(); - -protected: - int get_voice() override; - void adjust_volume() override; -}; - -#endif // __AC_MYMIDI_H \ No newline at end of file diff --git a/Engine/media/audio/clip_mymp3.cpp b/Engine/media/audio/clip_mymp3.cpp deleted file mode 100644 index b4c98d849ea..00000000000 --- a/Engine/media/audio/clip_mymp3.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" - -#ifndef NO_MP3_PLAYER - -#include "media/audio/clip_mymp3.h" -#include "media/audio/audiointernaldefs.h" -#include "ac/common.h" // quit() -#include "ac/asset_helper.h" -#include "util/mutex_lock.h" - -#include "platform/base/agsplatformdriver.h" - - -void MYMP3::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - // update the buffer - char *tempbuf = nullptr; - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - tempbuf = (char *)almp3_get_mp3stream_buffer(stream); - } - - if (tempbuf != nullptr) { - AGS_PACKFILE_OBJ* obj = (AGS_PACKFILE_OBJ*)in->userdata; - int free_val = -1; - if (chunksize >= obj->remains) { - chunksize = obj->remains; - free_val = chunksize; - } - pack_fread(tempbuf, chunksize, in); - - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - almp3_free_mp3stream_buffer(stream, free_val); - } - } - - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - if (almp3_poll_mp3stream(stream) == ALMP3_POLL_PLAYJUSTFINISHED) { - state_ = SoundClipStopped; - } - } -} - -void MYMP3::adjust_stream() -{ - if (!is_playing()) { return; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - almp3_adjust_mp3stream(stream, get_final_volume(), panning, speed); -} - -void MYMP3::adjust_volume() -{ - adjust_stream(); -} - -void MYMP3::set_volume(int newvol) -{ - // boost MP3 volume - newvol += 20; - if (newvol > 255) - newvol = 255; - - vol = newvol; - adjust_stream(); -} - -void MYMP3::set_speed(int new_speed) -{ - speed = new_speed; - adjust_stream(); -} - -void MYMP3::destroy() -{ - if (stream) { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - almp3_stop_mp3stream(stream); - almp3_destroy_mp3stream(stream); - } - stream = nullptr; - - if (buffer) - free(buffer); - buffer = nullptr; - - pack_fclose(in); - - state_ = SoundClipStopped; -} - -void MYMP3::seek(int pos) -{ - if (!is_playing()) { return; } - quit("Tried to seek an mp3stream"); -} - -int MYMP3::get_pos() -{ - return 0; // Return 0 to signify that Seek is not supported - // return almp3_get_pos_msecs_mp3stream (stream); -} - -int MYMP3::get_pos_ms() -{ - if (!is_playing()) { return -1; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - return almp3_get_pos_msecs_mp3stream(stream); -} - -int MYMP3::get_length_ms() -{ - if (!is_playing()) { return -1; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - return almp3_get_length_msecs_mp3stream(stream, filesize); -} - -int MYMP3::get_voice() -{ - if (!is_playing()) { return -1; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - AUDIOSTREAM *ast = almp3_get_audiostream_mp3stream(stream); - return (ast != nullptr ? ast->voice : -1); -} - -int MYMP3::get_sound_type() { - return MUS_MP3; -} - -int MYMP3::play() { - if (in == nullptr) { return 0; } - - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - if (almp3_play_mp3stream(stream, chunksize, (vol > 230) ? vol : vol + 20, panning) != ALMP3_OK) { - return 0; - } - } - - state_ = SoundClipPlaying; - - if (!psp_audio_multithreaded) - poll(); - - return 1; -} - -MYMP3::MYMP3() : SOUNDCLIP() { - stream = nullptr; - in = nullptr; - filesize = 0; - buffer = nullptr; - chunksize = 0; -} - -#endif // !NO_MP3_PLAYER \ No newline at end of file diff --git a/Engine/media/audio/clip_mymp3.h b/Engine/media/audio/clip_mymp3.h deleted file mode 100644 index 58448149d7c..00000000000 --- a/Engine/media/audio/clip_mymp3.h +++ /dev/null @@ -1,50 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYMP3_H -#define __AC_MYMP3_H - -#include "almp3.h" -#include "media/audio/soundclip.h" - -extern AGS::Engine::Mutex _mp3_mutex; - -struct MYMP3:public SOUNDCLIP -{ - ALMP3_MP3STREAM *stream; - PACKFILE *in; - size_t filesize; - char *buffer; - int chunksize; - - void poll() override; - void set_volume(int newvol) override; - void set_speed(int new_speed) override; - void destroy() override; - void seek(int pos) override; - int get_pos() override; - int get_pos_ms() override; - int get_length_ms() override; - int get_sound_type() override; - int play() override; - MYMP3(); - -protected: - int get_voice() override; - void adjust_volume() override; -private: - void adjust_stream(); -}; - -#endif // __AC_MYMP3_H \ No newline at end of file diff --git a/Engine/media/audio/clip_myogg.cpp b/Engine/media/audio/clip_myogg.cpp deleted file mode 100644 index da16c94162a..00000000000 --- a/Engine/media/audio/clip_myogg.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" -#include "media/audio/clip_myogg.h" -#include "media/audio/audiointernaldefs.h" -#include "ac/common.h" // quit() -#include "ac/asset_helper.h" -#include "util/mutex_lock.h" - -#include "platform/base/agsplatformdriver.h" - -extern "C" { - extern int alogg_is_end_of_oggstream(ALOGG_OGGSTREAM *ogg); - extern int alogg_is_end_of_ogg(ALOGG_OGG *ogg); - extern int alogg_get_ogg_freq(ALOGG_OGG *ogg); - extern int alogg_get_ogg_stereo(ALOGG_OGG *ogg); -} - -void MYOGG::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - AGS_PACKFILE_OBJ* obj = (AGS_PACKFILE_OBJ*)in->userdata; - if (obj->remains > 0) - { - // update the buffer - char *tempbuf = (char *)alogg_get_oggstream_buffer(stream); - if (tempbuf != nullptr) - { - int free_val = -1; - if (chunksize >= obj->remains) - { - chunksize = obj->remains; - free_val = chunksize; - } - pack_fread(tempbuf, chunksize, in); - alogg_free_oggstream_buffer(stream, free_val); - } - } - - int ret = alogg_poll_oggstream(stream); - if (ret == ALOGG_OK || ret == ALOGG_POLL_BUFFERUNDERRUN) - get_pos_ms(); // call this to keep the last_but_one stuff up to date - else { - // finished playing or error - state_ = SoundClipStopped; - } -} - -void MYOGG::adjust_stream() -{ - if (!is_playing()) { return; } - alogg_adjust_oggstream(stream, get_final_volume(), panning, speed); -} - -void MYOGG::adjust_volume() -{ - adjust_stream(); -} - -void MYOGG::set_volume(int newvol) -{ - // boost MP3 volume - newvol += 20; - if (newvol > 255) - newvol = 255; - vol = newvol; - adjust_stream(); -} - -void MYOGG::set_speed(int new_speed) -{ - speed = new_speed; - adjust_stream(); -} - -void MYOGG::destroy() -{ - if (stream) { - alogg_stop_oggstream(stream); - alogg_destroy_oggstream(stream); - } - stream = nullptr; - - if (buffer) - free(buffer); - buffer = nullptr; - - pack_fclose(in); - - state_ = SoundClipStopped; -} - -void MYOGG::seek(int pos) -{ - if (!is_playing()) { return; } - quit("Attempted to seek an oggstream; operation not permitted"); -} - -int MYOGG::get_pos() -{ - return 0; -} - -int MYOGG::get_pos_ms() -{ - // Unfortunately the alogg_get_pos_msecs_oggstream function - // returns the ms offset that was last decoded, so it's always - // ahead of the actual playback. Therefore we have this - // hideous hack below to sort it out. - if ((!is_playing()) || (!alogg_is_playing_oggstream(stream))) - return 0; - - AUDIOSTREAM *str = alogg_get_audiostream_oggstream(stream); - long offs = (voice_get_position(str->voice) * 1000) / str->samp->freq; - - if (last_ms_offs != alogg_get_pos_msecs_oggstream(stream)) { - last_but_one_but_one = last_but_one; - last_but_one = last_ms_offs; - last_ms_offs = alogg_get_pos_msecs_oggstream(stream); - } - - // just about to switch buffers - if (offs < 0) - return last_but_one; - - int end_of_stream = alogg_is_end_of_oggstream(stream); - - if ((str->active == 1) && (last_but_one_but_one > 0) && (str->locked == nullptr)) { - switch (end_of_stream) { -case 0: -case 2: - offs -= (last_but_one - last_but_one_but_one); - break; -case 1: - offs -= (last_but_one - last_but_one_but_one); - break; - } - } - - if (end_of_stream == 1) { - - return offs + last_but_one; - } - - return offs + last_but_one_but_one; -} - -int MYOGG::get_length_ms() -{ // streamed OGG is variable bitrate so we don't know - return 0; -} - -int MYOGG::get_voice() -{ - if (!is_playing()) { return -1; } - - AUDIOSTREAM *ast = alogg_get_audiostream_oggstream(stream); - if (ast) - return ast->voice; - return -1; -} - -int MYOGG::get_sound_type() { - return MUS_OGG; -} - -int MYOGG::play() { - if (in == nullptr) { return 0; } - - if (alogg_play_oggstream(stream, MP3CHUNKSIZE, (vol > 230) ? vol : vol + 20, panning) != ALOGG_OK) { - return 0; - } - - state_ = SoundClipPlaying; - - if (!psp_audio_multithreaded) - poll(); - - return 1; -} - -MYOGG::MYOGG() : SOUNDCLIP() { - stream = nullptr; - in = nullptr; - buffer = nullptr; - chunksize = 0; - last_but_one_but_one = 0; - last_but_one = 0; - last_ms_offs = 0; -} diff --git a/Engine/media/audio/clip_myogg.h b/Engine/media/audio/clip_myogg.h deleted file mode 100644 index 093920476af..00000000000 --- a/Engine/media/audio/clip_myogg.h +++ /dev/null @@ -1,60 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYOGG_H -#define __AC_MYOGG_H - -#include "alogg.h" -#include "media/audio/soundclip.h" - -struct MYOGG:public SOUNDCLIP -{ - ALOGG_OGGSTREAM *stream; - PACKFILE *in; - char *buffer; - int chunksize; - - int last_but_one_but_one; - int last_but_one; - int last_ms_offs; - - void poll() override; - - void set_volume(int newvol) override; - void set_speed(int new_speed) override; - - void destroy() override; - - void seek(int pos) override; - - int get_pos() override; - - int get_pos_ms() override; - - int get_length_ms() override; - - int get_sound_type() override; - - int play() override; - - MYOGG(); - -protected: - int get_voice() override; - void adjust_volume() override; -private: - void adjust_stream(); -}; - -#endif // __AC_MYOGG_H \ No newline at end of file diff --git a/Engine/media/audio/clip_mystaticmp3.cpp b/Engine/media/audio/clip_mystaticmp3.cpp deleted file mode 100644 index 1c0c0c46bcc..00000000000 --- a/Engine/media/audio/clip_mystaticmp3.cpp +++ /dev/null @@ -1,156 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" - -#ifndef NO_MP3_PLAYER - -#include "media/audio/clip_mystaticmp3.h" -#include "media/audio/audiointernaldefs.h" -#include "media/audio/soundcache.h" -#include "util/mutex_lock.h" - -#include "platform/base/agsplatformdriver.h" - -extern int our_eip; - -// ALMP3 functions are not reentrant! This mutex should be locked before calling any -// of the mp3 functions and unlocked afterwards. -AGS::Engine::Mutex _mp3_mutex; - -void MYSTATICMP3::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - int oldeip = our_eip; - our_eip = 5997; - - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - int result = almp3_poll_mp3(tune); - - if (result == ALMP3_POLL_PLAYJUSTFINISHED) - { - if (!repeat) - { - state_ = SoundClipStopped; - } - } - our_eip = oldeip; -} - -void MYSTATICMP3::adjust_stream() -{ - if (!is_playing()) { return; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - almp3_adjust_mp3(tune, get_final_volume(), panning, speed, repeat); -} - -void MYSTATICMP3::adjust_volume() -{ - adjust_stream(); -} - -void MYSTATICMP3::set_volume(int newvol) -{ - vol = newvol; - adjust_stream(); -} - -void MYSTATICMP3::set_speed(int new_speed) -{ - speed = new_speed; - adjust_stream(); -} - -void MYSTATICMP3::destroy() -{ - if (tune) { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - almp3_stop_mp3(tune); - almp3_destroy_mp3(tune); - } - tune = nullptr; - - if (mp3buffer) { - sound_cache_free(mp3buffer, false); - } - mp3buffer = nullptr; - - state_ = SoundClipStopped; -} - -void MYSTATICMP3::seek(int pos) -{ - if (!is_playing()) { return; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - almp3_seek_abs_msecs_mp3(tune, pos); -} - -int MYSTATICMP3::get_pos() -{ - if (!is_playing()) { return -1; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - return almp3_get_pos_msecs_mp3(tune); -} - -int MYSTATICMP3::get_pos_ms() -{ - int result = get_pos(); - return result; -} - -int MYSTATICMP3::get_length_ms() -{ - if (tune == nullptr) { return -1; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - return almp3_get_length_msecs_mp3(tune); -} - -int MYSTATICMP3::get_voice() -{ - if (!is_playing()) { return -1; } - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - AUDIOSTREAM *ast = almp3_get_audiostream_mp3(tune); - return (ast != nullptr ? ast->voice : -1); -} - -int MYSTATICMP3::get_sound_type() { - return MUS_MP3; -} - -int MYSTATICMP3::play() { - if (tune == nullptr) { return 0; } - - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - int result = almp3_play_ex_mp3(tune, 16384, vol, panning, 1000, repeat); - if (result != ALMP3_OK) { - return 0; - } - } - - state_ = SoundClipPlaying; - - if (!psp_audio_multithreaded) - poll(); - - return 1; -} - -MYSTATICMP3::MYSTATICMP3() : SOUNDCLIP() { - tune = nullptr; - mp3buffer = nullptr; -} - -#endif // !NO_MP3_PLAYER diff --git a/Engine/media/audio/clip_mystaticmp3.h b/Engine/media/audio/clip_mystaticmp3.h deleted file mode 100644 index 20f79e4711d..00000000000 --- a/Engine/media/audio/clip_mystaticmp3.h +++ /dev/null @@ -1,57 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYSTATICMP3_H -#define __AC_MYSTATICMP3_H - -#include "almp3.h" -#include "media/audio/soundclip.h" - -extern AGS::Engine::Mutex _mp3_mutex; - -// pre-loaded (non-streaming) MP3 file -struct MYSTATICMP3:public SOUNDCLIP -{ - ALMP3_MP3 *tune; - char *mp3buffer; - - void poll() override; - - void set_volume(int newvol) override; - void set_speed(int new_speed) override; - - void destroy() override; - - void seek(int pos) override; - - int get_pos() override; - - int get_pos_ms() override; - - int get_length_ms() override; - - int get_sound_type() override; - - int play() override; - - MYSTATICMP3(); - -protected: - int get_voice() override; - void adjust_volume() override; -private: - void adjust_stream(); -}; - -#endif // __AC_MYSTATICMP3_H diff --git a/Engine/media/audio/clip_mystaticogg.cpp b/Engine/media/audio/clip_mystaticogg.cpp deleted file mode 100644 index 5a744e499fd..00000000000 --- a/Engine/media/audio/clip_mystaticogg.cpp +++ /dev/null @@ -1,205 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "media/audio/audiodefines.h" -#include "media/audio/clip_mystaticogg.h" -#include "media/audio/audiointernaldefs.h" -#include "media/audio/soundcache.h" -#include "util/mutex_lock.h" - -#include "platform/base/agsplatformdriver.h" - -extern "C" { - extern int alogg_is_end_of_oggstream(ALOGG_OGGSTREAM *ogg); - extern int alogg_is_end_of_ogg(ALOGG_OGG *ogg); - extern int alogg_get_ogg_freq(ALOGG_OGG *ogg); - extern int alogg_get_ogg_stereo(ALOGG_OGG *ogg); -} - -extern int use_extra_sound_offset; // defined in ac.cpp - -void MYSTATICOGG::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - if (alogg_poll_ogg(tune) == ALOGG_POLL_PLAYJUSTFINISHED) { - if (!repeat) - { - state_ = SoundClipStopped; - } - } - else get_pos(); // call this to keep the last_but_one stuff up to date -} - -void MYSTATICOGG::adjust_stream() -{ - if (!is_playing()) { return; } - alogg_adjust_ogg(tune, get_final_volume(), panning, speed, repeat); -} - -void MYSTATICOGG::adjust_volume() -{ - adjust_stream(); -} - -void MYSTATICOGG::set_volume(int newvol) -{ - vol = newvol; - adjust_stream(); -} - -void MYSTATICOGG::set_speed(int new_speed) -{ - speed = new_speed; - adjust_stream(); -} - -void MYSTATICOGG::destroy() -{ - if (tune) { - alogg_stop_ogg(tune); - alogg_destroy_ogg(tune); - } - tune = nullptr; - - if (mp3buffer) { - sound_cache_free(mp3buffer, false); - } - mp3buffer = nullptr; - - state_ = SoundClipStopped; -} - -void MYSTATICOGG::seek(int pos) -{ - if (!is_playing()) { return; } - - // we stop and restart it because otherwise the buffer finishes - // playing first and the seek isn't quite accurate - alogg_stop_ogg(tune); - state_ = SoundClipInitial; - play_from(pos); -} - -int MYSTATICOGG::get_pos() -{ - if (!is_playing()) { return -1; } - return get_pos_ms(); -} - -int MYSTATICOGG::get_pos_ms() -{ - if (!is_playing()) { return -1; } - - // Unfortunately the alogg_get_pos_msecs function - // returns the ms offset that was last decoded, so it's always - // ahead of the actual playback. Therefore we have this - // hideous hack below to sort it out. - if (!alogg_is_playing_ogg(tune)) - return 0; - - AUDIOSTREAM *str = alogg_get_audiostream_ogg(tune); - long offs = (voice_get_position(str->voice) * 1000) / str->samp->freq; - - if (last_ms_offs != alogg_get_pos_msecs_ogg(tune)) { - last_but_one_but_one = last_but_one; - last_but_one = last_ms_offs; - last_ms_offs = alogg_get_pos_msecs_ogg(tune); - } - - // just about to switch buffers - if (offs < 0) - return last_but_one; - - int end_of_stream = alogg_is_end_of_ogg(tune); - - if ((str->active == 1) && (last_but_one_but_one > 0) && (str->locked == nullptr)) { - switch (end_of_stream) { -case 0: -case 2: - offs -= (last_but_one - last_but_one_but_one); - break; -case 1: - offs -= (last_but_one - last_but_one_but_one); - break; - } - } - - if (end_of_stream == 1) { - return offs + last_but_one + extraOffset; - } - - return offs + last_but_one_but_one + extraOffset; -} - -int MYSTATICOGG::get_length_ms() -{ - if (tune == nullptr) { return -1; } - return alogg_get_length_msecs_ogg(tune); -} - -int MYSTATICOGG::get_voice() -{ - if (!is_playing()) { return -1; } - AUDIOSTREAM *ast = alogg_get_audiostream_ogg(tune); - if (ast) - return ast->voice; - return -1; -} - -int MYSTATICOGG::get_sound_type() { - return MUS_OGG; -} - -int MYSTATICOGG::play_from(int position) -{ - if (tune == nullptr) { return 0; } - - if (use_extra_sound_offset) - extraOffset = ((16384 / (alogg_get_wave_is_stereo_ogg(tune) ? 2 : 1)) * 1000) / alogg_get_wave_freq_ogg(tune); - else - extraOffset = 0; - - if (alogg_play_ex_ogg(tune, 16384, vol, panning, 1000, repeat) != ALOGG_OK) { - return 0; - } - - last_ms_offs = position; - last_but_one = position; - last_but_one_but_one = position; - - if (position > 0) - alogg_seek_abs_msecs_ogg(tune, position); - - state_ = SoundClipPlaying; - - if (!psp_audio_multithreaded) - poll(); - - return 1; -} - -int MYSTATICOGG::play() { - return play_from(0); -} - -MYSTATICOGG::MYSTATICOGG() : SOUNDCLIP() { - tune = nullptr; - mp3buffer = nullptr; - mp3buffersize = 0; - extraOffset = 0; - last_but_one = 0; - last_ms_offs = 0; - last_but_one_but_one = 0; -} diff --git a/Engine/media/audio/clip_mystaticogg.h b/Engine/media/audio/clip_mystaticogg.h deleted file mode 100644 index a57250857dd..00000000000 --- a/Engine/media/audio/clip_mystaticogg.h +++ /dev/null @@ -1,63 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYSTATICOGG_H -#define __AC_MYSTATICOGG_H - -#include "alogg.h" -#include "media/audio/soundclip.h" - -// pre-loaded (non-streaming) OGG file -struct MYSTATICOGG:public SOUNDCLIP -{ - ALOGG_OGG *tune; - char *mp3buffer; - int mp3buffersize; - int extraOffset; - - int last_but_one_but_one; - int last_but_one; - int last_ms_offs; - - void poll() override; - - void set_volume(int newvol) override; - void set_speed(int new_speed) override; - - void destroy() override; - - void seek(int pos) override; - - int get_pos() override; - - int get_pos_ms() override; - - int get_length_ms() override; - - int get_sound_type() override; - - int play_from(int position) override; - - int play() override; - - MYSTATICOGG(); - -protected: - int get_voice() override; - void adjust_volume() override; -private: - void adjust_stream(); -}; - -#endif // __AC_MYSTATICOGG_H diff --git a/Engine/media/audio/clip_mywave.cpp b/Engine/media/audio/clip_mywave.cpp deleted file mode 100644 index 4ab79f06136..00000000000 --- a/Engine/media/audio/clip_mywave.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "util/wgt2allg.h" -#include "media/audio/audiodefines.h" -#include "media/audio/clip_mywave.h" -#include "media/audio/audiointernaldefs.h" -#include "media/audio/soundcache.h" -#include "util/mutex_lock.h" - -#include "platform/base/agsplatformdriver.h" - -void MYWAVE::poll() -{ - if (state_ != SoundClipPlaying) { return; } - - if (voice_get_position(voice) < 0) - { - state_ = SoundClipStopped; - } -} - -void MYWAVE::adjust_volume() -{ - if (!is_playing()) { return; } - if (voice < 0) { return; } - voice_set_volume(voice, get_final_volume()); -} - -void MYWAVE::set_volume(int newvol) -{ - vol = newvol; - adjust_volume(); -} - -void MYWAVE::destroy() -{ - // Stop sound and decrease reference count. - if (wave) { - stop_sample(wave); - sound_cache_free((char*)wave, true); - } - wave = nullptr; - - state_ = SoundClipStopped; -} - -void MYWAVE::seek(int pos) -{ - if (!is_playing()) { return; } - voice_set_position(voice, pos); -} - -int MYWAVE::get_pos() -{ - if (!is_playing()) { return -1; } - return voice_get_position(voice); -} - -int MYWAVE::get_pos_ms() -{ - // convert the offset in samples into the offset in ms - //return ((1000000 / voice_get_frequency(voice)) * voice_get_position(voice)) / 1000; - - if (voice_get_frequency(voice) < 100) - return 0; - // (number of samples / (samples per second / 100)) * 10 = ms - return (voice_get_position(voice) / (voice_get_frequency(voice) / 100)) * 10; -} - -int MYWAVE::get_length_ms() -{ - if (wave == nullptr) { return -1; } - if (wave->freq < 100) - return 0; - return (wave->len / (wave->freq / 100)) * 10; -} - -int MYWAVE::get_voice() -{ - if (!is_playing()) { return -1; } - return voice; -} - -int MYWAVE::get_sound_type() { - return MUS_WAVE; -} - -int MYWAVE::play() { - if (wave == nullptr) { return 0; } - - voice = play_sample(wave, vol, panning, 1000, repeat); - if (voice < 0) { - return 0; - } - - state_ = SoundClipPlaying; - - return 1; -} - -MYWAVE::MYWAVE() : SOUNDCLIP() { - wave = nullptr; - voice = -1; -} diff --git a/Engine/media/audio/clip_mywave.h b/Engine/media/audio/clip_mywave.h deleted file mode 100644 index b78c5ed29b6..00000000000 --- a/Engine/media/audio/clip_mywave.h +++ /dev/null @@ -1,50 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_MYWAVE_H -#define __AC_MYWAVE_H - -#include "media/audio/soundclip.h" - -// My new MP3STREAM wrapper -struct MYWAVE:public SOUNDCLIP -{ - SAMPLE *wave; - int voice; - - void poll() override; - - void set_volume(int new_speed) override; - - void destroy() override; - - void seek(int pos) override; - - int get_pos() override; - int get_pos_ms() override; - - int get_length_ms() override; - - int get_sound_type() override; - - int play() override; - - MYWAVE(); - -protected: - int get_voice() override; - void adjust_volume() override; -}; - -#endif // __AC_MYWAVE_H \ No newline at end of file diff --git a/Engine/media/audio/clip_openal.h b/Engine/media/audio/clip_openal.h index f4379ca1588..42e74cfd919 100644 --- a/Engine/media/audio/clip_openal.h +++ b/Engine/media/audio/clip_openal.h @@ -60,7 +60,6 @@ struct OPENAL_SOUNDCLIP final : public SOUNDCLIP protected: void adjust_volume() override; - int get_voice() override { return 0; } // only for Allegro-specific implementations private: void configure_slot(); diff --git a/Engine/media/audio/sound.cpp b/Engine/media/audio/sound.cpp index 4bc3348a397..c1cacddbb7f 100644 --- a/Engine/media/audio/sound.cpp +++ b/Engine/media/audio/sound.cpp @@ -11,346 +11,41 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= -// -// ACSOUND - AGS sound system wrapper -// -//============================================================================= - -#include // for toupper - -#include "core/platform.h" -#include "util/wgt2allg.h" -#include "ac/file.h" -#include "media/audio/audiodefines.h" #include "media/audio/sound.h" -#include "media/audio/audiointernaldefs.h" -#include "media/audio/clip_mywave.h" -#ifndef NO_MP3_PLAYER -#include "media/audio/clip_mymp3.h" -#include "media/audio/clip_mystaticmp3.h" -#endif -#include "media/audio/clip_myogg.h" -#include "media/audio/clip_mystaticogg.h" -#include "media/audio/clip_mymidi.h" -#ifdef JGMOD_MOD_PLAYER -#include "media/audio/clip_myjgmod.h" -#endif -#ifdef DUMB_MOD_PLAYER -#include "media/audio/clip_mydumbmod.h" -#endif -#include "media/audio/soundcache.h" -#include "util/mutex_lock.h" - -#if defined JGMOD_MOD_PLAYER && defined DUMB_MOD_PLAYER -#error JGMOD_MOD_PLAYER and DUMB_MOD_PLAYER macros cannot be defined at the same time. -#endif - -#if !defined PSP_NO_MOD_PLAYBACK && !defined JGMOD_MOD_PLAYER && !defined DUMB_MOD_PLAYER -#error Either JGMOD_MOD_PLAYER or DUMB_MOD_PLAYER should be defined. -#endif - -extern "C" -{ -// Load MIDI from PACKFILE stream -MIDI *load_midi_pf(PACKFILE *pf); -} - +#include "media/audio/clip_openal.h" -int use_extra_sound_offset = 0; - - - -MYWAVE *thiswave; SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, int loop) { - // Load via soundcache. - size_t dummy; - SAMPLE *new_sample = (SAMPLE*)get_cached_sound(asset_name, true, dummy); - - if (new_sample == nullptr) - return nullptr; - - thiswave = new MYWAVE(); - thiswave->wave = new_sample; - thiswave->vol = voll; - thiswave->repeat = (loop != 0); - - return thiswave; + return my_load_openal(asset_name, "WAV", voll, loop); } -PACKFILE *mp3in; - -#ifndef NO_MP3_PLAYER - -MYMP3 *thistune; SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, int voll) { - size_t asset_size; - mp3in = PackfileFromAsset(asset_name, asset_size); - if (mp3in == nullptr) - return nullptr; - - char *tmpbuffer = (char *)malloc(MP3CHUNKSIZE); - if (tmpbuffer == nullptr) { - pack_fclose(mp3in); - return nullptr; - } - thistune = new MYMP3(); - thistune->in = mp3in; - thistune->chunksize = MP3CHUNKSIZE; - thistune->filesize = asset_size; - thistune->vol = voll; - - if (thistune->chunksize > thistune->filesize) - thistune->chunksize = thistune->filesize; - - pack_fread(tmpbuffer, thistune->chunksize, mp3in); - - thistune->buffer = (char *)tmpbuffer; - - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - thistune->stream = almp3_create_mp3stream(tmpbuffer, thistune->chunksize, (thistune->filesize < 1)); - } - - if (thistune->stream == nullptr) { - free(tmpbuffer); - pack_fclose(mp3in); - delete thistune; - return nullptr; - } - - return thistune; + return my_load_openal(asset_name, "MP3", voll, false); } - - -MYSTATICMP3 *thismp3; SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop) { - // Load via soundcache. - size_t muslen = 0; - char* mp3buffer = get_cached_sound(asset_name, false, muslen); - if (mp3buffer == nullptr) - return nullptr; - - // now, create an MP3 structure for it - thismp3 = new MYSTATICMP3(); - if (thismp3 == nullptr) { - free(mp3buffer); - return nullptr; - } - thismp3->vol = voll; - thismp3->mp3buffer = nullptr; - thismp3->repeat = loop; - - { - AGS::Engine::MutexLock _lockMp3(_mp3_mutex); - thismp3->tune = almp3_create_mp3(mp3buffer, muslen); - } - - if (thismp3->tune == nullptr) { - free(mp3buffer); - delete thismp3; - return nullptr; - } - - thismp3->mp3buffer = mp3buffer; - - return thismp3; + return my_load_openal(asset_name, "MP3", voll, loop); } -#else // NO_MP3_PLAYER - -SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, int voll) -{ - return NULL; -} - -SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop) -{ - return NULL; -} - -#endif // NO_MP3_PLAYER - - - -MYSTATICOGG *thissogg; SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, int voll, bool loop) { - // Load via soundcache. - size_t muslen = 0; - char* mp3buffer = get_cached_sound(asset_name, false, muslen); - if (mp3buffer == nullptr) - return nullptr; - - // now, create an OGG structure for it - thissogg = new MYSTATICOGG(); - thissogg->vol = voll; - thissogg->repeat = loop; - thissogg->mp3buffer = mp3buffer; - thissogg->mp3buffersize = muslen; - - thissogg->tune = alogg_create_ogg_from_buffer(mp3buffer, muslen); - - if (thissogg->tune == nullptr) { - thissogg->destroy(); - delete thissogg; - return nullptr; - } - - return thissogg; + return my_load_openal(asset_name, "OGG", voll, loop); } -MYOGG *thisogg; SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll) { - size_t asset_size; - mp3in = PackfileFromAsset(asset_name, asset_size); - if (mp3in == nullptr) - return nullptr; - - char *tmpbuffer = (char *)malloc(MP3CHUNKSIZE); - if (tmpbuffer == nullptr) { - pack_fclose(mp3in); - return nullptr; - } - - thisogg = new MYOGG(); - thisogg->in = mp3in; - thisogg->vol = voll; - thisogg->chunksize = MP3CHUNKSIZE; - thisogg->last_but_one = 0; - thisogg->last_ms_offs = 0; - thisogg->last_but_one_but_one = 0; - - if (thisogg->chunksize > asset_size) - thisogg->chunksize = asset_size; - - pack_fread(tmpbuffer, thisogg->chunksize, mp3in); - - thisogg->buffer = (char *)tmpbuffer; - thisogg->stream = alogg_create_oggstream(tmpbuffer, thisogg->chunksize, (asset_size < 1)); - - if (thisogg->stream == nullptr) { - free(tmpbuffer); - pack_fclose(mp3in); - delete thisogg; - return nullptr; - } - - return thisogg; + return my_load_openal(asset_name, "OGG", voll, false); } - - -MYMIDI *thismidi; SOUNDCLIP *my_load_midi(const AssetPath &asset_name, int repet) { - // The first a midi is played, preload all patches. - if (!thismidi && psp_midi_preload_patches) - load_midi_patches(); - - size_t asset_size; - PACKFILE *pf = PackfileFromAsset(asset_name, asset_size); - if (!pf) - return nullptr; - - MIDI* midiPtr = load_midi_pf(pf); - pack_fclose(pf); - - if (midiPtr == nullptr) - return nullptr; - - thismidi = new MYMIDI(); - thismidi->tune = midiPtr; - thismidi->repeat = (repet != 0); - - return thismidi; -} - - -#ifdef JGMOD_MOD_PLAYER - -MYMOD *thismod = NULL; -SOUNDCLIP *my_load_mod(const char *filname, int repet) -{ - - JGMOD *modPtr = load_mod((char *)filname); - if (modPtr == NULL) - return NULL; - - thismod = new MYMOD(); - thismod->tune = modPtr; - thismod->repeat = (repet != 0); - - return thismod; -} - -int init_mod_player(int numVoices) { - return install_mod(numVoices); -} - -void remove_mod_player() { - remove_mod(); + return my_load_openal(asset_name, "MIDI", 0, repet); } -//#endif // JGMOD_MOD_PLAYER -#elif defined DUMB_MOD_PLAYER - -MYMOD *thismod = nullptr; SOUNDCLIP *my_load_mod(const AssetPath &asset_name, int repet) { - size_t asset_size; - DUMBFILE *df = DUMBfileFromAsset(asset_name, asset_size); - if (!df) - return nullptr; - - DUH *modPtr = nullptr; - // determine the file extension - const char *lastDot = strrchr(asset_name.second, '.'); - if (lastDot == nullptr) - { - dumbfile_close(df); - return nullptr; - } - // get the first char of the extensin - int charAfterDot = toupper(lastDot[1]); - - // use the appropriate loader - if (charAfterDot == 'I') { - modPtr = dumb_read_it(df); - } - else if (charAfterDot == 'X') { - modPtr = dumb_read_xm(df); - } - else if (charAfterDot == 'S') { - modPtr = dumb_read_s3m(df); - } - else if (charAfterDot == 'M') { - modPtr = dumb_read_mod(df); - } - - dumbfile_close(df); - if (modPtr == nullptr) - return nullptr; - - thismod = new MYMOD(); - thismod->tune = modPtr; - thismod->vol = 255; - thismod->repeat = (repet != 0); - - return thismod; -} - -int init_mod_player(int numVoices) { - dumb_register_packfiles(); - return 0; -} - -void remove_mod_player() { - dumb_exit(); + return my_load_openal(asset_name, "MOD", 0, repet); } -#endif // DUMB_MOD_PLAYER diff --git a/Engine/media/audio/sound.h b/Engine/media/audio/sound.h index 2a644159fb7..01e77e910e5 100644 --- a/Engine/media/audio/sound.h +++ b/Engine/media/audio/sound.h @@ -12,7 +12,7 @@ // //============================================================================= // -// ACSOUND - AGS sound system wrapper +// SOUNDCLIP factory methods. // //============================================================================= @@ -30,6 +30,4 @@ SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll); SOUNDCLIP *my_load_midi(const AssetPath &asset_name, int repet); SOUNDCLIP *my_load_mod(const AssetPath &asset_name, int repet); -extern int use_extra_sound_offset; - #endif // __AC_SOUND_H diff --git a/Engine/media/audio/soundcache.cpp b/Engine/media/audio/soundcache.cpp deleted file mode 100644 index 3f59917c120..00000000000 --- a/Engine/media/audio/soundcache.cpp +++ /dev/null @@ -1,234 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include -#include -#include "ac/file.h" -#include "util/wgt2allg.h" -#include "media/audio/soundcache.h" -#include "media/audio/audiointernaldefs.h" -#include "util/mutex.h" -#include "util/mutex_lock.h" -#include "util/string.h" -#include "debug/out.h" - -using namespace Common; - -sound_cache_entry_t* sound_cache_entries = nullptr; -unsigned int sound_cache_counter = 0; - -AGS::Engine::Mutex _sound_cache_mutex; - - -void clear_sound_cache() -{ - AGS::Engine::MutexLock _lock(_sound_cache_mutex); - - if (sound_cache_entries) - { - int i; - for (i = 0; i < psp_audio_cachesize; i++) - { - if (sound_cache_entries[i].data) - { - free(sound_cache_entries[i].data); - sound_cache_entries[i].data = nullptr; - free(sound_cache_entries[i].file_name); - sound_cache_entries[i].file_name = nullptr; - sound_cache_entries[i].reference = 0; - } - } - } - else - { - sound_cache_entries = (sound_cache_entry_t*)malloc(psp_audio_cachesize * sizeof(sound_cache_entry_t)); - memset(sound_cache_entries, 0, psp_audio_cachesize * sizeof(sound_cache_entry_t)); - } -} - -void sound_cache_free(char* buffer, bool is_wave) -{ - AGS::Engine::MutexLock _lock(_sound_cache_mutex); - -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("sound_cache_free(%p %d)\n", buffer, (unsigned int)is_wave); -#endif - int i; - for (i = 0; i < psp_audio_cachesize; i++) - { - if (sound_cache_entries[i].data == buffer) - { - if (sound_cache_entries[i].reference > 0) - sound_cache_entries[i].reference--; - -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("..decreased reference count of slot %d to %d\n", i, sound_cache_entries[i].reference); -#endif - return; - } - } - -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("..freeing uncached sound\n"); -#endif - - // Sound is uncached - if (i == psp_audio_cachesize) - { - if (is_wave) - destroy_sample((SAMPLE*)buffer); - else - free(buffer); - } -} - - -char* get_cached_sound(const AssetPath &asset_name, bool is_wave, size_t &size) -{ - AGS::Engine::MutexLock _lock(_sound_cache_mutex); - -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("get_cached_sound(%s %d)\n", asset_name.first.GetCStr(), (unsigned int)is_wave); -#endif - - size = 0; - - int i; - for (i = 0; i < psp_audio_cachesize; i++) - { - if (sound_cache_entries[i].data == nullptr) - continue; - - if (strcmp(asset_name.second, sound_cache_entries[i].file_name) == 0) - { -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("..found in slot %d\n", i); -#endif - sound_cache_entries[i].reference++; - sound_cache_entries[i].last_used = sound_cache_counter++; - size = sound_cache_entries[i].size; - - return sound_cache_entries[i].data; - } - } - - // Not found - PACKFILE *mp3in = nullptr; - SAMPLE* wave = nullptr; - - if (is_wave) - { - PACKFILE *wavin = PackfileFromAsset(asset_name, size); - if (wavin != nullptr) - { - wave = load_wav_pf(wavin); - pack_fclose(wavin); - } - } - else - { - mp3in = PackfileFromAsset(asset_name, size); - if (mp3in == nullptr) - { - return nullptr; - } - } - - // Find free slot - for (i = 0; i < psp_audio_cachesize; i++) - { - if (sound_cache_entries[i].data == nullptr) - break; - } - - // No free slot? - if (i == psp_audio_cachesize) - { - unsigned int oldest = sound_cache_counter; - int index = -1; - - for (i = 0; i < psp_audio_cachesize; i++) - { - if (sound_cache_entries[i].reference == 0) - { - if (sound_cache_entries[i].last_used < oldest) - { - oldest = sound_cache_entries[i].last_used; - index = i; - } - } - } - - i = index; - } - - // Load new file - char* newdata; - - if (is_wave) - { - size = 0; // ??? CHECKME - newdata = (char*)wave; - } - else - { - newdata = (char *)malloc(size); - - if (newdata == nullptr) - { - pack_fclose(mp3in); - return nullptr; - } - - pack_fread(newdata, size, mp3in); - pack_fclose(mp3in); - } - - if (i == -1) - { - // No cache slot empty, return uncached data -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("..loading uncached\n"); -#endif - return newdata; - } - else - { - // Add to cache, free old sound first -#ifdef SOUND_CACHE_DEBUG - Debug::Printf("..loading cached in slot %d\n", i); -#endif - - if (sound_cache_entries[i].data) { - if (sound_cache_entries[i].is_wave) - destroy_sample((SAMPLE*)sound_cache_entries[i].data); - else - free(sound_cache_entries[i].data); - } - - sound_cache_entries[i].size = size; - sound_cache_entries[i].data = newdata; - - if (sound_cache_entries[i].file_name) - free(sound_cache_entries[i].file_name); - sound_cache_entries[i].file_name = (char*)malloc(strlen(asset_name.second) + 1); - strcpy(sound_cache_entries[i].file_name, asset_name.second); - sound_cache_entries[i].reference = 1; - sound_cache_entries[i].last_used = sound_cache_counter++; - sound_cache_entries[i].is_wave = is_wave; - - return sound_cache_entries[i].data; - } - -} diff --git a/Engine/media/audio/soundcache.h b/Engine/media/audio/soundcache.h deleted file mode 100644 index ebdb67c69a9..00000000000 --- a/Engine/media/audio/soundcache.h +++ /dev/null @@ -1,48 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_SOUNDCACHE_H -#define __AC_SOUNDCACHE_H - -#include "ac/asset_helper.h" - -// PSP: A simple sound cache. The size can be configured in the config file. -// The data rate while reading from disk on the PSP is usually between 500 to 900 kiB/s, -// caching the last used sound files therefore improves game performance. - -//#define SOUND_CACHE_DEBUG - -typedef struct -{ - char* file_name; - int number; - int free; - unsigned int last_used; - unsigned int size; - char* data; - int reference; - bool is_wave; -} sound_cache_entry_t; - -extern int psp_use_sound_cache; -extern int psp_sound_cache_max_size; -extern int psp_audio_cachesize; -extern int psp_midi_preload_patches; - -void clear_sound_cache(); -void sound_cache_free(char* buffer, bool is_wave); -char* get_cached_sound(const AssetPath &asset_name, bool is_wave, size_t &size); - - -#endif // __AC_SOUNDCACHE_H diff --git a/Engine/media/audio/soundclip.cpp b/Engine/media/audio/soundclip.cpp index 844eb0fa918..13484db5766 100644 --- a/Engine/media/audio/soundclip.cpp +++ b/Engine/media/audio/soundclip.cpp @@ -18,48 +18,7 @@ #include "media/audio/soundclip.h" #include "media/audio/audiointernaldefs.h" -int SOUNDCLIP::play_from(int position) -{ - int retVal = play(); - if ((retVal != 0) && (position > 0)) - { - seek(position); - } - return retVal; -} - -void SOUNDCLIP::set_panning(int newPanning) { - if (!is_playing()) { return; } - - int voice = get_voice(); - if (voice >= 0) { - voice_set_pan(voice, newPanning); - panning = newPanning; - } -} - -void SOUNDCLIP::pause() { - if (state_ != SoundClipPlaying) { return; } - - int voice = get_voice(); - if (voice >= 0) { - voice_stop(voice); - state_ = SoundClipPaused; - } -} - -void SOUNDCLIP::resume() { - if (state_ != SoundClipPaused) { return; } - - int voice = get_voice(); - if (voice >= 0) { - voice_start(voice); - state_ = SoundClipPlaying; - } -} - SOUNDCLIP::SOUNDCLIP() { - state_ = SoundClipInitial; priority = 50; panning = 128; panningAsPercentage = 0; diff --git a/Engine/media/audio/soundclip.h b/Engine/media/audio/soundclip.h index 3909ec47057..d48a3767343 100644 --- a/Engine/media/audio/soundclip.h +++ b/Engine/media/audio/soundclip.h @@ -21,17 +21,12 @@ #include "util/mutex.h" -// JJS: This is needed for the derieved classes -extern volatile int psp_audio_multithreaded; - // TODO: one of the biggest problems with sound clips currently is that it // provides several methods of applying volume, which may ignore or override // each other, and does not shape a consistent interface. // Improving this situation is only possible with massive refactory of // sound clip use, taking backwards-compatible audio system in account. -enum SoundClipState { SoundClipInitial, SoundClipPlaying, SoundClipPaused, SoundClipStopped }; - struct SOUNDCLIP { int priority; @@ -62,16 +57,15 @@ struct SOUNDCLIP virtual int get_length_ms() = 0; // return total track length in ms (or 0) virtual int get_sound_type() = 0; virtual int play() = 0; + virtual int play_from(int position) = 0; - virtual int play_from(int position); - - virtual void set_panning(int newPanning); - virtual void set_speed(int new_speed) { speed = new_speed; } + virtual void set_panning(int newPanning) = 0; + virtual void set_speed(int new_speed) = 0; - virtual void pause(); - virtual void resume(); + virtual void pause() = 0; + virtual void resume() = 0; - virtual bool is_playing() const { return state_ == SoundClipPlaying || state_ == SoundClipPaused; } + virtual bool is_playing() const = 0; // true if playing or paused. false if never played or stopped. inline int get_speed() const { @@ -145,19 +139,12 @@ struct SOUNDCLIP protected: - - SoundClipState state_; - // mute mode overrides the volume; if set, any volume assigned is stored // in properties, but not applied to playback itself bool muted; // speed of playback, in clip ms per real second - int speed; - - // Return the allegro voice number (or -1 if none) - // Used by generic pause/resume functions. - virtual int get_voice() = 0; + int speed; // helper function for calculating volume with applied modifiers inline int get_final_volume() const diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index 970611540d7..6fc7a92d3eb 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -230,7 +230,6 @@ void AGSPlatformDriver::Delay(int millis) { // don't allow it to check for debug messages, since this Delay() // call might be from within a debugger polling loop - update_polled_mp3(); now = AGS_Clock::now(); // update now } } diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index 8e3b91d6252..6efcfc43140 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -946,9 +946,6 @@ void AGSWin32::PlayVideo(const char *name, int skip, int flags) { useSound = false; } else { - // for some reason DirectSound can't be shared, so uninstall - // allegro sound before playing the video - shutdown_sound(); } bool isError = false; @@ -971,14 +968,6 @@ void AGSWin32::PlayVideo(const char *name, int skip, int flags) { game.options[OPT_ALWAYSSPCH] = oldalways; } - if (useSound) - { - // Restore sound system - install_sound(usetup.digicard,usetup.midicard,NULL); - if (usetup.mod_player) - init_mod_player(NUM_MOD_DIGI_VOICES); - } - set_palette_range(palette, 0, 255, 0); } diff --git a/Engine/plugin/agsplugin.cpp b/Engine/plugin/agsplugin.cpp index 240f0d14fcf..ed4586825dc 100644 --- a/Engine/plugin/agsplugin.cpp +++ b/Engine/plugin/agsplugin.cpp @@ -590,17 +590,15 @@ void IAGSEngine::PlaySoundChannel (int32 channel, int32 soundType, int32 volume, else if (soundType == PSND_OGGSTATIC) newcha = my_load_static_ogg (asset_name, volume, (loop != 0)); else if (soundType == PSND_MIDI) { - if (midi_pos >= 0) + if (play.silent_midi != 0 || current_music_type == MUS_MIDI) quit("!IAGSEngine::PlaySoundChannel: MIDI already in use"); newcha = my_load_midi (asset_name, loop); newcha->set_volume (volume); } -#ifndef PSP_NO_MOD_PLAYBACK else if (soundType == PSND_MOD) { newcha = my_load_mod (asset_name, loop); newcha->set_volume (volume); } -#endif else quit("!IAGSEngine::PlaySoundChannel: unknown sound type"); @@ -674,8 +672,6 @@ void IAGSEngine::DisableSound() { shutdown_sound(); usetup.digicard = DIGI_NONE; usetup.midicard = MIDI_NONE; - reserve_voices(0, 0); - install_sound(DIGI_NONE, MIDI_NONE, nullptr); } int IAGSEngine::CanRunScriptFunctionNow() { if (inside_script) diff --git a/Engine/script/script.cpp b/Engine/script/script.cpp index 40f3fb915f9..d5f77e190a2 100644 --- a/Engine/script/script.cpp +++ b/Engine/script/script.cpp @@ -211,7 +211,6 @@ int run_interaction_script(InteractionScripts *nint, int evnt, int chkAny, int i RuntimeScriptValue rval_null; - update_polled_mp3(); if ((strstr(evblockbasename,"character")!=nullptr) || (strstr(evblockbasename,"inventory")!=nullptr)) { // Character or Inventory (global script) QueueScriptFunction(kScInstGame, nint->ScriptFuncNames[evnt]); @@ -220,7 +219,6 @@ int run_interaction_script(InteractionScripts *nint, int evnt, int chkAny, int i // Other (room script) QueueScriptFunction(kScInstRoom, nint->ScriptFuncNames[evnt]); } - update_polled_mp3(); int retval = 0; // if the room changed within the action @@ -689,7 +687,6 @@ int run_interaction_commandlist (InteractionCommandList *nicl, int *timesrun, in { TempEip tempip(4001); RuntimeScriptValue rval_null; - update_polled_mp3(); if ((strstr(evblockbasename,"character")!=nullptr) || (strstr(evblockbasename,"inventory")!=nullptr)) { // Character or Inventory (global script) const char *torun = make_ts_func_name(evblockbasename,evblocknum,nicl->Cmds[i].Data[0].Value); @@ -701,7 +698,6 @@ int run_interaction_commandlist (InteractionCommandList *nicl, int *timesrun, in const char *torun = make_ts_func_name(evblockbasename,evblocknum,nicl->Cmds[i].Data[0].Value); QueueScriptFunction(kScInstRoom, torun); } - update_polled_mp3(); break; } case 2: // Add score (first time) diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index eeffde15c9b..b3211c97994 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -484,19 +484,10 @@ - - - - - - - - - @@ -779,20 +770,11 @@ - - - - - - - - - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index add45ef5a67..0ba99424beb 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -651,39 +651,12 @@ Source Files\media\audio - - Source Files\media\audio - - - Source Files\media\audio - - - Source Files\media\audio - - - Source Files\media\audio - - - Source Files\media\audio - - - Source Files\media\audio - - - Source Files\media\audio - - - Source Files\media\audio - Source Files\media\audio Source Files\media\audio - - Source Files\media\audio - Source Files\media\audio @@ -1571,39 +1544,12 @@ Header Files\media\audio - - Header Files\media\audio - - - Header Files\media\audio - - - Header Files\media\audio - - - Header Files\media\audio - - - Header Files\media\audio - - - Header Files\media\audio - - - Header Files\media\audio - - - Header Files\media\audio - Header Files\media\audio Header Files\media\audio - - Header Files\media\audio - Header Files\media\audio From f782e841a4ed29de19944426dd34b122dad706b4 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 1 Oct 2020 04:56:15 +0300 Subject: [PATCH 05/41] OpenALDecoder: factor out PollBuffers and fill some data before start There's some kind of race condition with MojoAL which may try to mix-in our new clip before it gets properly initialized with data. When it does so, it drops the clip out of the slot. Here we prevent this by polling at least some data in before calling alSourcePlay. --- Engine/media/audio/openaldecoder.cpp | 101 ++++++++++++++------------- Engine/media/audio/openaldecoder.h | 1 + 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/Engine/media/audio/openaldecoder.cpp b/Engine/media/audio/openaldecoder.cpp index c96183c5883..6e93f23d0da 100644 --- a/Engine/media/audio/openaldecoder.cpp +++ b/Engine/media/audio/openaldecoder.cpp @@ -108,6 +108,55 @@ void OpenALDecoder::DecoderUnqueueProcessedBuffers() } } +void OpenALDecoder::PollBuffers() +{ + // buffer management + DecoderUnqueueProcessedBuffers(); + + // generate extra buffers if none are free + if (g_oaldec.freeBuffers.size() < SourceMinimumQueuedBuffers) { + std::array genbufs; + alGenBuffers(genbufs.size(), genbufs.data()); + dump_al_errors(); + for (const auto &b : genbufs) { + g_oaldec.freeBuffers.push_back(b); + } + } + + // decode and attach buffers + while (!EOS_) { + ALint buffersQueued = -1; + alGetSourcei(source_, AL_BUFFERS_QUEUED, &buffersQueued); + dump_al_errors(); + + if (buffersQueued >= SourceMinimumQueuedBuffers) { break; } + + assert(g_oaldec.freeBuffers.size() > 0); + auto it = std::prev(g_oaldec.freeBuffers.end()); + auto b = *it; + + auto sz = Sound_Decode(sample_.get()); + + if (sz <= 0) { + EOS_ = true; + // if repeat, then seek to start. + if (repeat_) { + auto res = Sound_Rewind(sample_.get()); + auto success = (res != 0); + EOS_ = !success; + } + continue; + } + + alBufferData(b, sampleOpenAlFormat_, sample_->buffer, sz, sample_->desired.rate); + dump_al_errors(); + + alSourceQueueBuffers(source_, 1, &b); + dump_al_errors(); + + g_oaldec.freeBuffers.erase(it); + } +} OpenALDecoder::OpenALDecoder(ALuint source, std::future> sampleBufFuture, AGS::Common::String sampleExt, bool repeat) @@ -159,53 +208,7 @@ void OpenALDecoder::Poll() if (playState_ != PlayStatePlaying) { return; } - // buffer management - DecoderUnqueueProcessedBuffers(); - - // generate extra buffers if none are free - if (g_oaldec.freeBuffers.size() < SourceMinimumQueuedBuffers) { - std::array genbufs; - alGenBuffers(genbufs.size(), genbufs.data()); - dump_al_errors(); - for (const auto &b : genbufs) { - g_oaldec.freeBuffers.push_back(b); - } - } - - // decode and attach buffers - while (!EOS_) { - ALint buffersQueued = -1; - alGetSourcei(source_, AL_BUFFERS_QUEUED, &buffersQueued); - dump_al_errors(); - - if (buffersQueued >= SourceMinimumQueuedBuffers) { break; } - - assert(g_oaldec.freeBuffers.size() > 0); - auto it = std::prev(g_oaldec.freeBuffers.end()); - auto b = *it; - - auto sz = Sound_Decode(sample_.get()); - - if (sz <= 0) { - EOS_ = true; - // if repeat, then seek to start. - if (repeat_) { - auto res = Sound_Rewind(sample_.get()); - auto success = (res != 0); - EOS_ = !success; - } - continue; - } - - alBufferData(b, sampleOpenAlFormat_, sample_->buffer, sz, sample_->desired.rate); - dump_al_errors(); - - alSourceQueueBuffers(source_, 1, &b); - dump_al_errors(); - - g_oaldec.freeBuffers.erase(it); - } - + PollBuffers(); // setup play state @@ -240,6 +243,10 @@ void OpenALDecoder::Play() Seek(0.0f); case PlayStatePaused: playState_ = AudioCorePlayState::PlayStatePlaying; + // we poll some data before alSourcePlay because mojoAL + // can drop a clip out of its slot if it is not initialized with something + // see mojoal.c mix_source + PollBuffers(); alSourcePlay(source_); dump_al_errors(); break; diff --git a/Engine/media/audio/openaldecoder.h b/Engine/media/audio/openaldecoder.h index f20d2edd9f3..7c92c894083 100644 --- a/Engine/media/audio/openaldecoder.h +++ b/Engine/media/audio/openaldecoder.h @@ -69,6 +69,7 @@ class OpenALDecoder static float buffer_duration_ms(ALuint bufferID); static ALenum openalFormatFromSample(const SoundSampleUniquePtr &sample); void DecoderUnqueueProcessedBuffers(); + void PollBuffers(); }; From a891e3c7f246cd21ab73d6903ce3bfd78d4c72df Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 2 Oct 2020 01:16:54 +0300 Subject: [PATCH 06/41] Replaced sound config with a simplier temporary on/off switch --- Engine/ac/gamesetup.cpp | 3 +- Engine/ac/gamesetup.h | 3 +- Engine/ac/global_video.cpp | 2 +- Engine/main/config.cpp | 101 +-------------------- Engine/main/config.h | 11 --- Engine/main/engine.cpp | 12 ++- Engine/media/audio/audio.cpp | 3 +- Engine/platform/windows/setup/winsetup.cpp | 29 ------ Engine/plugin/agsplugin.cpp | 3 +- 9 files changed, 14 insertions(+), 153 deletions(-) diff --git a/Engine/ac/gamesetup.cpp b/Engine/ac/gamesetup.cpp index c55cdce483c..e5d0fd1e089 100644 --- a/Engine/ac/gamesetup.cpp +++ b/Engine/ac/gamesetup.cpp @@ -17,8 +17,7 @@ GameSetup::GameSetup() { - digicard=DIGI_AUTODETECT; - midicard=MIDI_AUTODETECT; + audio_backend = 1; no_speech_pack = false; textheight = 0; enable_antialiasing = false; diff --git a/Engine/ac/gamesetup.h b/Engine/ac/gamesetup.h index 13b5b8faf0c..41bd71ae0bf 100644 --- a/Engine/ac/gamesetup.h +++ b/Engine/ac/gamesetup.h @@ -46,8 +46,7 @@ using AGS::Common::String; // that engine may use a "config" object or combo of objects to store // current user config, which may also be changed from script, and saved. struct GameSetup { - int digicard; - int midicard; + int audio_backend; // abstract option, currently only works as on/off int textheight; // text height used on the certain built-in GUI // TODO: move out to game class? bool no_speech_pack; bool enable_antialiasing; diff --git a/Engine/ac/global_video.cpp b/Engine/ac/global_video.cpp index 438fcc83371..1d63035b14d 100644 --- a/Engine/ac/global_video.cpp +++ b/Engine/ac/global_video.cpp @@ -34,7 +34,7 @@ void scrPlayVideo(const char* name, int skip, int flags) { if (debug_flags & DBG_NOVIDEO) return; - if ((flags < 10) && (usetup.digicard == DIGI_NONE)) { + if ((flags < 10) && (usetup.audio_backend == 0)) { // if game audio is disabled in Setup, then don't // play any sound on the video either flags += 10; diff --git a/Engine/main/config.cpp b/Engine/main/config.cpp index a6b166d1cf6..97dbb09e176 100644 --- a/Engine/main/config.cpp +++ b/Engine/main/config.cpp @@ -207,69 +207,6 @@ int convert_fp_to_scaling(uint32_t scaling) return scaling >= kUnit ? (scaling >> kShift) : -kUnit / (int32_t)scaling; } -AlIDStr AlIDToChars(int al_id) -{ - if (al_id == 0) - return AlIDStr {{ 'N', 'O', 'N', 'E', '\0' }}; - else if (al_id == -1) - return AlIDStr {{ 'A', 'U', 'T', 'O', '\0' }}; - else - return AlIDStr {{ - static_cast((al_id >> 24) & 0xFF), - static_cast((al_id >> 16) & 0xFF), - static_cast((al_id >> 8) & 0xFF), - static_cast((al_id) & 0xFF), - '\0' - }}; -} - -AlIDStr AlIDToChars(const String &s) -{ - AlIDStr id_str; - size_t i = 0; - for (; i < s.GetLength(); ++i) - id_str.s[i] = toupper(s[i]); - for (; i < 4; ++i) - id_str.s[i] = ' '; - id_str.s[4] = 0; - return id_str; -} - -int StringToAlID(const char *cstr) -{ - return (int)(AL_ID(cstr[0u], cstr[1u], cstr[2u], cstr[3u])); -} - -// Parses a config string which may hold plain driver's ID or 4-char ID packed -// as a 32-bit integer. -int parse_driverid(const String &id) -{ - int asint; - if (StrUtil::StringToInt(id, asint, 0) == StrUtil::kNoError) - return asint; - if (id.GetLength() > 4) - return -1; // autodetect - if (id.CompareNoCase("AUTO") == 0) - return -1; // autodetect - if (id.CompareNoCase("NONE") == 0) - return 0; // no driver - return StringToAlID(AlIDToChars(id).s); -} - -// Reads driver ID from config, where it may be represented as string or number -int read_driverid(const ConfigTree &cfg, const String §n, const String &item, int def_value) -{ - String s = INIreadstring(cfg, sectn, item); - if (s.IsEmpty()) - return def_value; - return parse_driverid(s); -} - -void write_driverid(ConfigTree &cfg, const String §n, const String &item, int value) -{ - INIwritestring(cfg, sectn, item, AlIDToChars(value).s); -} - void graphics_mode_get_defaults(bool windowed, ScreenSizeSetup &scsz_setup, GameFrameSetup &frame_setup) { scsz_setup.Size = Size(); @@ -325,10 +262,7 @@ void config_defaults() #else usetup.Screen.DriverID = "OGL"; #endif -#if AGS_PLATFORM_OS_WINDOWS - usetup.digicard = DIGI_DIRECTAMX(0); -#endif - usetup.midicard = MIDI_AUTODETECT; + usetup.audio_backend = 1; usetup.translation = ""; } @@ -353,33 +287,6 @@ void read_game_data_location(const ConfigTree &cfg) usetup.main_data_filename = INIreadstring(cfg, "misc", "datafile", usetup.main_data_filename); } -void read_legacy_audio_config(const ConfigTree &cfg) -{ -#if AGS_PLATFORM_OS_WINDOWS - int idx = INIreadint(cfg, "sound", "digiwinindx", -1); - if (idx == 0) - idx = DIGI_DIRECTAMX(0); - else if (idx == 1) - idx = DIGI_WAVOUTID(0); - else if (idx == 2) - idx = DIGI_NONE; - else if (idx == 3) - idx = DIGI_DIRECTX(0); - else - idx = DIGI_AUTODETECT; - usetup.digicard = idx; - - idx = INIreadint(cfg, "sound", "midiwinindx", -1); - if (idx == 1) - idx = MIDI_NONE; - else if (idx == 2) - idx = MIDI_WIN32MAPPER; - else - idx = MIDI_AUTODETECT; - usetup.midicard = idx; -#endif -} - void read_legacy_graphics_config(const ConfigTree &cfg) { usetup.Screen.DisplayMode.Windowed = INIreadint(cfg, "misc", "windowed") > 0; @@ -481,11 +388,7 @@ void override_config_ext(ConfigTree &cfg) void apply_config(const ConfigTree &cfg) { { - // Legacy settings has to be translated into new options; - // they must be read first, to let newer options override them, if ones are present - read_legacy_audio_config(cfg); - usetup.digicard = read_driverid(cfg, "sound", "digiid", usetup.digicard); - usetup.midicard = read_driverid(cfg, "sound", "midiid", usetup.midicard); + usetup.audio_backend = INIreadint(cfg, "sound", "enabled", usetup.audio_backend); // Legacy graphics settings has to be translated into new options; // they must be read first, to let newer options override them, if ones are present diff --git a/Engine/main/config.h b/Engine/main/config.h index 5398a148b21..16f9d2901a1 100644 --- a/Engine/main/config.h +++ b/Engine/main/config.h @@ -52,17 +52,6 @@ int convert_fp_to_scaling(uint32_t scaling); // Fill in setup structs with default settings for the given mode (windowed or fullscreen) void graphics_mode_get_defaults(bool windowed, ScreenSizeSetup &scsz_setup, GameFrameSetup &frame_setup); -typedef struct { char s[5]; } AlIDStr; -// Converts Allegro driver ID type to 4-char string -AlIDStr AlIDToChars(int al_id); -AlIDStr AlIDToChars(const String &s); -// Converts C-string into Allegro's driver ID; string must be at least 4 character long -int StringToAlID(const char *cstr); -// Reads driver ID from config, where it may be represented as string or number -int read_driverid(const ConfigTree &cfg, const String §n, const String &item, int def_value); -// Writes driver ID to config -void write_driverid(ConfigTree &cfg, const String §n, const String &item, int value); - bool INIreaditem(const ConfigTree &cfg, const String §n, const String &item, String &value); int INIreadint(const ConfigTree &cfg, const String §n, const String &item, int def_value = 0); diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index a38fe060643..1ec03de7d58 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -440,14 +440,16 @@ void engine_init_timer() void engine_init_audio() { - Debug::Printf("Initializing sound drivers"); - audio_core_init(); // audio core system + if (usetup.audio_backend != 0) + { + Debug::Printf("Initializing audio"); + audio_core_init(); // audio core system + } our_eip = -181; - if (digi_card == DIGI_NONE) + if (usetup.audio_backend == 0) { - // disable speech and music if no digital sound - // therefore the MIDI soundtrack will be used if present, + // all audio is disabled // and the voice mode should not go to Voice Only play.want_speech = -2; play.separate_music_lib = 0; diff --git a/Engine/media/audio/audio.cpp b/Engine/media/audio/audio.cpp index 83e91c3efbe..736a2db53e7 100644 --- a/Engine/media/audio/audio.cpp +++ b/Engine/media/audio/audio.cpp @@ -233,8 +233,7 @@ static int find_free_audio_channel(ScriptAudioClip *clip, int priority, bool int bool is_audiotype_allowed_to_play(AudioFileType type) { - return (type == eAudioFileMIDI && usetup.midicard != MIDI_NONE) || - (type != eAudioFileMIDI && usetup.digicard != DIGI_NONE); + return usetup.audio_backend != 0; } SOUNDCLIP *load_sound_clip(ScriptAudioClip *audioClip, bool repeat) diff --git a/Engine/platform/windows/setup/winsetup.cpp b/Engine/platform/windows/setup/winsetup.cpp index ea4f77fc7ec..e834fa93896 100644 --- a/Engine/platform/windows/setup/winsetup.cpp +++ b/Engine/platform/windows/setup/winsetup.cpp @@ -92,9 +92,6 @@ struct WinConfig bool RenderAtScreenRes; bool AntialiasSprites; - int DigiID; - int MidiID; - bool ThreadedAudio; bool UseVoicePack; bool MouseAutoLock; @@ -136,9 +133,6 @@ void WinConfig::SetDefaults() MouseAutoLock = false; MouseSpeed = 1.f; - DigiID = -1; // autodetect - MidiID = -1; - ThreadedAudio = false; UseVoicePack = true; SpriteCacheSize = 1024 * 128; @@ -175,9 +169,6 @@ void WinConfig::Load(const ConfigTree &cfg) AntialiasSprites = INIreadint(cfg, "misc", "antialias", AntialiasSprites ? 1 : 0) != 0; - DigiID = read_driverid(cfg, "sound", "digiid", DigiID); - MidiID = read_driverid(cfg, "sound", "midiid", MidiID); - ThreadedAudio = INIreadint(cfg, "sound", "threaded", ThreadedAudio ? 1 : 0) != 0; UseVoicePack = INIreadint(cfg, "sound", "usespeech", UseVoicePack ? 1 : 0) != 0; MouseAutoLock = INIreadint(cfg, "mouse", "auto_lock", MouseAutoLock ? 1 : 0) != 0; @@ -210,9 +201,6 @@ void WinConfig::Save(ConfigTree &cfg) INIwriteint(cfg, "misc", "antialias", AntialiasSprites ? 1 : 0); - write_driverid(cfg, "sound", "digiid", DigiID); - write_driverid(cfg, "sound", "midiid", MidiID); - INIwriteint(cfg, "sound", "threaded", ThreadedAudio ? 1 : 0); INIwriteint(cfg, "sound", "usespeech", UseVoicePack ? 1 : 0); INIwriteint(cfg, "mouse", "auto_lock", MouseAutoLock ? 1 : 0); @@ -642,18 +630,6 @@ INT_PTR WinSetupDialog::OnInitDialog(HWND hwnd) SetCheck(_hRenderAtScreenRes, _winCfg.RenderAtScreenRes); - AddString(_hDigiDriverList, "No Digital Sound", DIGI_NONE); - AddString(_hDigiDriverList, "Default device (auto)", MIDI_AUTODETECT); - AddString(_hDigiDriverList, "Default DirectSound Device", DIGI_DIRECTAMX(0)); - AddString(_hDigiDriverList, "Default WaveOut Device", DIGI_WAVOUTID(0)); - AddString(_hDigiDriverList, "DirectSound (Hardware mixer)", DIGI_DIRECTX(0)); - SetCurSelToItemData(_hDigiDriverList, _winCfg.DigiID); - - AddString(_hMidiDriverList, "No MIDI music", MIDI_NONE); - AddString(_hMidiDriverList, "Default device (auto)", MIDI_AUTODETECT); - AddString(_hMidiDriverList, "Win32 MIDI Mapper", MIDI_WIN32MAPPER); - SetCurSelToItemData(_hMidiDriverList, _winCfg.MidiID); - FillLanguageList(); SetCheck(_hMouseLock, _winCfg.MouseAutoLock); @@ -674,7 +650,6 @@ INT_PTR WinSetupDialog::OnInitDialog(HWND hwnd) SetCheck(_hRefresh85Hz, _winCfg.RefreshRate == 85); SetCheck(_hAntialiasSprites, _winCfg.AntialiasSprites); - SetCheck(_hThreadedAudio, _winCfg.ThreadedAudio); SetCheck(_hUseVoicePack, _winCfg.UseVoicePack); if (!File::TestReadFile("speech.vox")) EnableWindow(_hUseVoicePack, FALSE); @@ -1133,15 +1108,11 @@ void WinSetupDialog::SaveSetup() _winCfg.UserSaveDir = ""; } - _winCfg.DigiID = GetCurItemData(_hDigiDriverList); - _winCfg.MidiID = GetCurItemData(_hMidiDriverList); - if (GetCurSel(_hLanguageList) == 0) _winCfg.Language.Empty(); else _winCfg.Language = GetText(_hLanguageList); _winCfg.SpriteCacheSize = GetCurItemData(_hSpriteCacheList) * 1024; - _winCfg.ThreadedAudio = GetCheck(_hThreadedAudio); _winCfg.UseVoicePack = GetCheck(_hUseVoicePack); _winCfg.VSync = GetCheck(_hVSync); _winCfg.RenderAtScreenRes = GetCheck(_hRenderAtScreenRes); diff --git a/Engine/plugin/agsplugin.cpp b/Engine/plugin/agsplugin.cpp index ed4586825dc..a266bcd3da5 100644 --- a/Engine/plugin/agsplugin.cpp +++ b/Engine/plugin/agsplugin.cpp @@ -670,8 +670,7 @@ int IAGSEngine::IsSpriteAlphaBlended(int32 slot) { // disable AGS's sound engine void IAGSEngine::DisableSound() { shutdown_sound(); - usetup.digicard = DIGI_NONE; - usetup.midicard = MIDI_NONE; + usetup.audio_backend = 0; } int IAGSEngine::CanRunScriptFunctionNow() { if (inside_script) From fe2f9964e337472eda3808f9c6109019a9b493a7 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 2 Oct 2020 01:49:39 +0300 Subject: [PATCH 07/41] Removed unnecessary Allegro4-based sound libraries --- Common/libinclude/aldumb.h | 98 - Common/libinclude/almp3.h | 155 - Common/libinclude/almp3dll.h | 20 - Common/libinclude/alogg.h | 141 - Common/libinclude/aloggdll.h | 20 - Common/libinclude/apeg.h | 147 - Common/libinclude/common.h | 14 - Common/libinclude/dumb.h | 563 --- Common/libinclude/genre.h | 266 -- Common/libinclude/getbits.h | 87 - Common/libinclude/getblk.h | 109 - Common/libinclude/huffman.h | 334 -- Common/libinclude/internal/aldumb.h | 27 - Common/libinclude/internal/dumb.h | 58 - Common/libinclude/internal/it.h | 710 ---- Common/libinclude/l2tables.h | 158 - Common/libinclude/libcda.h | 48 - Common/libinclude/mpeg1dec.h | 236 -- Common/libinclude/mpg123.h | 301 -- Common/libinclude/mpglib.h | 49 - Engine/ac/asset_helper.h | 3 - Engine/ac/file.cpp | 9 - Engine/libsrc/allegro-4.2.2-agspatch/midi.c | 103 - Engine/libsrc/almp3-2.0.5/CMakeLists.txt | 36 - Engine/libsrc/almp3-2.0.5/decoder/README | 39 - Engine/libsrc/almp3-2.0.5/decoder/common.c | 191 - .../libsrc/almp3-2.0.5/decoder/dct64_i386.c | 314 -- .../libsrc/almp3-2.0.5/decoder/decode_i386.c | 262 -- Engine/libsrc/almp3-2.0.5/decoder/huffman.h | 332 -- Engine/libsrc/almp3-2.0.5/decoder/interface.c | 217 - Engine/libsrc/almp3-2.0.5/decoder/l2tables.h | 163 - Engine/libsrc/almp3-2.0.5/decoder/layer2.c | 300 -- Engine/libsrc/almp3-2.0.5/decoder/layer3.c | 1619 -------- Engine/libsrc/almp3-2.0.5/decoder/mpg123.h | 135 - Engine/libsrc/almp3-2.0.5/decoder/mpglib.h | 49 - Engine/libsrc/almp3-2.0.5/decoder/tabinit.c | 78 - Engine/libsrc/almp3-2.0.5/include/almp3.h | 155 - Engine/libsrc/almp3-2.0.5/include/almp3dll.h | 20 - Engine/libsrc/almp3-2.0.5/src/almp3.c | 2025 ---------- Engine/libsrc/almp3/almp3.c | 2025 ---------- Engine/libsrc/alogg/ALOGG.txt | 380 -- Engine/libsrc/alogg/AUTHORS.txt | 5 - Engine/libsrc/alogg/CHANGES.txt | 16 - Engine/libsrc/alogg/CMakeLists.txt | 17 - Engine/libsrc/alogg/COPYING.txt | 28 - Engine/libsrc/alogg/README.txt | 71 - Engine/libsrc/alogg/alogg.c | 1195 ------ Engine/libsrc/alogg/alogg.h | 141 - Engine/libsrc/alogg/aloggdll.h | 20 - Engine/libsrc/dumb-0.9.2/CMakeLists.txt | 54 - Engine/libsrc/dumb-0.9.2/allegro/alplay.c | 270 -- Engine/libsrc/dumb-0.9.2/allegro/datduh.c | 60 - Engine/libsrc/dumb-0.9.2/allegro/datit.c | 62 - Engine/libsrc/dumb-0.9.2/allegro/datmod.c | 61 - Engine/libsrc/dumb-0.9.2/allegro/dats3m.c | 61 - Engine/libsrc/dumb-0.9.2/allegro/datunld.c | 31 - Engine/libsrc/dumb-0.9.2/allegro/datxm.c | 62 - Engine/libsrc/dumb-0.9.2/allegro/packfile.c | 98 - Engine/libsrc/dumb-0.9.2/core/atexit.c | 71 - Engine/libsrc/dumb-0.9.2/core/duhlen.c | 34 - Engine/libsrc/dumb-0.9.2/core/dumbfile.c | 401 -- Engine/libsrc/dumb-0.9.2/core/loadduh.c | 42 - Engine/libsrc/dumb-0.9.2/core/makeduh.c | 92 - Engine/libsrc/dumb-0.9.2/core/rawsig.c | 44 - Engine/libsrc/dumb-0.9.2/core/readduh.c | 107 - Engine/libsrc/dumb-0.9.2/core/register.c | 104 - Engine/libsrc/dumb-0.9.2/core/rendduh.c | 202 - Engine/libsrc/dumb-0.9.2/core/rendsig.c | 298 -- Engine/libsrc/dumb-0.9.2/core/unload.c | 58 - Engine/libsrc/dumb-0.9.2/helpers/clickrem.c | 270 -- Engine/libsrc/dumb-0.9.2/helpers/memfile.c | 96 - Engine/libsrc/dumb-0.9.2/helpers/resample.c | 1177 ------ Engine/libsrc/dumb-0.9.2/helpers/sampbuf.c | 47 - Engine/libsrc/dumb-0.9.2/helpers/silence.c | 29 - Engine/libsrc/dumb-0.9.2/helpers/stdfile.c | 93 - Engine/libsrc/dumb-0.9.2/include/aldumb.h | 98 - Engine/libsrc/dumb-0.9.2/include/dumb.h | 563 --- .../dumb-0.9.2/include/internal/aldumb.h | 27 - .../libsrc/dumb-0.9.2/include/internal/dumb.h | 58 - .../libsrc/dumb-0.9.2/include/internal/it.h | 710 ---- Engine/libsrc/dumb-0.9.2/it/itload.c | 43 - Engine/libsrc/dumb-0.9.2/it/itmisc.c | 175 - Engine/libsrc/dumb-0.9.2/it/itorder.c | 63 - Engine/libsrc/dumb-0.9.2/it/itread.c | 1179 ------ Engine/libsrc/dumb-0.9.2/it/itrender.c | 3512 ----------------- Engine/libsrc/dumb-0.9.2/it/itunload.c | 71 - Engine/libsrc/dumb-0.9.2/it/loadmod.c | 42 - Engine/libsrc/dumb-0.9.2/it/loads3m.c | 42 - Engine/libsrc/dumb-0.9.2/it/loadxm.c | 42 - Engine/libsrc/dumb-0.9.2/it/readmod.c | 594 --- Engine/libsrc/dumb-0.9.2/it/reads3m.c | 668 ---- Engine/libsrc/dumb-0.9.2/it/readxm.c | 998 ----- Engine/libsrc/dumb-0.9.2/it/xmeffect.c | 242 -- Engine/libsrc/dumb-0.9.2/readme.txt | 421 -- Engine/libsrc/dumb-0.9.2/release.txt | 406 -- Solutions/Engine.App/Engine.App.vcxproj | 56 +- .../Engine.App/Engine.App.vcxproj.filters | 174 +- 97 files changed, 22 insertions(+), 27575 deletions(-) delete mode 100644 Common/libinclude/aldumb.h delete mode 100644 Common/libinclude/almp3.h delete mode 100644 Common/libinclude/almp3dll.h delete mode 100644 Common/libinclude/alogg.h delete mode 100644 Common/libinclude/aloggdll.h delete mode 100644 Common/libinclude/apeg.h delete mode 100644 Common/libinclude/common.h delete mode 100644 Common/libinclude/dumb.h delete mode 100644 Common/libinclude/genre.h delete mode 100644 Common/libinclude/getbits.h delete mode 100644 Common/libinclude/getblk.h delete mode 100644 Common/libinclude/huffman.h delete mode 100644 Common/libinclude/internal/aldumb.h delete mode 100644 Common/libinclude/internal/dumb.h delete mode 100644 Common/libinclude/internal/it.h delete mode 100644 Common/libinclude/l2tables.h delete mode 100644 Common/libinclude/libcda.h delete mode 100644 Common/libinclude/mpeg1dec.h delete mode 100644 Common/libinclude/mpg123.h delete mode 100644 Common/libinclude/mpglib.h delete mode 100644 Engine/libsrc/allegro-4.2.2-agspatch/midi.c delete mode 100644 Engine/libsrc/almp3-2.0.5/CMakeLists.txt delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/README delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/common.c delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/dct64_i386.c delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/decode_i386.c delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/huffman.h delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/interface.c delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/l2tables.h delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/layer2.c delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/layer3.c delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/mpg123.h delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/mpglib.h delete mode 100644 Engine/libsrc/almp3-2.0.5/decoder/tabinit.c delete mode 100644 Engine/libsrc/almp3-2.0.5/include/almp3.h delete mode 100644 Engine/libsrc/almp3-2.0.5/include/almp3dll.h delete mode 100644 Engine/libsrc/almp3-2.0.5/src/almp3.c delete mode 100644 Engine/libsrc/almp3/almp3.c delete mode 100644 Engine/libsrc/alogg/ALOGG.txt delete mode 100644 Engine/libsrc/alogg/AUTHORS.txt delete mode 100644 Engine/libsrc/alogg/CHANGES.txt delete mode 100644 Engine/libsrc/alogg/CMakeLists.txt delete mode 100644 Engine/libsrc/alogg/COPYING.txt delete mode 100644 Engine/libsrc/alogg/README.txt delete mode 100644 Engine/libsrc/alogg/alogg.c delete mode 100644 Engine/libsrc/alogg/alogg.h delete mode 100644 Engine/libsrc/alogg/aloggdll.h delete mode 100644 Engine/libsrc/dumb-0.9.2/CMakeLists.txt delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/alplay.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/datduh.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/datit.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/datmod.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/dats3m.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/datunld.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/datxm.c delete mode 100644 Engine/libsrc/dumb-0.9.2/allegro/packfile.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/atexit.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/duhlen.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/dumbfile.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/loadduh.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/makeduh.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/rawsig.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/readduh.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/register.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/rendduh.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/rendsig.c delete mode 100644 Engine/libsrc/dumb-0.9.2/core/unload.c delete mode 100644 Engine/libsrc/dumb-0.9.2/helpers/clickrem.c delete mode 100644 Engine/libsrc/dumb-0.9.2/helpers/memfile.c delete mode 100644 Engine/libsrc/dumb-0.9.2/helpers/resample.c delete mode 100644 Engine/libsrc/dumb-0.9.2/helpers/sampbuf.c delete mode 100644 Engine/libsrc/dumb-0.9.2/helpers/silence.c delete mode 100644 Engine/libsrc/dumb-0.9.2/helpers/stdfile.c delete mode 100644 Engine/libsrc/dumb-0.9.2/include/aldumb.h delete mode 100644 Engine/libsrc/dumb-0.9.2/include/dumb.h delete mode 100644 Engine/libsrc/dumb-0.9.2/include/internal/aldumb.h delete mode 100644 Engine/libsrc/dumb-0.9.2/include/internal/dumb.h delete mode 100644 Engine/libsrc/dumb-0.9.2/include/internal/it.h delete mode 100644 Engine/libsrc/dumb-0.9.2/it/itload.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/itmisc.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/itorder.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/itread.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/itrender.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/itunload.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/loadmod.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/loads3m.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/loadxm.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/readmod.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/reads3m.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/readxm.c delete mode 100644 Engine/libsrc/dumb-0.9.2/it/xmeffect.c delete mode 100644 Engine/libsrc/dumb-0.9.2/readme.txt delete mode 100644 Engine/libsrc/dumb-0.9.2/release.txt diff --git a/Common/libinclude/aldumb.h b/Common/libinclude/aldumb.h deleted file mode 100644 index 75262508d9b..00000000000 --- a/Common/libinclude/aldumb.h +++ /dev/null @@ -1,98 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * aldumb.h - The user header file for DUMB with / / \ \ - * Allegro. | < / \_ - * | \/ /\ / - * Include this file if you wish to use DUMB \_ / > / - * with Allegro. It will include dumb.h for you, | \ / / - * and provide extra functionality such as audio | ' / - * stream and datafile integration. \__/ - */ - -#ifndef ALDUMB_H -#define ALDUMB_H - - -#include - -#include "dumb.h" - - -#ifdef __cplusplus - extern "C" { -#endif - - -/* Packfile Support */ - -void dumb_register_packfiles(void); - -DUMBFILE *dumbfile_open_packfile(PACKFILE *p); -DUMBFILE *dumbfile_from_packfile(PACKFILE *p); - - -/* Datafile Registration Functions */ - -#define DUMB_DAT_DUH DAT_ID('D','U','H',' ') -#define DUMB_DAT_IT DAT_ID('I','T',' ',' ') -#define DUMB_DAT_XM DAT_ID('X','M',' ',' ') -#define DUMB_DAT_S3M DAT_ID('S','3','M',' ') -#define DUMB_DAT_MOD DAT_ID('M','O','D',' ') - -void dumb_register_dat_duh(long type); -void dumb_register_dat_it(long type); -void dumb_register_dat_xm(long type); -void dumb_register_dat_s3m(long type); -void dumb_register_dat_mod(long type); -void dumb_register_dat_it_quick(long type); -void dumb_register_dat_xm_quick(long type); -void dumb_register_dat_s3m_quick(long type); -void dumb_register_dat_mod_quick(long type); - - -/* DUH Playing Functions */ - -typedef struct AL_DUH_PLAYER AL_DUH_PLAYER; - -AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq); -void al_stop_duh(AL_DUH_PLAYER *dp); -void al_pause_duh(AL_DUH_PLAYER *dp); -void al_resume_duh(AL_DUH_PLAYER *dp); -void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority); -void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume); -float al_duh_get_volume(AL_DUH_PLAYER *dp); -int al_poll_duh(AL_DUH_PLAYER *dp); -long al_duh_get_position(AL_DUH_PLAYER *dp); - -AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq); -DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp); - -/* IMPORTANT: This function will return NULL if the music has ended. */ -DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp); - -#ifdef DUMB_DECLARE_DEPRECATED - -AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq) DUMB_DEPRECATED; -DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED; -DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED; -/* Replace 'renderer' with 'sigrenderer' in each case where you called one of - * these functions. - */ - -#endif - - -#ifdef __cplusplus - } -#endif - - -#endif /* ALDUMB_H */ diff --git a/Common/libinclude/almp3.h b/Common/libinclude/almp3.h deleted file mode 100644 index a45a574b83c..00000000000 --- a/Common/libinclude/almp3.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Allegro MP3 - a wrapper for mpglib from mpg123 */ -/* to play MP3 files with Allegro */ - -/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ -/* Allegro MP3 is copyright (c) 2001, 2002 Javier Gonz lez */ - -/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ - - -#ifndef ALMP3_H -#define ALMP3_H - - -#include - -#include "almp3dll.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* common define */ - -#define ALMP3_MAJOR_VERSION 2 -#define ALMP3_MINOR_VERSION 0 -#define ALMP3_SUB_VERSION 4 -#define ALMP3_VERSION_STR "2.0.4" -#define ALMP3_DATE_STR "08/04/2003" -#define ALMP3_DATE 20030408 /* yyyymmdd */ - -/* error codes */ - -#define ALMP3_OK 0 - -#define ALMP3_PLAY_BUFFERTOOSMALL -1 - -#define ALMP3_POLL_PLAYJUSTFINISHED 1 -#define ALMP3_POLL_NOTPLAYING -1 -#define ALMP3_POLL_FRAMECORRUPT -2 -#define ALMP3_POLL_BUFFERUNDERRUN -3 -#define ALMP3_POLL_INTERNALERROR -4 - - -/* API - MP3 */ - -typedef struct ALMP3_MP3 ALMP3_MP3; - - -ALMP3_DLL_DECLSPEC ALMP3_MP3 *almp3_create_mp3(void *data, int data_len); -ALMP3_DLL_DECLSPEC void almp3_destroy_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC int almp3_play_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan); -ALMP3_DLL_DECLSPEC int almp3_play_ex_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan, int speed, int loop); -ALMP3_DLL_DECLSPEC void almp3_stop_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC void almp3_rewind_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_frames_mp3(ALMP3_MP3 *mp3, int frame); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_msecs_mp3(ALMP3_MP3 *mp3, int msecs); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_secs_mp3(ALMP3_MP3 *mp3, int secs); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_bytes_mp3(ALMP3_MP3 *mp3, int bytes); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_frames_mp3(ALMP3_MP3 *mp3, int frame); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_msecs_mp3(ALMP3_MP3 *mp3, int msec); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_secs_mp3(ALMP3_MP3 *mp3, int sec); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_bytes_mp3(ALMP3_MP3 *mp3, int bytes); -ALMP3_DLL_DECLSPEC void almp3_adjust_mp3(ALMP3_MP3 *mp3, int vol, int pan, int speed, int loop); - -ALMP3_DLL_DECLSPEC int almp3_poll_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC void almp3_start_autopoll_mp3(ALMP3_MP3 *mp3, int speed); -ALMP3_DLL_DECLSPEC void almp3_stop_autopoll_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC int almp3_get_pos_frames_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_msecs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_secs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_bytes_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_frames_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_secs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_msecs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_bytes_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_msecs_per_frame_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_bitrate_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_layer_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_is_stereo_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_bits_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_is_stereo_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_freq_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC SAMPLE *almp3_create_sample_from_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC void *almp3get_output_wave_mp3(ALMP3_MP3 *mp3, int *buffer_size); - -ALMP3_DLL_DECLSPEC int almp3_is_playing_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_is_looping_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC AUDIOSTREAM *almp3_get_audiostream_mp3(ALMP3_MP3 *mp3); - - - -/* API - MP3STREAM */ - -typedef struct ALMP3_MP3STREAM ALMP3_MP3STREAM; - - -ALMP3_DLL_DECLSPEC ALMP3_MP3STREAM *almp3_create_mp3stream(void *first_data_buffer, int data_buffer_len, int last_block); -ALMP3_DLL_DECLSPEC ALMP3_MP3STREAM *almp3_create_mp3stream_ex(void *first_data_buffer, int data_buffer_len, int last_block, int downsample, int downmix); -ALMP3_DLL_DECLSPEC void almp3_destroy_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC int almp3_play_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan); -ALMP3_DLL_DECLSPEC int almp3_play_ex_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan, int speed); -ALMP3_DLL_DECLSPEC void almp3_stop_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void almp3_adjust_mp3stream(ALMP3_MP3STREAM *mp3, int vol, int pan, int speed); - -ALMP3_DLL_DECLSPEC int almp3_poll_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void almp3_start_autopoll_mp3stream(ALMP3_MP3STREAM *mp3, int speed); -ALMP3_DLL_DECLSPEC void almp3_stop_autopoll_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void *almp3_get_mp3stream_buffer(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void almp3_free_mp3stream_buffer(ALMP3_MP3STREAM *mp3, int bytes_used); - -ALMP3_DLL_DECLSPEC int almp3_get_length_frames_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_length_secs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_length_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_length_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_pos_frames_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_msecs_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_secs_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_bytes_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_msecs_per_frame_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_bitrate_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_layer_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_bits_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_freq_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC void *almp3_get_output_wave_mp3stream(ALMP3_MP3STREAM *mp3, int *buffer_size); - -ALMP3_DLL_DECLSPEC int almp3_is_playing_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC AUDIOSTREAM *almp3_get_audiostream_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC int almp3_seek_abs_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_abs_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msecs, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_abs_secs_mp3stream(ALMP3_MP3STREAM *mp3, int secs, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_abs_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msec, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_secs_mp3stream(ALMP3_MP3STREAM *mp3, int sec, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Common/libinclude/almp3dll.h b/Common/libinclude/almp3dll.h deleted file mode 100644 index a69c03f66a0..00000000000 --- a/Common/libinclude/almp3dll.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Allegro MP3 - a wrapper for mpglib from mpg123 */ -/* to play MP3 files with Allegro */ - -/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ -/* Allegro MP3 is copyright (c) 2001, 2002 Javier Gonz lez */ - -/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ - - -#ifndef ALMP3_DLL_DECLSPEC -# ifdef ALMP3_DLL -# ifdef ALMP3_DLL_EXPORTS -# define ALMP3_DLL_DECLSPEC __declspec(dllexport) -# else -# define ALMP3_DLL_DECLSPEC __declspec(dllimport) -# endif -# else -# define ALMP3_DLL_DECLSPEC -# endif -#endif diff --git a/Common/libinclude/alogg.h b/Common/libinclude/alogg.h deleted file mode 100644 index 7d1e4abc1ed..00000000000 --- a/Common/libinclude/alogg.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Allegro OGG */ -/* to play OGG files with Allegro */ - -/* OGG decoder part ofOgg Vorbis (Xiph.org Foundation) */ -/* Allegro OGG is copyright (c) 2002 Javier Gonz lez */ - -/* See COPYING.txt for license */ - - -#ifndef ALOGG_H -#define ALOGG_H - - -#include -#include - -#include "aloggdll.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* common define */ - -#define ALOGG_MAJOR_VERSION 1 -#define ALOGG_MINOR_VERSION 0 -#define ALOGG_SUB_VERSION 0 -#define ALOGG_VERSION_STR "1.0.0" -#define ALOGG_DATE_STR "23/08/2002" -#define ALOGG_DATE 20020823 /* yyyymmdd */ - -/* error codes */ - -#define ALOGG_OK 0 - -#define ALOGG_PLAY_BUFFERTOOSMALL -1 - -#define ALOGG_POLL_PLAYJUSTFINISHED 1 -#define ALOGG_POLL_NOTPLAYING -1 -#define ALOGG_POLL_FRAMECORRUPT -2 -#define ALOGG_POLL_BUFFERUNDERRUN -3 -#define ALOGG_POLL_INTERNALERROR -4 - - -/* API - OGG */ - -typedef struct ALOGG_OGG ALOGG_OGG; - - -ALOGG_DLL_DECLSPEC ALOGG_OGG *alogg_create_ogg_from_buffer(void *data, int data_len); -ALOGG_DLL_DECLSPEC ALOGG_OGG *alogg_create_ogg_from_file(FILE *f); -ALOGG_DLL_DECLSPEC void alogg_destroy_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_play_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan); -ALOGG_DLL_DECLSPEC int alogg_play_ex_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan, int speed, int loop); -ALOGG_DLL_DECLSPEC void alogg_stop_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC void alogg_adjust_ogg(ALOGG_OGG *ogg, int vol, int pan, int speed, int loop); - -ALOGG_DLL_DECLSPEC void alogg_rewind_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC void alogg_seek_abs_msecs_ogg(ALOGG_OGG *ogg, int msecs); -ALOGG_DLL_DECLSPEC void alogg_seek_abs_secs_ogg(ALOGG_OGG *ogg, int secs); -ALOGG_DLL_DECLSPEC void alogg_seek_abs_bytes_ogg(ALOGG_OGG *ogg, int bytes); -ALOGG_DLL_DECLSPEC void alogg_seek_rel_msecs_ogg(ALOGG_OGG *ogg, int msec); -ALOGG_DLL_DECLSPEC void alogg_seek_rel_secs_ogg(ALOGG_OGG *ogg, int sec); -ALOGG_DLL_DECLSPEC void alogg_seek_rel_bytes_ogg(ALOGG_OGG *ogg, int bytes); - -ALOGG_DLL_DECLSPEC int alogg_poll_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC void alogg_start_autopoll_ogg(ALOGG_OGG *ogg, int speed); -ALOGG_DLL_DECLSPEC void alogg_stop_autopoll_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_pos_msecs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_secs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_bytes_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_length_secs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_length_msecs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_length_bytes_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_bitrate_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_is_stereo_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_bits_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_is_stereo_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_freq_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC SAMPLE *alogg_create_sample_from_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC void *aloggget_output_wave_ogg(ALOGG_OGG *ogg, int *buffer_size); - -ALOGG_DLL_DECLSPEC int alogg_is_playing_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_is_looping_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC AUDIOSTREAM *alogg_get_audiostream_ogg(ALOGG_OGG *ogg); - - - -/* API - OGGSTREAM */ - -typedef struct ALOGG_OGGSTREAM ALOGG_OGGSTREAM; - - -ALOGG_DLL_DECLSPEC ALOGG_OGGSTREAM *alogg_create_oggstream(void *first_data_buffer, int data_buffer_len, int last_block); -ALOGG_DLL_DECLSPEC ALOGG_OGGSTREAM *alogg_create_oggstream_ex(void *first_data_buffer, int data_buffer_len, int last_block, int downsample, int downmix); -ALOGG_DLL_DECLSPEC void alogg_destroy_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC int alogg_play_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan); -ALOGG_DLL_DECLSPEC int alogg_play_ex_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan, int speed); -ALOGG_DLL_DECLSPEC void alogg_stop_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC void alogg_adjust_oggstream(ALOGG_OGGSTREAM *ogg, int vol, int pan, int speed); - -ALOGG_DLL_DECLSPEC int alogg_poll_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC void alogg_start_autopoll_oggstream(ALOGG_OGGSTREAM *ogg, int speed); -ALOGG_DLL_DECLSPEC void alogg_stop_autopoll_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC void *alogg_get_oggstream_buffer(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC void alogg_free_oggstream_buffer(ALOGG_OGGSTREAM *ogg, int bytes_used); - -ALOGG_DLL_DECLSPEC int alogg_get_pos_msecs_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_secs_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_bytes_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_bitrate_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_bits_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_freq_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC void *alogg_get_output_wave_oggstream(ALOGG_OGGSTREAM *ogg, int *buffer_size); - -ALOGG_DLL_DECLSPEC int alogg_is_playing_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC AUDIOSTREAM *alogg_get_audiostream_oggstream(ALOGG_OGGSTREAM *ogg); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Common/libinclude/aloggdll.h b/Common/libinclude/aloggdll.h deleted file mode 100644 index 2a417de2297..00000000000 --- a/Common/libinclude/aloggdll.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Allegro OGG */ -/* to play OGG files with Allegro */ - -/* OGG decoder part of Ogg Vorbis (Xiph.org Foundation) */ -/* Allegro OGG is copyright (c) 2002 Javier Gonz lez */ - -/* See COPYING.txt for license */ - - -#ifndef ALOGG_DLL_DECLSPEC -# ifdef ALOGG_DLL -# ifdef ALOGG_DLL_EXPORTS -# define ALOGG_DLL_DECLSPEC __declspec(dllexport) -# else -# define ALOGG_DLL_DECLSPEC __declspec(dllimport) -# endif -# else -# define ALOGG_DLL_DECLSPEC -# endif -#endif diff --git a/Common/libinclude/apeg.h b/Common/libinclude/apeg.h deleted file mode 100644 index c0bb9cea3ed..00000000000 --- a/Common/libinclude/apeg.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef APEG_H -#define APEG_H - -#include - - -#define APEG_MAKE_VERSION(a, b, c) (((a)<<16) | ((b)<<8) | (c)) - -#define APEG_MAJOR_VERSION 1 -#define APEG_MINOR_VERSION 2 -#define APEG_REVISION 1 - -#define APEG_VERSION_NUM APEG_MAKE_VERSION(APEG_MAJOR_VERSION, APEG_MINOR_VERSION, APEG_REVISION) - -#define APEG_VERSION_STR "1.2.1" - - -#define FPS_TO_TIMER(x) ((long)((float)TIMERS_PER_SECOND / (float)(x))) - -#define APEG_OK (0) -#define APEG_ERROR (-1) -#define APEG_EOF (-2) - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct APEG_AUDIO_INF { - int kbps; - int layer; - int freq; - int down_sample; - int channels; - int down_channel; - int flushed; -} APEG_AUDIO_INF; - -typedef struct APEG_STREAM { - BITMAP *bitmap; - int frame_updated; - unsigned int frame; - - int w, h; - - double aspect_ratio; - int aspect_numerator, aspect_denominator; - - double length; - double pos; - - enum { - APEG_420, - APEG_422, - APEG_444 - } pixel_format; - - double frame_rate; - int fps_numerator, fps_denominator; - - int bit_rate; - - int sequence; - - volatile int timer; - - int flags; - - APEG_AUDIO_INF audio; -} APEG_STREAM; -#define APEG_MPG_VIDEO 1 -#define APEG_MPG_AUDIO 2 -#define APEG_VORBIS_AUDIO 4 -#define APEG_THEORA_VIDEO 8 -#define APEG_HAS_VIDEO (APEG_MPG_VIDEO|APEG_THEORA_VIDEO) -#define APEG_HAS_AUDIO (APEG_MPG_AUDIO|APEG_VORBIS_AUDIO) - - -APEG_STREAM *apeg_open_stream(const char *filename); -APEG_STREAM *apeg_open_memory_stream(void *buffer, int length); -APEG_STREAM *apeg_open_stream_ex(void *ptr); -int apeg_advance_stream(APEG_STREAM *stream, int loop); -int apeg_reset_stream(APEG_STREAM *stream); -void apeg_close_stream(APEG_STREAM *stream); - -int apeg_play_mpg(const char *filename, BITMAP *target, int loop, - int (*callback)(void)); -int apeg_play_memory_mpg(void *buffer, BITMAP *target, int loop, - int (*callback)(BITMAP*)); -int apeg_play_mpg_ex(void *ptr, BITMAP *target, int loop, - int (*callback)(BITMAP*)); -int apeg_play_apeg_stream(APEG_STREAM *stream_to_play, BITMAP *bmp, int loop, int (*callback)(BITMAP*tempBuffer)); - -int apeg_ignore_video(int ignore); -int apeg_ignore_audio(int ignore); - -void apeg_set_memory_stream_size(int size); -void apeg_set_stream_reader(int (*init)(void *ptr), - int (*read)(void *buffer, int bytes, void *ptr), - void (*skip)(int bytes, void *ptr)); - - -void apeg_set_display_callbacks(int (*init)(APEG_STREAM *stream, int coded_w, - int coded_h, void *ptr), - void (*callback)(APEG_STREAM *stream, - unsigned char **src, - void *ptr), - void *ptr); -void apeg_set_display_depth(int depth); -void apeg_set_quality(int quality); - -void apeg_enable_framedrop(int framedrop); -void apeg_disable_length_detection(int skipdetect); - -void apeg_reset_colors(APEG_STREAM *stream); - - -void apeg_get_video_size(APEG_STREAM *stream, int *w, int *h); -void apeg_set_stream_rate(APEG_STREAM *stream, float rate); - - -SAMPLE *apeg_preload_audio(const char *filename); - -int apeg_get_stream_voice(APEG_STREAM *stream); - -void apeg_set_audio_callbacks(int (*init)(APEG_STREAM *stream, int *channels, - int *frequency, void *ptr), - int (*callback)(APEG_STREAM *stream, - void *buffer, int bytes, - void *ptr), - void *ptr); - -int apeg_downsample_audio(int mode); -void apeg_downchannel_audio(int mode); - -int apeg_set_audio_bufsize(int size); - - -extern APEG_STREAM *apeg_stream; -extern PALETTE apeg_palette; -extern char apeg_error[256]; - -#ifdef __cplusplus -} -#endif - -#endif // APEG_H diff --git a/Common/libinclude/common.h b/Common/libinclude/common.h deleted file mode 100644 index 1515b2bc781..00000000000 --- a/Common/libinclude/common.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef DISABLE_MPEG_AUDIO - -/* - * common.h - */ - -extern void print_id3_tag(unsigned char *buf); -extern unsigned long firsthead; -extern int tabsel_123[2][3][16]; -extern double compute_tpf(struct frame *fr); -extern double compute_bpf(struct frame *fr); -extern long compute_buffer_offset(struct frame *fr); - -#endif diff --git a/Common/libinclude/dumb.h b/Common/libinclude/dumb.h deleted file mode 100644 index 1271c6786e1..00000000000 --- a/Common/libinclude/dumb.h +++ /dev/null @@ -1,563 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * dumb.h - The user header file for DUMB. / / \ \ - * | < / \_ - * Include this file in any of your files in | \/ /\ / - * which you wish to use the DUMB functions \_ / > / - * and variables. | \ / / - * | ' / - * \__/ - */ - -#ifndef DUMB_H -#define DUMB_H - - -#include -#include - - -#ifdef __cplusplus - extern "C" { -#endif - - -#define DUMB_MAJOR_VERSION 0 -#define DUMB_MINOR_VERSION 9 -#define DUMB_REVISION_VERSION 2 - -#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION) - -#define DUMB_VERSION_STR "0.9.2" - -#define DUMB_NAME "DUMB v" DUMB_VERSION_STR - -#define DUMB_YEAR 2003 -#define DUMB_MONTH 4 -#define DUMB_DAY 2 - -#define DUMB_YEAR_STR2 "03" -#define DUMB_YEAR_STR4 "2003" -#define DUMB_MONTH_STR1 "4" -#define DUMB_DAY_STR1 "2" - -#if DUMB_MONTH < 10 -#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1 -#else -#define DUMB_MONTH_STR2 DUMB_MONTH_STR1 -#endif - -#if DUMB_DAY < 10 -#define DUMB_DAY_STR2 "0" DUMB_DAY_STR1 -#else -#define DUMB_DAY_STR2 DUMB_DAY_STR1 -#endif - - -/* WARNING: The month and day were inadvertently swapped in the v0.8 release. - * Please do not compare this constant against any date in 2002. In - * any case, DUMB_VERSION is probably more useful for this purpose. - */ -#define DUMB_DATE (DUMB_YEAR*10000 + DUMB_MONTH*100 + DUMB_DAY) - -#define DUMB_DATE_STR DUMB_DAY_STR1 "." DUMB_MONTH_STR1 "." DUMB_YEAR_STR4 - - -#undef MIN -#undef MAX -#undef MID - -#define MIN(x,y) (((x) < (y)) ? (x) : (y)) -#define MAX(x,y) (((x) > (y)) ? (x) : (y)) -#define MID(x,y,z) MAX((x), MIN((y), (z))) - -#undef ABS -#define ABS(x) (((x) >= 0) ? (x) : (-(x))) - - -#ifdef DEBUGMODE - -#ifndef ASSERT -#include -#define ASSERT(n) assert(n) -#endif -#ifndef TRACE -// it would be nice if this did actually trace ... -#define TRACE 1 ? (void)0 : (void)printf -#endif - -#else - -#ifndef ASSERT -#define ASSERT(n) -#endif -#ifndef TRACE -#define TRACE 1 ? (void)0 : (void)printf -#endif - -#endif - - -#define DUMB_ID(a,b,c,d) (((unsigned int)(a) << 24) | \ - ((unsigned int)(b) << 16) | \ - ((unsigned int)(c) << 8) | \ - ((unsigned int)(d) )) - - - -#ifndef LONG_LONG -#ifdef __GNUC__ -#define LONG_LONG long long -#elif defined _MSC_VER -#define LONG_LONG __int64 -#else -#error 64-bit integer type unknown -#endif -#endif - -#if __GNUC__ * 100 + __GNUC_MINOR__ >= 301 /* GCC 3.1+ */ -#ifndef DUMB_DECLARE_DEPRECATED -#define DUMB_DECLARE_DEPRECATED -#endif -#define DUMB_DEPRECATED __attribute__((__deprecated__)) -#else -#define DUMB_DEPRECATED -#endif - - -/* Basic Sample Type. Normal range is -0x800000 to 0x7FFFFF. */ - -typedef int sample_t; - - -/* Library Clean-up Management */ - -int dumb_atexit(void (*proc)(void)); - -void dumb_exit(void); - - -/* File Input Functions */ - -typedef struct DUMBFILE_SYSTEM -{ - void *(*open)(const char *filename); - int (*skip)(void *f, long n); - int (*getc)(void *f); - long (*getnc)(char *ptr, long n, void *f); - void (*close)(void *f); -} -DUMBFILE_SYSTEM; - -typedef struct DUMBFILE DUMBFILE; - -void register_dumbfile_system(DUMBFILE_SYSTEM *dfs); - -DUMBFILE *dumbfile_open(const char *filename); -DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs); - -long dumbfile_pos(DUMBFILE *f); -int dumbfile_skip(DUMBFILE *f, long n); - -int dumbfile_getc(DUMBFILE *f); - -int dumbfile_igetw(DUMBFILE *f); -int dumbfile_mgetw(DUMBFILE *f); - -long dumbfile_igetl(DUMBFILE *f); -long dumbfile_mgetl(DUMBFILE *f); - -unsigned long dumbfile_cgetul(DUMBFILE *f); -signed long dumbfile_cgetsl(DUMBFILE *f); - -long dumbfile_getnc(char *ptr, long n, DUMBFILE *f); - -int dumbfile_error(DUMBFILE *f); -int dumbfile_close(DUMBFILE *f); - - -/* stdio File Input Module */ - -void dumb_register_stdfiles(void); - -DUMBFILE *dumbfile_open_stdfile(FILE *p); - - -/* Memory File Input Module */ - -DUMBFILE *dumbfile_open_memory(const char *data, long size); - - -/* DUH Management */ - -typedef struct DUH DUH; - -#define DUH_SIGNATURE DUMB_ID('D','U','H','!') - -void unload_duh(DUH *duh); - -DUH *load_duh(const char *filename); -DUH *read_duh(DUMBFILE *f); - -long duh_get_length(DUH *duh); - - -/* Signal Rendering Functions */ - -typedef struct DUH_SIGRENDERER DUH_SIGRENDERER; - -DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos); - -#ifdef DUMB_DECLARE_DEPRECATED -typedef void (*DUH_SIGRENDERER_CALLBACK)(void *data, sample_t **samples, int n_channels, long length); -/* This is deprecated, but is not marked as such because GCC tends to - * complain spuriously when the typedef is used later. See comments below. - */ - -void duh_sigrenderer_set_callback( - DUH_SIGRENDERER *sigrenderer, - DUH_SIGRENDERER_CALLBACK callback, void *data -) DUMB_DEPRECATED; -/* The 'callback' argument's type has changed for const-correctness. See the - * DUH_SIGRENDERER_CALLBACK definition just above. Also note that the samples - * in the buffer are now 256 times as large; the normal range is -0x800000 to - * 0x7FFFFF. The function has been renamed partly because its functionality - * has changed slightly and partly so that its name is more meaningful. The - * new one is duh_sigrenderer_set_analyser_callback(), and the typedef for - * the function pointer has also changed, from DUH_SIGRENDERER_CALLBACK to - * DUH_SIGRENDERER_ANALYSER_CALLBACK. (If you wanted to use this callback to - * apply a DSP effect, don't worry; there is a better way of doing this. It - * is undocumented, so contact me and I shall try to help. Contact details - * are in readme.txt.) - */ -#endif - -typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length); - -void duh_sigrenderer_set_analyser_callback( - DUH_SIGRENDERER *sigrenderer, - DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data -); - -int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer); -long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer); - -void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer, unsigned char id, long value); - -long duh_sigrenderer_get_samples( - DUH_SIGRENDERER *sigrenderer, - float volume, float delta, - long size, sample_t **samples -); - -void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples); - -void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer); - - -/* DUH Rendering Functions */ - -long duh_render( - DUH_SIGRENDERER *sigrenderer, - int bits, int unsign, - float volume, float delta, - long size, void *sptr -); - -#ifdef DUMB_DECLARE_DEPRECATED - -long duh_render_signal( - DUH_SIGRENDERER *sigrenderer, - float volume, float delta, - long size, sample_t **samples -) DUMB_DEPRECATED; -/* Please use duh_sigrenderer_get_samples(). Arguments and functionality are - * identical. - */ - -typedef DUH_SIGRENDERER DUH_RENDERER DUMB_DEPRECATED; -/* Please use DUH_SIGRENDERER instead of DUH_RENDERER. */ - -DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) DUMB_DEPRECATED; -/* Please use duh_start_sigrenderer() instead. Pass 0 for 'sig'. */ - -int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -long duh_renderer_get_position(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -/* Please use the duh_sigrenderer_*() equivalents of these two functions. */ - -void duh_end_renderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -/* Please use duh_end_sigrenderer() instead. */ - -DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) DUMB_DEPRECATED; -DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -/* These functions have become no-ops that just return the parameter. - * So, for instance, replace - * duh_renderer_encapsulate_sigrenderer(my_sigrenderer) - * with - * my_sigrenderer - */ - -#endif - - -/* Impulse Tracker Support */ - -extern int dumb_it_max_to_mix; - -typedef struct DUMB_IT_SIGDATA DUMB_IT_SIGDATA; -typedef struct DUMB_IT_SIGRENDERER DUMB_IT_SIGRENDERER; - -DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh); -DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos); -DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer); - -DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder); - -void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); -void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); -void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char byte), void *data); - -int dumb_it_callback_terminate(void *data); -int dumb_it_callback_midi_block(void *data, int channel, unsigned char byte); - -DUH *dumb_load_it(const char *filename); -DUH *dumb_load_xm(const char *filename); -DUH *dumb_load_s3m(const char *filename); -DUH *dumb_load_mod(const char *filename); - -DUH *dumb_read_it(DUMBFILE *f); -DUH *dumb_read_xm(DUMBFILE *f); -DUH *dumb_read_s3m(DUMBFILE *f); -DUH *dumb_read_mod(DUMBFILE *f); - -int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd); - -int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv); - -int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv); - -int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed); - -int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo); - -int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel); -void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume); - -int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr); -int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr); - -int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr); -void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv); - -int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr); -void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo); - -int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr); -void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed); - -#define DUMB_IT_N_CHANNELS 64 -#define DUMB_IT_N_NNA_CHANNELS 192 -#define DUMB_IT_TOTAL_CHANNELS (DUMB_IT_N_CHANNELS + DUMB_IT_N_NNA_CHANNELS) - -/* Channels passed to any of these functions are 0-based */ -int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel); -void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume); - -typedef struct DUMB_IT_CHANNEL_STATE DUMB_IT_CHANNEL_STATE; - -struct DUMB_IT_CHANNEL_STATE -{ - int channel; /* 0-based; meaningful for NNA channels */ - int sample; /* 1-based; 0 if nothing playing, then other fields undef */ - int freq; /* in Hz */ - float volume; /* 1.0 maximum; affected by ALL factors, inc. mixing vol */ - unsigned char pan; /* 0-64, 100 for surround */ - signed char subpan; /* use (pan + subpan/256.0f) or ((pan<<8)+subpan) */ - unsigned char filter_cutoff; /* 0-127 cutoff=127 AND resonance=0 */ - unsigned char filter_subcutoff; /* 0-255 -> no filters (subcutoff */ - unsigned char filter_resonance; /* 0-127 always 0 in this case) */ - /* subcutoff only changes from zero if filter envelopes are in use. The - * calculation (filter_cutoff + filter_subcutoff/256.0f) gives a more - * accurate filter cutoff measurement as a float. It would often be more - * useful to use a scaled int such as ((cutoff<<8) + subcutoff). - */ -}; - -/* Values of 64 or more will access NNA channels here. */ -void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state); - - -/* Signal Design Helper Values */ - -/* Use pow(DUMB_SEMITONE_BASE, n) to get the 'delta' value to transpose up by - * n semitones. To transpose down, use negative n. - */ -#define DUMB_SEMITONE_BASE 1.059463094359295309843105314939748495817 - -/* Use pow(DUMB_QUARTERTONE_BASE, n) to get the 'delta' value to transpose up - * by n quartertones. To transpose down, use negative n. - */ -#define DUMB_QUARTERTONE_BASE 1.029302236643492074463779317738953977823 - -/* Use pow(DUMB_PITCH_BASE, n) to get the 'delta' value to transpose up by n - * units. In this case, 256 units represent one semitone; 3072 units - * represent one octave. These units are used by the sequence signal (SEQU). - */ -#define DUMB_PITCH_BASE 1.000225659305069791926712241547647863626 - - -/* Signal Design Function Types */ - -typedef void sigdata_t; -typedef void sigrenderer_t; - -typedef sigdata_t *(*DUH_LOAD_SIGDATA)(DUH *duh, DUMBFILE *file); - -typedef sigrenderer_t *(*DUH_START_SIGRENDERER)( - DUH *duh, - sigdata_t *sigdata, - int n_channels, - long pos -); - -typedef void (*DUH_SIGRENDERER_SET_SIGPARAM)( - sigrenderer_t *sigrenderer, - unsigned char id, long value -); - -typedef long (*DUH_SIGRENDERER_GET_SAMPLES)( - sigrenderer_t *sigrenderer, - float volume, float delta, - long size, sample_t **samples -); - -typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)( - sigrenderer_t *sigrenderer, - float volume, - sample_t *samples -); - -typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer); - -typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata); - - -/* Signal Design Function Registration */ - -typedef struct DUH_SIGTYPE_DESC -{ - long type; - DUH_LOAD_SIGDATA load_sigdata; - DUH_START_SIGRENDERER start_sigrenderer; - DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam; - DUH_SIGRENDERER_GET_SAMPLES sigrenderer_get_samples; - DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample; - DUH_END_SIGRENDERER end_sigrenderer; - DUH_UNLOAD_SIGDATA unload_sigdata; -} -DUH_SIGTYPE_DESC; - -void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc); - - -// Decide where to put these functions; new heading? - -sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type); - -DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos); -sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type); - - -/* Sample Buffer Allocation Helpers */ - -sample_t **create_sample_buffer(int n_channels, long length); -void destroy_sample_buffer(sample_t **samples); - - -/* Silencing Helper */ - -void dumb_silence(sample_t *samples, long length); - - -/* Click Removal Helpers */ - -typedef struct DUMB_CLICK_REMOVER DUMB_CLICK_REMOVER; - -DUMB_CLICK_REMOVER *dumb_create_click_remover(void); -void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step); -void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, float halflife); -sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr); -void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr); - -DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n); -void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); -void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); -void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife); -void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset); -void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr); - - -/* Resampling Helpers */ - -#define DUMB_RQ_ALIASING 0 -#define DUMB_RQ_LINEAR 1 -#define DUMB_RQ_CUBIC 2 -#define DUMB_RQ_N_LEVELS 3 -extern int dumb_resampling_quality; - -typedef struct DUMB_RESAMPLER DUMB_RESAMPLER; - -typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data); - -struct DUMB_RESAMPLER -{ - sample_t *src; - long pos; - int subpos; - long start, end; - int dir; - DUMB_RESAMPLE_PICKUP pickup; - void *pickup_data; - int min_quality; - int max_quality; - /* Everything below this point is internal: do not use. */ - sample_t x[3]; - int overshot; -}; - -void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, long pos, long start, long end); -DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, long pos, long start, long end); -long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta); -sample_t dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, float volume); -void dumb_end_resampler(DUMB_RESAMPLER *resampler); - - -/* DUH Construction */ - -DUH *make_duh( - long length, - int n_signals, - DUH_SIGTYPE_DESC *desc[], - sigdata_t *sigdata[] -); - - -#ifdef __cplusplus - } -#endif - - -#endif /* DUMB_H */ diff --git a/Common/libinclude/genre.h b/Common/libinclude/genre.h deleted file mode 100644 index 0a33fd7db70..00000000000 --- a/Common/libinclude/genre.h +++ /dev/null @@ -1,266 +0,0 @@ -#ifndef DISABLE_MPEG_AUDIO - -char *genre_table[] = -{ - "Blues", - "Classic Rock", - "Country", - "Dance", - "Disco", - "Funk", - "Grunge", - "Hip-Hop", - "Jazz", - "Metal", - "New Age", - "Oldies", - "Other", - "Pop", - "R&B", - "Rap", - "Reggae", - "Rock", - "Techno", - "Industrial", - "Alternative", - "Ska", - "Death Metal", - "Pranks", - "Soundtrack", - "Euro-Techno", - "Ambient", - "Trip-Hop", - "Vocal", - "Jazz+Funk", - "Fusion", - "Trance", - "Classical", - "Instrumental", - "Acid", - "House", - "Game", - "Sound Clip", - "Gospel", - "Noise", - "AlternRock", - "Bass", - "Soul", - "Punk", - "Space", - "Meditative", - "Instrumental Pop", - "Instrumental Rock", - "Ethnic", - "Gothic", - "Darkwave", - "Techno-Industrial", - "Electronic", - "Pop-Folk", - "Eurodance", - "Dream", - "Southern Rock", - "Comedy", - "Cult", - "Gangsta", - "Top 40", - "Christian Rap", - "Pop/Funk", - "Jungle", - "Native American", - "Cabaret", - "New Wave", - "Psychadelic", - "Rave", - "Showtunes", - "Trailer", - "Lo-Fi", - "Tribal", - "Acid Punk", - "Acid Jazz", - "Polka", - "Retro", - "Musical", - "Rock & Roll", - "Hard Rock", - "Folk", - "Folk/Rock", - "National folk", - "Swing", - "Fast-fusion", - "Bebob", - "Latin", - "Revival", - "Celtic", - "Bluegrass", - "Avantgarde", - "Gothic Rock", - "Progressive Rock", - "Psychedelic Rock", - "Symphonic Rock", - "Slow Rock", - "Big Band", - "Chorus", - "Easy Listening", - "Acoustic", - "Humour", - "Speech", - "Chanson", - "Opera", - "Chamber Music", - "Sonata", - "Symphony", - "Booty Bass", - "Primus", - "Porn Groove", - "Satire", - "Slow Jam", - "Club", - "Tango", - "Samba", - "Folklore", - "Ballad", - "Powder Ballad", - "Rhythmic Soul", - "Freestyle", - "Duet", - "Punk Rock", - "Drum Solo", - "A Capella", - "Euro-House", - "Dance Hall", - "Goa", - "Drum & Bass", - "Club House", - "Hardcore", - "Terror", - "Indie", - "BritPop", - "NegerPunk", - "Polsk Punk", - "Beat", - "Christian Gangsta", - "Heavy Metal", - "Black Metal", - "Crossover", - "Contemporary C", - "Christian Rock", - "Merengue", - "Salsa", - "Thrash Metal", - "Anime", - "JPop", - "SynthPop" -/* , - "Unknown", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" -*/ -}; -const int genre_count = ((int)(sizeof(genre_table)/sizeof(char*))-1); - -#endif diff --git a/Common/libinclude/getbits.h b/Common/libinclude/getbits.h deleted file mode 100644 index ae3e147c946..00000000000 --- a/Common/libinclude/getbits.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef DISABLE_MPEG_AUDIO - -/* that's the same file as mpg123's getits.c but with defines to - force inlining */ - -/*static unsigned long rval; -#define backbits(bitbuf,nob) ((void)( \ - (*(bitbuf)).bitindex -= (nob), \ - (*(bitbuf)).wordpointer += ((*(bitbuf)).bitindex>>3), \ - (*(bitbuf)).bitindex &= 0x7 )) -#define getbitoffset(bitbuf) ((-(*(bitbuf)).bitindex)&0x7) -#define getbyte(bitbuf) (*(*(bitbuf)).wordpointer++) -#define getbits(bitbuf,nob) ( \ - rval = (*(bitbuf)).wordpointer[0], rval <<= 8, rval |= (*(bitbuf)).wordpointer[1], \ - rval <<= 8, rval |= (*(bitbuf)).wordpointer[2], rval <<= (*(bitbuf)).bitindex, \ - rval &= 0xffffff, (*(bitbuf)).bitindex += (nob), \ - rval >>= (24-(nob)), (*(bitbuf)).wordpointer += ((*(bitbuf)).bitindex>>3), \ - (*(bitbuf)).bitindex &= 7,rval) -#define getbits_fast(bitbuf,nob) ( \ - rval = (unsigned char) ((*(bitbuf)).wordpointer[0] << (*(bitbuf)).bitindex), \ - rval |= ((unsigned long) (*(bitbuf)).wordpointer[1]<<(*(bitbuf)).bitindex)>>8, \ - rval <<= (nob), rval >>= 8, \ - (*(bitbuf)).bitindex += (nob), (*(bitbuf)).wordpointer += ((*(bitbuf)).bitindex>>3), \ - (*(bitbuf)).bitindex &= 7, rval )*/ - -/* Actually, static INLINEs should work fine. Granted, C code in - a header files is bad, but it does allow real multi-source - inlining, and the compiler should be smart enough to keep quiet - about it when certain files don't use some functions */ -static INLINE unsigned char get1bit(struct bitstream_info *bitbuf) -{ - unsigned char rval_uc = bitbuf->wordpointer[0] << bitbuf->bitindex; - bitbuf->bitindex++; - bitbuf->wordpointer += (bitbuf->bitindex>>3); - bitbuf->bitindex &= 7; - - return rval_uc >> 7; -} - - -static INLINE void backbits(struct bitstream_info *bitbuf, int nob) -{ - bitbuf->bitindex -= nob; - bitbuf->wordpointer += bitbuf->bitindex >> 3; - bitbuf->bitindex &= 0x7; -} - -static INLINE int getbitoffset(struct bitstream_info *bitbuf) -{ - return (-bitbuf->bitindex) & 0x7; -} -static INLINE unsigned char getbyte(struct bitstream_info *bitbuf) -{ - return *(bitbuf->wordpointer++); -} - -static INLINE unsigned long getbits(struct bitstream_info *bitbuf, int nob) -{ - unsigned long rval = bitbuf->wordpointer[0]; - rval = (rval << 8) | bitbuf->wordpointer[1]; - rval = (rval << 8) | bitbuf->wordpointer[2]; - rval = (rval << bitbuf->bitindex) & 0xffffff; - rval >>= (24-nob); - - bitbuf->bitindex += nob; - - bitbuf->wordpointer += (bitbuf->bitindex >> 3); - bitbuf->bitindex &= 7; - - return rval; -} - -static INLINE unsigned long getbits_fast(struct bitstream_info *bitbuf, int nob) -{ - unsigned long rval = (bitbuf->wordpointer[0] << bitbuf->bitindex) & 0xFF; - rval |= (unsigned long)(bitbuf->wordpointer[1] << bitbuf->bitindex) >> 8; - rval <<= nob; - rval >>= 8; - - bitbuf->bitindex += nob; - bitbuf->wordpointer += bitbuf->bitindex >> 3; - bitbuf->bitindex &= 7; - - return rval; -} - -#endif diff --git a/Common/libinclude/getblk.h b/Common/libinclude/getblk.h deleted file mode 100644 index 1cb8acac81a..00000000000 --- a/Common/libinclude/getblk.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef GETBLK_H -#define GETBLK_H - -typedef struct { - char val, len; -} VLCtab; - -typedef struct { - char run, level, len; -} DCTtab; - -/* Table B-14, DCT coefficients table zero, - * codes 0100 ... 1xxx (used for first (DC) coefficient) - */ -static const DCTtab DCTtabfirst[12] = { - {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, - {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, - {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1} -}; - -/* Table B-14, DCT coefficients table zero, - * codes 0100 ... 1xxx (used for all other coefficients) - */ -static const DCTtab DCTtabnext[12] = { - {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, - {64,0,2}, {64,0,2}, {64,0,2}, {64,0,2}, /* EOB */ - {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2} -}; - -/* Table B-14, DCT coefficients table zero, - * codes 000001xx ... 00111xxx - */ -static const DCTtab DCTtab0[60] = { - {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ - {2,2,7}, {2,2,7}, {9,1,7}, {9,1,7}, - {0,4,7}, {0,4,7}, {8,1,7}, {8,1,7}, - {7,1,6}, {7,1,6}, {7,1,6}, {7,1,6}, - {6,1,6}, {6,1,6}, {6,1,6}, {6,1,6}, - {1,2,6}, {1,2,6}, {1,2,6}, {1,2,6}, - {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, - {13,1,8}, {0,6,8}, {12,1,8}, {11,1,8}, - {3,2,8}, {1,3,8}, {0,5,8}, {10,1,8}, - {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, - {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, - {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, - {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, - {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, - {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5} -}; - -/* Table B-14, DCT coefficients table zero, - * codes 0000001000 ... 0000001111 - */ -static const DCTtab DCTtab1[8] = { - {16,1,10}, {5,2,10}, {0,7,10}, {2,3,10}, - {1,4,10}, {15,1,10}, {14,1,10}, {4,2,10} -}; - -/* Table B-14/15, DCT coefficients table zero / one, - * codes 000000010000 ... 000000011111 - */ -static const DCTtab DCTtab2[16] = { - {0,11,12}, {8,2,12}, {4,3,12}, {0,10,12}, - {2,4,12}, {7,2,12}, {21,1,12}, {20,1,12}, - {0,9,12}, {19,1,12}, {18,1,12}, {1,5,12}, - {3,3,12}, {0,8,12}, {6,2,12}, {17,1,12} -}; - -/* Table B-14/15, DCT coefficients table zero / one, - * codes 0000000010000 ... 0000000011111 - */ -static const DCTtab DCTtab3[16] = { - {10,2,13}, {9,2,13}, {5,3,13}, {3,4,13}, - {2,5,13}, {1,7,13}, {1,6,13}, {0,15,13}, - {0,14,13}, {0,13,13}, {0,12,13}, {26,1,13}, - {25,1,13}, {24,1,13}, {23,1,13}, {22,1,13} -}; - -/* Table B-14/15, DCT coefficients table zero / one, - * codes 00000000010000 ... 00000000011111 - */ -static const DCTtab DCTtab4[16] = { - {0,31,14}, {0,30,14}, {0,29,14}, {0,28,14}, - {0,27,14}, {0,26,14}, {0,25,14}, {0,24,14}, - {0,23,14}, {0,22,14}, {0,21,14}, {0,20,14}, - {0,19,14}, {0,18,14}, {0,17,14}, {0,16,14} -}; - -/* Table B-14/15, DCT coefficients table zero / one, - * codes 000000000010000 ... 000000000011111 - */ -static const DCTtab DCTtab5[16] = { - {0,40,15}, {0,39,15}, {0,38,15}, {0,37,15}, - {0,36,15}, {0,35,15}, {0,34,15}, {0,33,15}, - {0,32,15}, {1,14,15}, {1,13,15}, {1,12,15}, - {1,11,15}, {1,10,15}, {1,9,15}, {1,8,15} -}; - -/* Table B-14/15, DCT coefficients table zero / one, - * codes 0000000000010000 ... 0000000000011111 - */ -static const DCTtab DCTtab6[16] = { - {1,18,16}, {1,17,16}, {1,16,16}, {1,15,16}, - {6,3,16}, {16,2,16}, {15,2,16}, {14,2,16}, - {13,2,16}, {12,2,16}, {11,2,16}, {31,1,16}, - {30,1,16}, {29,1,16}, {28,1,16}, {27,1,16} -}; - -#endif diff --git a/Common/libinclude/huffman.h b/Common/libinclude/huffman.h deleted file mode 100644 index 3c8b1c7173d..00000000000 --- a/Common/libinclude/huffman.h +++ /dev/null @@ -1,334 +0,0 @@ -#ifndef DISABLE_MPEG_AUDIO - -/* - * huffman tables ... recalcualted to work with my optimzed - * decoder scheme (MH) - * - * probably we could save a few bytes of memory, because the - * smaller tables are often the part of a bigger table - */ - -struct newhuff -{ - unsigned int linbits; - short *table; -}; - -static short tab0[] = -{ - 0 -}; - -static short tab1[] = -{ - -5, -3, -1, 17, 1, 16, 0 -}; - -static short tab2[] = -{ - -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, - 16, 0 -}; - -static short tab3[] = -{ - -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, - 1, 0 -}; - -static short tab5[] = -{ - -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, - 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, - 0 -}; - -static short tab6[] = -{ - -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, - 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, - 0 -}; - -static short tab7[] = -{ - -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, - -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, - 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, - -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, - -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 -}; - -static short tab8[] = -{ - -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, - -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, - 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, - 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, - 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 -}; - -static short tab9[] = -{ - -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, - 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, - -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, - -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, - 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 -}; - -static short tab10[] = -{ --125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, - 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, - -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, - 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, - -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, - -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, - -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, - 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, - 2, 32, 17, -1, 1, 16, 0 -}; - -static short tab11[] = -{ --121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, - -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, - -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, - -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, - -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, - 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, - 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, - -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, - 32, 17, -3, -1, 1, 16, 0 -}; - -static short tab12[] = -{ --115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, - 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, - 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, - 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, - -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, - 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, - 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, - -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, - 2, 32, 0, 17, -1, 1, 16 -}; - -static short tab13[] = -{ --509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, - -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, - 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, - 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, - 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, - -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, - 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, - 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, - 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, - -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, - 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, - 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, - 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, - -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, - 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, - -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, - 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, - 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, - 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, - -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, - -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, - -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, - 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, - -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, - -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, - 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, - 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, - 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, - -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, - -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, - 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, - -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, - -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, - -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, - 0 -}; - -static short tab15[] = -{ --495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, - -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, - 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, - -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, - -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, - -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, - -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, - -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, - 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, - 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, - 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, - -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, - -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, - 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, - 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, - -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, - -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, - 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, - -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, - -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, - -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, - -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, - 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, - 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, - -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, - -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, - -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, - -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, - 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, - -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, - -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, - 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, - 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, - 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, - 0 -}; - -static short tab16[] = -{ --509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, - 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, - -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, - -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, - -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, - 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, - -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, - 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, - -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, - -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, - -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, - 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, - -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, - -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, - 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, - 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, - 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, - -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, - -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, - -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, - 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, - 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, - -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, - -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, - -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, - 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, - -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, - 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, - -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, - 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, - -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, - -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, - -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, - 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, - 0 -}; - -static short tab24[] = -{ --451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, - 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, - -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, - 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, - 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, - 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, - -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, - -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, --143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, - -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, - -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, - 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, - 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, - 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, - -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, - -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, - -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, - 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, - 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, - 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, - 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, - 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, - -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, - -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, - -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, - -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, - -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, - 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, - -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, - -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, - 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, - 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, - -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, - 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, - 0 -}; - -static short tab_c0[] = -{ - -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, - 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, - 0 -}; - -static short tab_c1[] = -{ - -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, - 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, - 0 -}; - - - -static struct newhuff ht[] = -{ - { /* 0 */ 0 , tab0 } , - { /* 2 */ 0 , tab1 } , - { /* 3 */ 0 , tab2 } , - { /* 3 */ 0 , tab3 } , - { /* 0 */ 0 , tab0 } , - { /* 4 */ 0 , tab5 } , - { /* 4 */ 0 , tab6 } , - { /* 6 */ 0 , tab7 } , - { /* 6 */ 0 , tab8 } , - { /* 6 */ 0 , tab9 } , - { /* 8 */ 0 , tab10 } , - { /* 8 */ 0 , tab11 } , - { /* 8 */ 0 , tab12 } , - { /* 16 */ 0 , tab13 } , - { /* 0 */ 0 , tab0 } , - { /* 16 */ 0 , tab15 } , - - { /* 16 */ 1 , tab16 } , - { /* 16 */ 2 , tab16 } , - { /* 16 */ 3 , tab16 } , - { /* 16 */ 4 , tab16 } , - { /* 16 */ 6 , tab16 } , - { /* 16 */ 8 , tab16 } , - { /* 16 */ 10, tab16 } , - { /* 16 */ 13, tab16 } , - { /* 16 */ 4 , tab24 } , - { /* 16 */ 5 , tab24 } , - { /* 16 */ 6 , tab24 } , - { /* 16 */ 7 , tab24 } , - { /* 16 */ 8 , tab24 } , - { /* 16 */ 9 , tab24 } , - { /* 16 */ 11, tab24 } , - { /* 16 */ 13, tab24 } -}; - -static struct newhuff htc[] = -{ - { /* 1 , 1 , */ 0 , tab_c0 } , - { /* 1 , 1 , */ 0 , tab_c1 } -}; - -#endif diff --git a/Common/libinclude/internal/aldumb.h b/Common/libinclude/internal/aldumb.h deleted file mode 100644 index a0c6d63c075..00000000000 --- a/Common/libinclude/internal/aldumb.h +++ /dev/null @@ -1,27 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * internal/aldumb.h - The internal header file / / \ \ - * for DUMB with Allegro. | < / \_ - * | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#ifndef INTERNAL_ALDUMB_H -#define INTERNAL_ALDUMB_H - - -void _dat_unload_duh(void *duh); - - -#endif /* INTERNAL_DUMB_H */ diff --git a/Common/libinclude/internal/dumb.h b/Common/libinclude/internal/dumb.h deleted file mode 100644 index b4cd0ab1c4d..00000000000 --- a/Common/libinclude/internal/dumb.h +++ /dev/null @@ -1,58 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * internal/dumb.h - DUMB's internal declarations. / / \ \ - * | < / \_ - * This header file provides access to the | \/ /\ / - * internal structure of DUMB, and is liable \_ / > / - * to change, mutate or cease to exist at any | \ / / - * moment. Include it at your own peril. | ' / - * \__/ - * ... - * - * I mean it, people. You don't need access to anything in this file. If you - * disagree, contact the authors. In the unlikely event that you make a good - * case, we'll add what you need to dumb.h. Thanking you kindly. - */ - -#ifndef INTERNAL_DUMB_H -#define INTERNAL_DUMB_H - - -typedef struct DUH_SIGTYPE_DESC_LINK -{ - struct DUH_SIGTYPE_DESC_LINK *next; - DUH_SIGTYPE_DESC *desc; -} -DUH_SIGTYPE_DESC_LINK; - - -typedef struct DUH_SIGNAL -{ - sigdata_t *sigdata; - DUH_SIGTYPE_DESC *desc; -} -DUH_SIGNAL; - - -struct DUH -{ - long length; - - int n_signals; - DUH_SIGNAL **signal; -}; - - -DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type); - - -#endif /* INTERNAL_DUMB_H */ - diff --git a/Common/libinclude/internal/it.h b/Common/libinclude/internal/it.h deleted file mode 100644 index 7fffed6e6ba..00000000000 --- a/Common/libinclude/internal/it.h +++ /dev/null @@ -1,710 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * internal/it.h - Internal stuff for IT playback / / \ \ - * and MOD/XM/S3M conversion. | < / \_ - * | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#ifndef INTERNAL_IT_H -#define INTERNAL_IT_H - - - -#include - - - -/** TO DO: THINK ABOUT THE FOLLOWING: - -sigdata->flags & IT_COMPATIBLE_GXX - - Bit 5: On = Link Effect G's memory with Effect E/F. Also - Gxx with an instrument present will cause the - envelopes to be retriggered. If you change a - sample on a row with Gxx, it'll adjust the - frequency of the current note according to: - - NewFrequency = OldFrequency * NewC5 / OldC5; -*/ - - - -/* These #defines are TEMPORARY. They are used to write alternative code to - * handle ambiguities in the format specification. The correct code in each - * case will be determined most likely by experimentation. - */ -#define STEREO_SAMPLES_COUNT_AS_TWO -#define INVALID_ORDERS_END_SONG -#define INVALID_NOTES_CAUSE_NOTE_CUT -#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP -#define VOLUME_OUT_OF_RANGE_SETS_MAXIMUM - - - -#define SIGTYPE_IT DUMB_ID('I', 'T', ' ', ' ') - -#define IT_SIGNATURE DUMB_ID('I', 'M', 'P', 'M') -#define IT_INSTRUMENT_SIGNATURE DUMB_ID('I', 'M', 'P', 'I') -#define IT_SAMPLE_SIGNATURE DUMB_ID('I', 'M', 'P', 'S') - - - -/* 1 minute per 4 rows, each row 6 ticks; this is divided by the tempo to get - * the interval between ticks. - */ -#define TICK_TIME_DIVIDEND ((65536 * 60) / (4 * 6)) - - - -/* I'm not going to try to explain this, because I didn't derive it very - * formally ;) - */ -/* #define AMIGA_DIVISOR ((float)(4.0 * 14317056.0)) */ -/* I believe the following one to be more accurate. */ -#define AMIGA_DIVISOR ((float)(8.0 * 7159090.5)) - - - -typedef struct IT_MIDI IT_MIDI; -typedef struct IT_FILTER_STATE IT_FILTER_STATE; -typedef struct IT_ENVELOPE IT_ENVELOPE; -typedef struct IT_INSTRUMENT IT_INSTRUMENT; -typedef struct IT_SAMPLE IT_SAMPLE; -typedef struct IT_ENTRY IT_ENTRY; -typedef struct IT_PATTERN IT_PATTERN; -typedef struct IT_PLAYING_ENVELOPE IT_PLAYING_ENVELOPE; -typedef struct IT_PLAYING IT_PLAYING; -typedef struct IT_CHANNEL IT_CHANNEL; -typedef struct IT_CHECKPOINT IT_CHECKPOINT; -typedef struct IT_CALLBACKS IT_CALLBACKS; - - - -struct IT_MIDI -{ - unsigned char SFmacro[16][16]; // read these from 0x120 - unsigned char SFmacrolen[16]; - unsigned short SFmacroz[16]; /* Bitfield; bit 0 set = z in first position */ - unsigned char Zmacro[128][16]; // read these from 0x320 - unsigned char Zmacrolen[128]; -}; - - - -struct IT_FILTER_STATE -{ - float currsample, prevsample; -}; - - - -#define IT_ENVELOPE_ON 1 -#define IT_ENVELOPE_LOOP_ON 2 -#define IT_ENVELOPE_SUSTAIN_LOOP 4 -#define IT_ENVELOPE_PITCH_IS_FILTER 128 - -struct IT_ENVELOPE -{ - unsigned char flags; - unsigned char n_nodes; - unsigned char loop_start; - unsigned char loop_end; - unsigned char sus_loop_start; - unsigned char sus_loop_end; - signed char node_y[25]; - unsigned short node_t[25]; -}; - - - -#define NNA_NOTE_CUT 0 -#define NNA_NOTE_CONTINUE 1 -#define NNA_NOTE_OFF 2 -#define NNA_NOTE_FADE 3 - -#define DCT_OFF 0 -#define DCT_NOTE 1 -#define DCT_SAMPLE 2 -#define DCT_INSTRUMENT 3 - -#define DCA_NOTE_CUT 0 -#define DCA_NOTE_OFF 1 -#define DCA_NOTE_FADE 2 - -struct IT_INSTRUMENT -{ - int fadeout; - - IT_ENVELOPE volume_envelope; - IT_ENVELOPE pan_envelope; - IT_ENVELOPE pitch_envelope; - - unsigned char new_note_action; - unsigned char dup_check_type; - unsigned char dup_check_action; - unsigned char pp_separation; - unsigned char pp_centre; - unsigned char global_volume; - unsigned char default_pan; - unsigned char random_volume; - unsigned char random_pan; - - unsigned char filter_cutoff; - unsigned char filter_resonance; - - unsigned char map_note[120]; - unsigned short map_sample[120]; -}; - - - -#define IT_SAMPLE_EXISTS 1 -#define IT_SAMPLE_16BIT 2 -#define IT_SAMPLE_STEREO 4 -#define IT_SAMPLE_LOOP 16 -#define IT_SAMPLE_SUS_LOOP 32 -#define IT_SAMPLE_PINGPONG_LOOP 64 -#define IT_SAMPLE_PINGPONG_SUS_LOOP 128 - -#define IT_VIBRATO_SINE 0 -#define IT_VIBRATO_SAWTOOTH 1 /* Ramp down */ -#define IT_VIBRATO_SQUARE 2 -#define IT_VIBRATO_RANDOM 3 - -struct IT_SAMPLE -{ - unsigned char flags; - unsigned char global_volume; - unsigned char default_volume; - unsigned char default_pan; - - long length; - long loop_start; - long loop_end; - long C5_speed; - long sus_loop_start; - long sus_loop_end; - - unsigned char vibrato_speed; - unsigned char vibrato_depth; - unsigned char vibrato_rate; - unsigned char vibrato_waveform; - - sample_t *left; - sample_t *right; -}; - - - -#define IT_ENTRY_NOTE 1 -#define IT_ENTRY_INSTRUMENT 2 -#define IT_ENTRY_VOLPAN 4 -#define IT_ENTRY_EFFECT 8 - -#define IT_SET_END_ROW(entry) ((entry)->channel = 255) -#define IT_IS_END_ROW(entry) ((entry)->channel >= DUMB_IT_N_CHANNELS) - -#define IT_NOTE_OFF 255 -#define IT_NOTE_CUT 254 - -#define IT_ENVELOPE_SHIFT 8 - -#define IT_SURROUND 100 -#define IT_IS_SURROUND(pan) ((pan) > 64) -#define IT_IS_SURROUND_SHIFTED(pan) ((pan) > 64 << IT_ENVELOPE_SHIFT) - -#define IT_SET_SPEED 1 -#define IT_JUMP_TO_ORDER 2 -#define IT_BREAK_TO_ROW 3 -#define IT_VOLUME_SLIDE 4 -#define IT_PORTAMENTO_DOWN 5 -#define IT_PORTAMENTO_UP 6 -#define IT_TONE_PORTAMENTO 7 -#define IT_VIBRATO 8 -#define IT_TREMOR 9 -#define IT_ARPEGGIO 10 -#define IT_VOLSLIDE_VIBRATO 11 -#define IT_VOLSLIDE_TONEPORTA 12 -#define IT_SET_CHANNEL_VOLUME 13 -#define IT_CHANNEL_VOLUME_SLIDE 14 -#define IT_SET_SAMPLE_OFFSET 15 -#define IT_PANNING_SLIDE 16 -#define IT_RETRIGGER_NOTE 17 -#define IT_TREMOLO 18 -#define IT_S 19 -#define IT_SET_SONG_TEMPO 20 -#define IT_FINE_VIBRATO 21 -#define IT_SET_GLOBAL_VOLUME 22 -#define IT_GLOBAL_VOLUME_SLIDE 23 -#define IT_SET_PANNING 24 -#define IT_PANBRELLO 25 -#define IT_MIDI_MACRO 26 //see MIDI.TXT - -/* Some effects needed for XM compatibility */ -#define IT_XM_PORTAMENTO_DOWN 27 -#define IT_XM_PORTAMENTO_UP 28 -#define IT_XM_FINE_VOLSLIDE_DOWN 29 -#define IT_XM_FINE_VOLSLIDE_UP 30 -#define IT_XM_RETRIGGER_NOTE 31 - -#define IT_N_EFFECTS 32 - -/* These represent the top nibble of the command value. */ -#define IT_S_SET_FILTER 0 /* Greyed out in IT... */ -#define IT_S_SET_GLISSANDO_CONTROL 1 /* Greyed out in IT... */ -#define IT_S_FINETUNE 2 /* Greyed out in IT... */ -#define IT_S_SET_VIBRATO_WAVEFORM 3 -#define IT_S_SET_TREMOLO_WAVEFORM 4 -#define IT_S_SET_PANBRELLO_WAVEFORM 5 -#define IT_S_FINE_PATTERN_DELAY 6 -#define IT_S7 7 -#define IT_S_SET_PAN 8 -#define IT_S_SET_SURROUND_SOUND 9 -#define IT_S_SET_HIGH_OFFSET 10 -#define IT_S_PATTERN_LOOP 11 -#define IT_S_DELAYED_NOTE_CUT 12 -#define IT_S_NOTE_DELAY 13 -#define IT_S_PATTERN_DELAY 14 -#define IT_S_SET_MIDI_MACRO 15 - -/* -S0x Set filter -S1x Set glissando control -S2x Set finetune - - -S3x Set vibrato waveform to type x -S4x Set tremelo waveform to type x -S5x Set panbrello waveform to type x - Waveforms for commands S3x, S4x and S5x: - 0: Sine wave - 1: Ramp down - 2: Square wave - 3: Random wave -S6x Pattern delay for x ticks -S70 Past note cut -S71 Past note off -S72 Past note fade -S73 Set NNA to note cut -S74 Set NNA to continue -S75 Set NNA to note off -S76 Set NNA to note fade -S77 Turn off volume envelope -S78 Turn on volume envelope -S79 Turn off panning envelope -S7A Turn on panning envelope -S7B Turn off pitch envelope -S7C Turn on pitch envelope -S8x Set panning position -S91 Set surround sound -SAy Set high value of sample offset yxx00h -SB0 Set loopback point -SBx Loop x times to loopback point -SCx Note cut after x ticks -SDx Note delay for x ticks -SEx Pattern delay for x rows -SFx Set parameterised MIDI Macro -*/ - -struct IT_ENTRY -{ - unsigned char channel; /* End of row if channel >= DUMB_IT_N_CHANNELS */ - unsigned char mask; - unsigned char note; - unsigned char instrument; - unsigned char volpan; - unsigned char effect; - unsigned char effectvalue; -}; - - - -struct IT_PATTERN -{ - int n_rows; - int n_entries; - IT_ENTRY *entry; -}; - - - -#define IT_STEREO 1 -#define IT_USE_INSTRUMENTS 4 -#define IT_LINEAR_SLIDES 8 /* If not set, use Amiga slides */ -#define IT_OLD_EFFECTS 16 -#define IT_COMPATIBLE_GXX 32 - -/* Make sure IT_WAS_AN_XM and IT_WAS_A_MOD aren't set accidentally */ -#define IT_REAL_FLAGS 63 - -#define IT_WAS_AN_XM 64 /* Set for both XMs and MODs */ -#define IT_WAS_A_MOD 128 - -#define IT_ORDER_END 255 -#define IT_ORDER_SKIP 254 - -struct DUMB_IT_SIGDATA -{ - int n_orders; - int n_instruments; - int n_samples; - int n_patterns; - - int flags; - - int global_volume; - int mixing_volume; - int speed; - int tempo; - int pan_separation; - - unsigned char channel_pan[DUMB_IT_N_CHANNELS]; - unsigned char channel_volume[DUMB_IT_N_CHANNELS]; - - unsigned char *order; - unsigned char restart_position; /* for XM compatiblity */ - - IT_INSTRUMENT *instrument; - IT_SAMPLE *sample; - IT_PATTERN *pattern; - - IT_MIDI *midi; - - IT_CHECKPOINT *checkpoint; -}; - - - -struct IT_PLAYING_ENVELOPE -{ - int next_node; - int tick; -}; - - - -#define IT_PLAYING_BACKGROUND 1 -#define IT_PLAYING_SUSTAINOFF 2 -#define IT_PLAYING_FADING 4 -#define IT_PLAYING_DEAD 8 - -struct IT_PLAYING -{ - int flags; - - IT_CHANNEL *channel; - IT_SAMPLE *sample; - IT_INSTRUMENT *instrument; - IT_INSTRUMENT *env_instrument; - - unsigned short sampnum; - unsigned char instnum; - - unsigned char channel_volume; - - unsigned char volume; - unsigned short pan; - - unsigned char note; - - unsigned char filter_cutoff; - unsigned char filter_resonance; - - unsigned short true_filter_cutoff; /* These incorporate the filter envelope, and will not */ - unsigned char true_filter_resonance; /* be changed if they would be set to 127<<8 and 0. */ - - unsigned char vibrato_speed; - unsigned char vibrato_depth; - unsigned char vibrato_n; /* May be specified twice: volpan & effect. */ - unsigned char vibrato_time; - - unsigned char tremolo_speed; - unsigned char tremolo_depth; - unsigned char tremolo_time; - - unsigned char sample_vibrato_time; - int sample_vibrato_depth; /* Starts at rate?0:depth, increases by rate */ - - int slide; - float delta; - - IT_PLAYING_ENVELOPE volume_envelope; - IT_PLAYING_ENVELOPE pan_envelope; - IT_PLAYING_ENVELOPE pitch_envelope; - - int fadeoutcount; - - IT_FILTER_STATE filter_state[2]; /* Left and right */ - - DUMB_RESAMPLER resampler[2]; - - /* time_lost is used to emulate Impulse Tracker's sample looping - * characteristics. When time_lost is added to pos, the result represents - * the position in the theoretical version of the sample where all loops - * have been expanded. If this is stored, the resampling helpers will - * safely convert it for use with new loop boundaries. The situation is - * slightly more complicated if dir == -1 when the change takes place; we - * must reflect pos off the loop end point and set dir to 1 before - * proceeding. - */ - long time_lost; -}; - - - -#define IT_CHANNEL_MUTED 1 - -struct IT_CHANNEL -{ - int flags; - - unsigned char volume; - signed char volslide; - signed char xm_volslide; - - /* xm_volslide is used for volume slides done in the volume column in an - * XM file, since it seems the volume column slide is applied first, - * followed by clamping, followed by the effects column slide. IT does - * not exhibit this behaviour, so xm_volslide is maintained at zero. - */ - - unsigned char pan; - unsigned short truepan; - - unsigned char channelvolume; - signed char channelvolslide; - - unsigned char instrument; - unsigned char note; - - unsigned char SFmacro; - - unsigned char filter_cutoff; - unsigned char filter_resonance; - - unsigned char note_cut_count; - unsigned char note_delay_count; - IT_ENTRY *note_delay_entry; - - int arpeggio; - unsigned char retrig; - unsigned char xm_retrig; - int retrig_tick; - - unsigned char tremor; - unsigned char tremor_time; /* Bit 6 set if note on; bit 7 set if tremor active. */ - - int portamento; - int toneporta; - unsigned char destnote; - - /** WARNING - for neatness, should one or both of these be in the IT_PLAYING struct? */ - unsigned short sample; - unsigned char truenote; - - unsigned char midi_state; - - signed char lastvolslide; - unsigned char lastDKL; - unsigned char lastEF; /* Doubles as last portamento up for XM files */ - unsigned char lastG; - unsigned char lastHspeed; - unsigned char lastHdepth; - unsigned char lastRspeed; - unsigned char lastRdepth; - unsigned char lastI; - unsigned char lastJ; /* Doubles as last portamento down for XM files */ - unsigned char lastN; - unsigned char lastO; - unsigned char high_offset; - unsigned char lastQ; - unsigned char lastS; - unsigned char pat_loop_row; - unsigned char pat_loop_count; - unsigned char lastW; - - unsigned char xm_lastE1; - unsigned char xm_lastE2; - unsigned char xm_lastEA; - unsigned char xm_lastEB; - unsigned char xm_lastX1; - unsigned char xm_lastX2; - - IT_PLAYING *playing; -}; - - - -struct DUMB_IT_SIGRENDERER -{ - DUMB_IT_SIGDATA *sigdata; - - int n_channels; - - unsigned char globalvolume; - signed char globalvolslide; - - unsigned char tempo; - signed char temposlide; - - IT_CHANNEL channel[DUMB_IT_N_CHANNELS]; - - IT_PLAYING *playing[DUMB_IT_N_NNA_CHANNELS]; - - int tick; - int speed; - int rowcount; - - int order; /* Set to -1 if the song is terminated by a callback. */ - int row; - int processorder; - int processrow; - int breakrow; - int pat_loop_row; - - int n_rows; - - IT_ENTRY *entry_start; - IT_ENTRY *entry; - IT_ENTRY *entry_end; - - long time_left; /* Time before the next tick is processed */ - int sub_time_left; - - DUMB_CLICK_REMOVER **click_remover; - - IT_CALLBACKS *callbacks; -}; - - - -struct IT_CHECKPOINT -{ - IT_CHECKPOINT *next; - long time; - DUMB_IT_SIGRENDERER *sigrenderer; -}; - - - -struct IT_CALLBACKS -{ - int (*loop)(void *data); - void *loop_data; - /* Return 1 to prevent looping; the music will terminate abruptly. If you - * want to make the music stop but allow samples to fade (beware, as they - * might not fade at all!), use dumb_it_sr_set_speed() and set the speed - * to 0. Note that xm_speed_zero() will not be called if you set the - * speed manually, and also that this will work for IT and S3M files even - * though the music can't stop in this way by itself. - */ - - int (*xm_speed_zero)(void *data); - void *xm_speed_zero_data; - /* Return 1 to terminate the mod, without letting samples fade. */ - - int (*midi)(void *data, int channel, unsigned char byte); - void *midi_data; - /* Return 1 to prevent DUMB from subsequently interpreting the MIDI bytes - * itself. In other words, return 1 if the Zxx macros in an IT file are - * controlling filters and shouldn't be. - */ -}; - - - -void _dumb_it_end_sigrenderer(sigrenderer_t *sigrenderer); -void _dumb_it_unload_sigdata(sigdata_t *vsigdata); - -extern DUH_SIGTYPE_DESC _dumb_sigtype_it; - - - -long _dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata); - - - -#define XM_APPREGIO 0 -#define XM_PORTAMENTO_UP 1 -#define XM_PORTAMENTO_DOWN 2 -#define XM_TONE_PORTAMENTO 3 -#define XM_VIBRATO 4 -#define XM_VOLSLIDE_TONEPORTA 5 -#define XM_VOLSLIDE_VIBRATO 6 -#define XM_TREMOLO 7 -#define XM_SET_PANNING 8 -#define XM_SAMPLE_OFFSET 9 -#define XM_VOLUME_SLIDE 10 /* A */ -#define XM_POSITION_JUMP 11 /* B */ -#define XM_SET_CHANNEL_VOLUME 12 /* C */ -#define XM_PATTERN_BREAK 13 /* D */ -#define XM_E 14 /* E */ -#define XM_SET_TEMPO_BPM 15 /* F */ -#define XM_SET_GLOBAL_VOLUME 16 /* G */ -#define XM_GLOBAL_VOLUME_SLIDE 17 /* H */ -#define XM_KEY_OFF 20 /* K (undocumented) */ -#define XM_SET_ENVELOPE_POSITION 21 /* L */ -#define XM_PANNING_SLIDE 25 /* P */ -#define XM_MULTI_RETRIG 27 /* R */ -#define XM_TREMOR 29 /* T */ -#define XM_X 33 /* X */ -#define XM_N_EFFECTS (10+26) - -#define XM_E_SET_FILTER 0x0 -#define XM_E_FINE_PORTA_UP 0x1 -#define XM_E_FINE_PORTA_DOWN 0x2 -#define XM_E_SET_GLISSANDO_CONTROL 0x3 -#define XM_E_SET_VIBRATO_CONTROL 0x4 -#define XM_E_SET_FINETUNE 0x5 -#define XM_E_SET_LOOP 0x6 -#define XM_E_SET_TREMOLO_CONTROL 0x7 -#define XM_E_RETRIG_NOTE 0x9 -#define XM_E_FINE_VOLSLIDE_UP 0xA -#define XM_E_FINE_VOLSLIDE_DOWN 0xB -#define XM_E_NOTE_CUT 0xC -#define XM_E_NOTE_DELAY 0xD -#define XM_E_PATTERN_DELAY 0xE - -#define XM_X_EXTRAFINE_PORTA_UP 1 -#define XM_X_EXTRAFINE_PORTA_DOWN 2 - -/* To make my life a bit simpler during conversion, effect E:xy is converted - * to effect number EBASE+x:y. The same applies to effect X, and IT's S. That - * way, these effects can be manipulated like regular effects. - */ -#define EBASE (XM_N_EFFECTS) -#define XBASE (EBASE+16) -#define SBASE (IT_N_EFFECTS) - -#define EFFECT_VALUE(x, y) (((x)<<4)|(y)) -#define HIGH(v) ((v)>>4) -#define LOW(v) ((v)&0x0F) -#define SET_HIGH(v, x) v = (((x)<<4)|((v)&0x0F)) -#define SET_LOW(v, y) v = (((v)&0xF0)|(y)) -#define BCD_TO_NORMAL(v) (HIGH(v)*10+LOW(v)) - - - -#if 0 -unsigned char **_dumb_malloc2(int w, int h); -void _dumb_free2(unsigned char **line); -#endif - -void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry); -int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata); - - - -#endif /* INTERNAL_IT_H */ diff --git a/Common/libinclude/l2tables.h b/Common/libinclude/l2tables.h deleted file mode 100644 index 1b5c63c9d9e..00000000000 --- a/Common/libinclude/l2tables.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef DISABLE_MPEG_AUDIO - -/* - * Layer 2 Alloc tables .. - * most other tables are calculated on program start (which is (of course) - * not ISO-conform) .. - * Layer-3 huffman table is in huffman.h - */ - -struct al_table alloc_0[] = { - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767} }; - -struct al_table alloc_1[] = { - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767} }; - -struct al_table alloc_2[] = { - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; - -struct al_table alloc_3[] = { - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; - -struct al_table alloc_4[] = { - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9} -}; - -#endif diff --git a/Common/libinclude/libcda.h b/Common/libinclude/libcda.h deleted file mode 100644 index 201e459536c..00000000000 --- a/Common/libinclude/libcda.h +++ /dev/null @@ -1,48 +0,0 @@ -/* This file is part of libcda. See COPYING for licence. - * - * Peter Wang - */ - -#ifndef __included_libcda_h -#define __included_libcda_h - -#ifdef __cplusplus -extern "C" { -#endif - - -/* High-byte is major version, low-byte is minor. */ -#define LIBCDA_VERSION 0x0004 -#define LIBCDA_VERSION_STR "0.4" - - -extern const char *cd_error; - - -int cd_init(void); -void cd_exit(void); - -int cd_play(int track); -int cd_play_range(int start, int end); -int cd_play_from(int track); -int cd_current_track(void); -void cd_pause(void); -void cd_resume(void); -int cd_is_paused(void); -void cd_stop(void); - -int cd_get_tracks(int *first, int *last); -int cd_is_audio(int track); - -void cd_get_volume(int *c0, int *c1); -void cd_set_volume(int c0, int c1); - -void cd_eject(void); -void cd_close(void); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Common/libinclude/mpeg1dec.h b/Common/libinclude/mpeg1dec.h deleted file mode 100644 index 91abac49068..00000000000 --- a/Common/libinclude/mpeg1dec.h +++ /dev/null @@ -1,236 +0,0 @@ -/* mpeg1dec.h, internal defines */ -#ifndef MPEG1DEC_H -#define MPEG1DEC_H - -#include - -#include "apeg.h" -#include "mpg123.h" - -#define PICTURE_START_CODE 0x100 - -#define SLICE_START_CODE_MIN 0x101 -#define SLICE_START_CODE_MAX 0x1AF - -#define SEQUENCE_HEADER_CODE 0x1B3 -#define SEQUENCE_END_CODE 0x1B7 -#define GROUP_START_CODE 0x1B8 - -#define SYSTEM_START_CODE_MIN 0x1B9 -#define ISO_END_CODE 0x1B9 -#define PACK_START_CODE 0x1BA -#define SYSTEM_START_CODE 0x1BB -#define AUDIO_ELEMENTARY_STREAM 0x1C0 -#define VIDEO_ELEMENTARY_STREAM 0x1E0 -#define SYSTEM_START_CODE_MAX 0x1FF - -/* picture coding type */ -#define I_TYPE 1 -#define P_TYPE 2 -#define B_TYPE 3 -#define D_TYPE 4 - -/* macroblock type */ -#define MACROBLOCK_INTRA 1 -#define MACROBLOCK_PATTERN 2 -#define MACROBLOCK_MOTION_BACKWARD 4 -#define MACROBLOCK_MOTION_FORWARD 8 -#define MACROBLOCK_QUANT 16 - -/* Frame reconstruction quality options */ -#define RECON_SUBPIXEL 1 -#define RECON_AVG_SUBPIXEL 2 - - -struct APEG_LAYER; -struct APEG_STREAM; - -extern int _apeg_ignore_video; - -/* prototypes of global functions */ - -/* getbits.c */ -unsigned int apeg_get_bits(struct APEG_LAYER*, int); -unsigned int apeg_get_bits1(struct APEG_LAYER*); -unsigned int apeg_get_bits8(struct APEG_LAYER*, int); -unsigned int apeg_get_bits32(struct APEG_LAYER*); -void apeg_flush_bits(struct APEG_LAYER*, int); -void apeg_flush_bits1(struct APEG_LAYER*); -void apeg_flush_bits8(struct APEG_LAYER*, int); -void apeg_flush_bits32(struct APEG_LAYER*); - -#define show_bits(l, n) ((l)->Bfr >> (32-(n))) -#define show_bits32(l) ((l)->Bfr) -#define MASK_BITS(n) ((1<<(n))-1) -#define marker_bit(l, t) apeg_flush_bits1(l) - -/* getblk.c */ -void apeg_decode_intra_blocks(struct APEG_LAYER*, int*); -void apeg_decode_non_intra_block(struct APEG_LAYER*, int); - -/* gethdr.c */ -int apeg_get_header(struct APEG_LAYER*); -int apeg_start_code(struct APEG_LAYER*); - -/* getpic.c */ -unsigned char **apeg_get_frame(struct APEG_LAYER*); - -/* idct.c */ -void apeg_fast_idct(short*); - -/* motion.c */ -void apeg_motion_vector(struct APEG_LAYER*, int*, int, int); - -/* mpeg2dec.c */ -void apeg_error_jump(char*); -void _apeg_initialize_buffer(struct APEG_LAYER*); - -/* recon.c */ -void apeg_form_f_pred(struct APEG_LAYER*, int, int, int*); -void apeg_form_b_pred(struct APEG_LAYER*, int, int, int*); -void apeg_form_fb_pred(struct APEG_LAYER*, int, int, int*); -void apeg_empty_pred(unsigned char**, unsigned char**, int, int, int); - -/* display.c */ -void apeg_initialize_display(struct APEG_LAYER*, int); -void apeg_display_frame(struct APEG_LAYER*, unsigned char**); - -/* ogg.c */ -int alvorbis_update(struct APEG_LAYER*); -unsigned char **altheora_get_frame(struct APEG_LAYER*); -int alogg_open(struct APEG_LAYER*); -int alogg_reopen(struct APEG_LAYER*); -void alogg_cleanup(struct APEG_LAYER*); -void alvorbis_close(struct APEG_LAYER*); - -/* global variables */ -extern int _apeg_skip_length; - -/* zig-zag and alternate scan patterns */ -extern const unsigned char apeg_scan[64]; - -/* buffers for multiuse purposes */ -extern short apeg_block[6][64]; - -extern char apeg_error[256]; - - -// layer specific variables -typedef struct APEG_LAYER { - struct APEG_STREAM stream; - - // bit input - PACKFILE *pf; - - void *ogg_info; - - // from mpeg2play - unsigned int Bfr; - unsigned int Rdmax; - int Incnt; - - // sequence header - int intra_quantizer_matrix[64]; - int non_intra_quantizer_matrix[64]; - - // slice/macroblock - int quantizer_scale; - - // System layer type - enum { - NO_SYSTEM = 0, - MPEG_SYSTEM, - OGG_SYSTEM - } system_stream_flag; - - // pointer to non-interlaced YCrCb picture buffers - unsigned char *image_ptr; - - // pointers derived from the picture buffer - unsigned char *backward_frame[3]; - unsigned char *forward_frame[3]; - unsigned char *auxframe[3]; - - // current MPEG buffer - unsigned char *current_frame[3]; - - // current buffer to be converted - unsigned char **picture; - - // if we got the last MPEG frame - int got_last; - - // non-normative variables derived from normative elements - int coded_width; - int coded_height; - int chroma_width; - int chroma_height; - - // normative derived variables (as per ISO/IEC 13818-2) - int mb_cols; - int mb_rows; - - // headers - int picture_type; - - // display callback - void (*display_frame)(APEG_STREAM*, unsigned char**, void*); - void *display_arg; - - // filename and buffer info - char *fname; - int buffer_size; - enum { - DISK_BUFFER = 0, - MEMORY_BUFFER, - USER_BUFFER - } buffer_type; - - struct { - unsigned char *buf; - unsigned int bytes_left; - } mem_data; - - struct { - void (*skip)(int bytes, void *ptr); - int (*request)(void *bfr, int bytes, void *ptr); - int (*init)(void *ptr); - void *ptr; - int eof; - } ext_data; - - int quality; - - float multiple; - - struct { -#ifndef DISABLE_MPEG_AUDIO - struct reader rd; - struct frame fr; - struct mpstr mp; - int frame; -#endif - - int (*callback_init)(APEG_STREAM*, int*, int*, void*); - int (*callback)(APEG_STREAM*, void*, int, void*); - void *callback_arg; - - int buf_segment; - int voice; - SAMPLE *stream; - int bufsize; - - int samples_per_update; - int last_pos; - int pos; - - struct { - byte *samples; - int point; - } pcm; - - int inited; - } audio; -} APEG_LAYER; - -#endif // MPEG1DEC_H diff --git a/Common/libinclude/mpg123.h b/Common/libinclude/mpg123.h deleted file mode 100644 index 33a950067ab..00000000000 --- a/Common/libinclude/mpg123.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * mpg123 defines - * used source: musicout.h from mpegaudio package - */ -#ifndef MPG123_H -#define MPG123_H - -struct APEG_STREAM; -struct APEG_LAYER; - -typedef unsigned char byte; -extern int _apeg_ignore_audio; - -int alvorbis_init_streaming(struct APEG_LAYER*); -int alvorbis_stop_streaming(struct APEG_LAYER*); -int alvorbis_update(struct APEG_LAYER*); - -int _apeg_audio_poll(struct APEG_LAYER*); -int _apeg_audio_get_position(struct APEG_LAYER*); -void _apeg_audio_set_speed_multiple(struct APEG_LAYER*, float); -int _apeg_audio_close(struct APEG_LAYER*); -int _apeg_audio_flush(struct APEG_LAYER*); - -int _apeg_audio_reset_parameters(struct APEG_LAYER*); -int _apeg_start_audio(struct APEG_LAYER*, int); - -#ifndef DISABLE_MPEG_AUDIO - -#include -#include -#include - -#include - -#define ALMPA_OK 0 -#define ALMPA_ERROR (-1) -#define ALMPA_EOF (-2) - - -#ifndef M_PI -#define M_PI 3.14159265358979 -#endif - -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237 -#endif - - -#define SBLIMIT 32 -#define SCALE_BLOCK 12 -#define SSLIMIT 18 - -#define MPG_MD_STEREO 0 -#define MPG_MD_JOINT_STEREO 1 -#define MPG_MD_DUAL_CHANNEL 2 -#define MPG_MD_MONO 3 - -#define MAXFRAMESIZE 4096 - - -int almpa_head_backcheck(unsigned long); - -struct gr_info_s { - int scfsi; - unsigned int part2_3_length; - unsigned int big_values; - unsigned int scalefac_compress; - unsigned int block_type; - unsigned int mixed_block_flag; - unsigned int table_select[3]; - unsigned int subblock_gain[3]; - unsigned int maxband[3]; - unsigned int maxbandl; - unsigned int maxb; - unsigned int region1start; - unsigned int region2start; - unsigned int preflag; - unsigned int scalefac_scale; - unsigned int count1table_select; - float *full_gain[3]; - float *pow2gain; -}; - -struct III_sideinfo -{ - unsigned int main_data_begin; - unsigned int private_bits; - struct { - struct gr_info_s gr[2]; - } ch[2]; -}; - -struct al_table -{ - short bits; - short d; -}; - -extern int tabsel_123[2][3][16]; - -#define VBR_FRAMES_FLAG 0x0001 -#define VBR_BYTES_FLAG 0x0002 -#define VBR_TOC_FLAG 0x0004 -#define VBR_SCALE_FLAG 0x0008 - -struct vbrHeader { - unsigned long flags; - unsigned long frames; - unsigned long bytes; - unsigned long scale; - unsigned char toc[100]; -}; - -struct frame { - struct al_table *alloc; - int stereo; - int jsbound; - int II_sblimit; - int down_sample_sblimit; - int lsf; - int mpeg25; - int header_change; - int lay; - int error_protection; - int bitrate_index; - int sampling_frequency; - int padding; - int extension; - int mode; - int mode_ext; - int copyright; - int original; - int emphasis; - int framesize; /* computed framesize */ - int padsize; /* */ - - int sideInfoSize; /* Layer3 sideInfo Header size */ - - int vbr; - struct vbrHeader vbr_header; - - /* FIXME: move this to another place */ - unsigned long firsthead; - unsigned long thishead; - int freeformatsize; -}; - -struct bitstream_info { - int bitindex; - unsigned char *wordpointer; -}; - -struct mpstr { - int bsize; - int framesize; - int fsizeold; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - float hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - float synth_buffs[2][2][0x110]; - int synth_bo; - - struct bitstream_info bsi; - int bsbufend[2]; - int bsbufold_end; - unsigned char *bsbuf, *bsbufold; - - float buffs[2][2][0x110]; - int bo; - - float hybridIn [2][SBLIMIT][SSLIMIT]; - float hybridOut[2][SSLIMIT][SBLIMIT]; - unsigned int balloc[2*SBLIMIT]; - struct III_sideinfo sideinfo; - int scalefacs[192]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ - int gr, ss; - int return_later; -}; - -struct reader { - void *filept; - - unsigned int left_in_packet; - unsigned int filepos; - int eof; -}; - -void almpa_close(struct APEG_LAYER*); -int almpa_read_bytes(struct APEG_LAYER*, byte*, unsigned int); -void almpa_head_read(struct APEG_LAYER*, unsigned long*); -void almpa_head_shift(struct APEG_LAYER*, unsigned long*); -void almpa_skip_bytes(struct APEG_LAYER*, int); - - -extern void print_header(struct frame *); -extern void print_header_compact(struct frame *); -extern void print_id3_tag(unsigned char *buf); - -extern void set_pointer(struct mpstr*,int,long); - -extern int open_stream(struct APEG_LAYER *layer); -extern void read_frame_init (struct frame *fr); -extern int read_frame(struct APEG_LAYER *layer,struct frame *fr); -extern int do_layer3(struct mpstr*, struct frame*, struct APEG_LAYER*); -extern int do_layer2(struct mpstr*, struct frame*, struct APEG_LAYER*); -extern int do_layer1(struct mpstr*, struct frame*, struct APEG_LAYER*); - - -extern void synth_1to1(float*,int,unsigned char*,int*,float(*)[2][0x110],int*); -extern void synth_1to1_mono(float*,unsigned char*,int*,float(*)[2][0x110],int*); - -extern void synth_2to1(float*,int,unsigned char*,int*,float(*)[2][0x110],int*); -extern void synth_2to1_mono(float*,unsigned char*,int*,float(*)[2][0x110],int*); - -extern void synth_4to1(float*,int,unsigned char*,int*,float(*)[2][0x110],int*); -extern void synth_4to1_mono(float*,unsigned char*,int*,float(*)[2][0x110],int*); - -#define synth_mono(ds, a, b, c, d, e) \ -switch((ds)) \ -{ \ - case 2: \ - synth_4to1_mono((a), (b), (c), (d), (e)); \ - break; \ - case 1: \ - synth_2to1_mono((a), (b), (c), (d), (e)); \ - break; \ - case 0: \ - synth_1to1_mono((a), (b), (c), (d), (e)); \ - break; \ -} - -#define synth(ds, a, b, c, d, e, f) \ -switch((ds)) \ -{ \ - case 2: \ - synth_4to1((a), (b), (c), (d), (e), (f)); \ - break; \ - case 1: \ - synth_2to1((a), (b), (c), (d), (e), (f)); \ - break; \ - case 0: \ - synth_1to1((a), (b), (c), (d), (e), (f)); \ - break; \ -} - -extern void init_layer3(int); -extern void init_layer2(void); -extern void make_decode_tables(); - -extern void control_generic(struct mpstr *,struct frame *fr); - -extern int getVBRHeader(struct vbrHeader *head,unsigned char *buf, - struct frame *fr); - - -extern long freqs[10]; -extern float muls[27][64]; -extern float decwin[512+32]; -extern float *pnts[5]; - -extern float equalizer[2][32]; - -/* 486 optimizations */ -#define FIR_BUFFER_SIZE 128 -void dct64(float*,float*,float*); -void dct36(float*,float*,float*,float*,float*); - - -static INLINE void do_equalizer(float *bandPtr, int channel) -{ -#if 0 - int i; - for(i = 0;i < 32;++i) - bandPtr[i] *= equalizer[channel][i]; -#else - (void)bandPtr; - (void)channel; -#endif -} - -#endif - -#include "mpeg1dec.h" - -static INLINE int clamp_val(int low, int val, int high) -{ - val -= low; - val &= (~val) >> 31; - val += low; - - val -= high; - val &= val >> 31; - val += high; - - return val; -} - -#endif // MPG123_H diff --git a/Common/libinclude/mpglib.h b/Common/libinclude/mpglib.h deleted file mode 100644 index 47cf465c65c..00000000000 --- a/Common/libinclude/mpglib.h +++ /dev/null @@ -1,49 +0,0 @@ - -struct buf { - unsigned char *pnt; - long size; - long pos; - struct buf *next; - struct buf *prev; -}; - -struct framebuf { - struct buf *buf; - long pos; - struct frame *next; - struct frame *prev; -}; - -struct mp3str { - struct buf *head,*tail; - int bsize; - int framesize; - int fsizeold; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - real hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - real synth_buffs[2][2][0x110]; - int synth_bo; -}; - - -#define MP3_ERR -1 -#define MP3_OK 0 -#define MP3_NEED_MORE 1 - - -#ifdef __cplusplus -extern "C" { -#endif - -int InitMP3(struct mp3str *mp); -int decodeMP3(struct mp3str *mp,char *inmemory,int inmemsize, - char *outmemory,int outmemsize,int *done); -void ExitMP3(struct mp3str *mp); - -#ifdef __cplusplus -} -#endif diff --git a/Engine/ac/asset_helper.h b/Engine/ac/asset_helper.h index 076b8762219..0339f87a11e 100644 --- a/Engine/ac/asset_helper.h +++ b/Engine/ac/asset_helper.h @@ -34,7 +34,6 @@ Stream *find_open_asset(const String &filename); extern "C" { struct PACKFILE; // Allegro 4's own stream type - struct DUMBFILE; // DUMB stream type } // AssetPath combines asset library and item names @@ -62,8 +61,6 @@ struct AGS_PACKFILE_OBJ // This function is supposed to be used only when you have to create Allegro // object, passing PACKFILE stream to constructor. PACKFILE *PackfileFromAsset(const AssetPath &path, size_t &asset_size); -// Creates DUMBFILE stream from AGS asset. Used for creating DUMB objects -DUMBFILE *DUMBfileFromAsset(const AssetPath &path, size_t &asset_size); bool DoesAssetExistInLib(const AssetPath &assetname); #endif // __AGS_EE_AC__ASSETHELPER_H diff --git a/Engine/ac/file.cpp b/Engine/ac/file.cpp index ebb1fec45af..f733d3e0bf2 100644 --- a/Engine/ac/file.cpp +++ b/Engine/ac/file.cpp @@ -12,7 +12,6 @@ // //============================================================================= -#include "aldumb.h" #include "ac/asset_helper.h" #include "ac/audiocliptype.h" #include "ac/file.h" @@ -486,14 +485,6 @@ PACKFILE *PackfileFromAsset(const AssetPath &path, size_t &asset_size) return nullptr; } -DUMBFILE *DUMBfileFromAsset(const AssetPath &path, size_t &asset_size) -{ - PACKFILE *pf = PackfileFromAsset(path, asset_size); - if (pf) - return dumbfile_open_packfile(pf); - return nullptr; -} - bool DoesAssetExistInLib(const AssetPath &assetname) { bool needsetback = false; diff --git a/Engine/libsrc/allegro-4.2.2-agspatch/midi.c b/Engine/libsrc/allegro-4.2.2-agspatch/midi.c deleted file mode 100644 index 2de914a2dd4..00000000000 --- a/Engine/libsrc/allegro-4.2.2-agspatch/midi.c +++ /dev/null @@ -1,103 +0,0 @@ -// -// Allegro 4.4.2 and earlier do not have a variant of MIDI -// constructor that takes PACKFILE stream as parameter. Hence our own -// version. This should be removed when either Allegro 4 gets patched -// or we switch to another backend library. -// -// Much of the code is plain copied from load_midi Allegro's function. -// - -#include - -#if (ALLEGRO_DATE < 20190303) - -#include - -/* load_midi_pf: - * Reads a standard MIDI file from the packfile given, returning a MIDI - * structure, or NULL on error. - * - * If unsuccessful the offset into the file is unspecified, i.e. you must - * either reset the offset to some known place or close the packfile. The - * packfile is not closed by this function. - */ -MIDI *load_midi_pf(PACKFILE *fp) -{ - int c; - char buf[4]; - long data; - MIDI *midi; - int num_tracks; - ASSERT(fp); - - midi = _AL_MALLOC(sizeof(MIDI)); /* get some memory */ - if (!midi) - return NULL; - - for (c=0; ctrack[c].data = NULL; - midi->track[c].len = 0; - } - - pack_fread(buf, 4, fp); /* read midi header */ - - /* Is the midi inside a .rmi file? */ - if (memcmp(buf, "RIFF", 4) == 0) { /* check for RIFF header */ - pack_mgetl(fp); - - while (!pack_feof(fp)) { - pack_fread(buf, 4, fp); /* RMID chunk? */ - if (memcmp(buf, "RMID", 4) == 0) break; - - pack_fseek(fp, pack_igetl(fp)); /* skip to next chunk */ - } - - if (pack_feof(fp)) goto err; - - pack_mgetl(fp); - pack_mgetl(fp); - pack_fread(buf, 4, fp); /* read midi header */ - } - - if (memcmp(buf, "MThd", 4)) - goto err; - - pack_mgetl(fp); /* skip header chunk length */ - - data = pack_mgetw(fp); /* MIDI file type */ - if ((data != 0) && (data != 1)) - goto err; - - num_tracks = pack_mgetw(fp); /* number of tracks */ - if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS)) - goto err; - - data = pack_mgetw(fp); /* beat divisions */ - midi->divisions = ABS(data); - - for (c=0; ctrack[c].len = data; - - midi->track[c].data = _AL_MALLOC_ATOMIC(data); /* allocate memory */ - if (!midi->track[c].data) - goto err; - /* finally, read track data */ - if (pack_fread(midi->track[c].data, data, fp) != data) - goto err; - } - - lock_midi(midi); - return midi; - - /* oh dear... */ - err: - destroy_midi(midi); - return NULL; -} - -#endif // (ALLEGRO_DATE < 20190303) diff --git a/Engine/libsrc/almp3-2.0.5/CMakeLists.txt b/Engine/libsrc/almp3-2.0.5/CMakeLists.txt deleted file mode 100644 index 47292f70947..00000000000 --- a/Engine/libsrc/almp3-2.0.5/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -add_library(almp3) - -set_target_properties(almp3 PROPERTIES - C_STANDARD 11 - C_EXTENSIONS NO -) - -target_include_directories(almp3 - PUBLIC include - PRIVATE . # for ./decoder -) - -target_sources(almp3 - PRIVATE - src/almp3.c - decoder/common.c - decoder/dct64_i386.c - decoder/decode_i386.c - decoder/huffman.h - decoder/interface.c - decoder/l2tables.h - decoder/layer2.c - decoder/layer3.c - decoder/mpg123.h - decoder/mpglib.h - decoder/tabinit.c -) - -target_link_libraries(almp3 PUBLIC Allegro::Allegro) - -# The PSP (and embedded processors in general) only has hardware support for single precision math. -if (ANDROID OR IOS) - target_compile_definitions(almp3 PRIVATE REAL_IS_FLOAT) -endif() - -add_library(AlMp3::AlMp3 ALIAS almp3) diff --git a/Engine/libsrc/almp3-2.0.5/decoder/README b/Engine/libsrc/almp3-2.0.5/decoder/README deleted file mode 100644 index 2465ffaa2c4..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/README +++ /dev/null @@ -1,39 +0,0 @@ -MP3 library ------------ -Version 0.2a - -This decoder is a 'light' version (thrown out all unnecessay parts) -from the mpg123 package. I made this for a company. - -Currently only Layer3 is enabled to save some space. Layer1,2 isn't -tested at all. The interface will not change significantly. -A backport to the mpg123 package is planed. - -compiled and tested only on Solaris 2.6 -main.c contains a simple demo application for library. - -COPYING: you may use this source under LGPL terms! - (Yes, I switched to LGPL for the _mpglib_ part!) - -PLEASE NOTE: This software may contain patented algorithms (at least - patented in some countries). It may be not allowed to sell/use products - based on this source code in these countries. Check this out first! - -COPYRIGHT of MP3 music: - Please note, that the duplicating of copyrighted music without explicit - permission violates the rights of the owner. - -SENDING PATCHES: - The current version is under LGPL. Please consider this when sending patches or - changes. I also want to have the freedom to sell the code to companies that - cannot or do not want to use the code under LGPL. So, if you send me - significant patches, I need your explicit permission to do this. Of course, - there will always be the LGPLed open source version of the 100% same code. - In the case you cannot accept this: the code is free, it's your freedom - to distribute your changes again under LGPL. - -FEEDBACK: - I'm interessted to here from you, when you use this package as part - of another project. - - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/common.c b/Engine/libsrc/almp3-2.0.5/decoder/common.c deleted file mode 100644 index a41d4d3b706..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/common.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include "mpg123.h" - - -int almp3tabsel_123[2][3][16] = { - { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, - {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, - {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, - { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, - {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, - {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } -}; - -long almp3freqs[9] = { 44100, 48000, 32000, - 22050, 24000, 16000 , - 11025 , 12000 , 8000 }; - -int bitindex; -unsigned char *wordpointer; - - -#define HDRCMPMASK 0xfffffd00 - - -/* - * the code a header and write the information - * into the frame structure - */ -int decode_header(struct frame *fr,unsigned long newhead) -{ - if( newhead & (1<<20) ) { - fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1; - fr->mpeg25 = 0; - } - else { - fr->lsf = 1; - fr->mpeg25 = 1; - } - - - fr->lay = 4-((newhead>>17)&3); - if( ((newhead>>10)&0x3) == 0x3) { - return (0); - } - if(fr->mpeg25) { - fr->sampling_frequency = 6 + ((newhead>>10)&0x3); - } - else - fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3); - fr->error_protection = ((newhead>>16)&0x1)^0x1; - - if(fr->mpeg25) /* allow Bitrate change for 2.5 ... */ - fr->bitrate_index = ((newhead>>12)&0xf); - - fr->bitrate_index = ((newhead>>12)&0xf); - fr->padding = ((newhead>>9)&0x1); - fr->extension = ((newhead>>8)&0x1); - fr->mode = ((newhead>>6)&0x3); - fr->mode_ext = ((newhead>>4)&0x3); - fr->copyright = ((newhead>>3)&0x1); - fr->original = ((newhead>>2)&0x1); - fr->emphasis = newhead & 0x3; - - fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; - - if(!fr->bitrate_index) - { - return (0); - } - - switch(fr->lay) - { - case 1: -#if 0 - fr->do_layer = do_layer1; - fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? - (fr->mode_ext<<2)+4 : 32; - fr->framesize = (long) almp3tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; - fr->framesize /= almp3freqs[fr->sampling_frequency]; - fr->framesize = ((fr->framesize+fr->padding)<<2)-4; -#endif - break; - case 2: -#if 1 - fr->do_layer = do_layer2; -// in layer2.c -// II_select_table(fr); -// fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? -// (fr->mode_ext<<2)+4 : fr->II_sblimit; - fr->framesize = (long) almp3tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; - fr->framesize /= almp3freqs[fr->sampling_frequency]; - fr->framesize += fr->padding - 4; -#endif - break; - case 3: - fr->do_layer = do_layer3; -#if 0 - if(fr->lsf) - ssize = (fr->stereo == 1) ? 9 : 17; - else - ssize = (fr->stereo == 1) ? 17 : 32; -#endif - -#if 0 - if(fr->error_protection) - ssize += 2; -#endif - { - long ltmp; - ltmp = (long)almp3tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; - ltmp /= almp3freqs[fr->sampling_frequency]<<(fr->lsf); - ltmp += fr->padding - 4; - fr->framesize = ltmp; - } - - break; - default: - return (0); - } - - return 1; -} - - -unsigned int getbits(int number_of_bits) -{ - unsigned long rval; - - if(!number_of_bits) - return 0; - - { - rval = wordpointer[0]; - rval <<= 8; - rval |= wordpointer[1]; - rval <<= 8; - rval |= wordpointer[2]; - rval <<= bitindex; - rval &= 0xffffff; - - bitindex += number_of_bits; - - rval >>= (24-number_of_bits); - - wordpointer += (bitindex>>3); - bitindex &= 7; - } - return rval; -} - -unsigned int getbits_fast(int number_of_bits) -{ - unsigned long rval; - - { - rval = wordpointer[0]; - rval <<= 8; - rval |= wordpointer[1]; - rval <<= bitindex; - rval &= 0xffff; - bitindex += number_of_bits; - - rval >>= (16-number_of_bits); - - wordpointer += (bitindex>>3); - bitindex &= 7; - } - return rval; -} - -int head_check(unsigned long head) -{ - - if((head & 0xffe00000) != 0xffe00000) - return FALSE; - if(!((head>>17)&3)) - return FALSE; - if(((head>>12)&0xf) == 0xf) - return FALSE; - if(((head>>10)&0x3) == 0x3) - return FALSE; - - return TRUE; -} diff --git a/Engine/libsrc/almp3-2.0.5/decoder/dct64_i386.c b/Engine/libsrc/almp3-2.0.5/decoder/dct64_i386.c deleted file mode 100644 index 536cc15f1e3..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/dct64_i386.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Discrete Cosine Tansform (DCT) for subband synthesis - * optimized for machines with no auto-increment. - * The performance is highly compiler dependend. Maybe - * the dct64.c version for 'normal' processor may be faster - * even for Intel processors. - */ - -#include "mpg123.h" - -static void dct64_1(real *out0,real *out1,real *b1,real *b2,real *samples) -{ - - { - register real *costab = pnts[0]; - - b1[0x00] = samples[0x00] + samples[0x1F]; - b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0]; - - b1[0x01] = samples[0x01] + samples[0x1E]; - b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1]; - - b1[0x02] = samples[0x02] + samples[0x1D]; - b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2]; - - b1[0x03] = samples[0x03] + samples[0x1C]; - b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3]; - - b1[0x04] = samples[0x04] + samples[0x1B]; - b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4]; - - b1[0x05] = samples[0x05] + samples[0x1A]; - b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5]; - - b1[0x06] = samples[0x06] + samples[0x19]; - b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6]; - - b1[0x07] = samples[0x07] + samples[0x18]; - b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7]; - - b1[0x08] = samples[0x08] + samples[0x17]; - b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8]; - - b1[0x09] = samples[0x09] + samples[0x16]; - b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9]; - - b1[0x0A] = samples[0x0A] + samples[0x15]; - b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA]; - - b1[0x0B] = samples[0x0B] + samples[0x14]; - b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB]; - - b1[0x0C] = samples[0x0C] + samples[0x13]; - b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC]; - - b1[0x0D] = samples[0x0D] + samples[0x12]; - b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD]; - - b1[0x0E] = samples[0x0E] + samples[0x11]; - b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE]; - - b1[0x0F] = samples[0x0F] + samples[0x10]; - b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF]; - } - - - { - register real *costab = pnts[1]; - - b2[0x00] = b1[0x00] + b1[0x0F]; - b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0]; - b2[0x01] = b1[0x01] + b1[0x0E]; - b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1]; - b2[0x02] = b1[0x02] + b1[0x0D]; - b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2]; - b2[0x03] = b1[0x03] + b1[0x0C]; - b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3]; - b2[0x04] = b1[0x04] + b1[0x0B]; - b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4]; - b2[0x05] = b1[0x05] + b1[0x0A]; - b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5]; - b2[0x06] = b1[0x06] + b1[0x09]; - b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6]; - b2[0x07] = b1[0x07] + b1[0x08]; - b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7]; - - b2[0x10] = b1[0x10] + b1[0x1F]; - b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0]; - b2[0x11] = b1[0x11] + b1[0x1E]; - b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1]; - b2[0x12] = b1[0x12] + b1[0x1D]; - b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2]; - b2[0x13] = b1[0x13] + b1[0x1C]; - b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3]; - b2[0x14] = b1[0x14] + b1[0x1B]; - b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4]; - b2[0x15] = b1[0x15] + b1[0x1A]; - b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5]; - b2[0x16] = b1[0x16] + b1[0x19]; - b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6]; - b2[0x17] = b1[0x17] + b1[0x18]; - b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7]; - } - - { - register real *costab = pnts[2]; - - b1[0x00] = b2[0x00] + b2[0x07]; - b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0]; - b1[0x01] = b2[0x01] + b2[0x06]; - b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1]; - b1[0x02] = b2[0x02] + b2[0x05]; - b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2]; - b1[0x03] = b2[0x03] + b2[0x04]; - b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3]; - - b1[0x08] = b2[0x08] + b2[0x0F]; - b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0]; - b1[0x09] = b2[0x09] + b2[0x0E]; - b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1]; - b1[0x0A] = b2[0x0A] + b2[0x0D]; - b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2]; - b1[0x0B] = b2[0x0B] + b2[0x0C]; - b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3]; - - b1[0x10] = b2[0x10] + b2[0x17]; - b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0]; - b1[0x11] = b2[0x11] + b2[0x16]; - b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1]; - b1[0x12] = b2[0x12] + b2[0x15]; - b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2]; - b1[0x13] = b2[0x13] + b2[0x14]; - b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3]; - - b1[0x18] = b2[0x18] + b2[0x1F]; - b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0]; - b1[0x19] = b2[0x19] + b2[0x1E]; - b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1]; - b1[0x1A] = b2[0x1A] + b2[0x1D]; - b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2]; - b1[0x1B] = b2[0x1B] + b2[0x1C]; - b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3]; - } - - { - register real const cos0 = pnts[3][0]; - register real const cos1 = pnts[3][1]; - - b2[0x00] = b1[0x00] + b1[0x03]; - b2[0x03] = (b1[0x00] - b1[0x03]) * cos0; - b2[0x01] = b1[0x01] + b1[0x02]; - b2[0x02] = (b1[0x01] - b1[0x02]) * cos1; - - b2[0x04] = b1[0x04] + b1[0x07]; - b2[0x07] = (b1[0x07] - b1[0x04]) * cos0; - b2[0x05] = b1[0x05] + b1[0x06]; - b2[0x06] = (b1[0x06] - b1[0x05]) * cos1; - - b2[0x08] = b1[0x08] + b1[0x0B]; - b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0; - b2[0x09] = b1[0x09] + b1[0x0A]; - b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1; - - b2[0x0C] = b1[0x0C] + b1[0x0F]; - b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0; - b2[0x0D] = b1[0x0D] + b1[0x0E]; - b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1; - - b2[0x10] = b1[0x10] + b1[0x13]; - b2[0x13] = (b1[0x10] - b1[0x13]) * cos0; - b2[0x11] = b1[0x11] + b1[0x12]; - b2[0x12] = (b1[0x11] - b1[0x12]) * cos1; - - b2[0x14] = b1[0x14] + b1[0x17]; - b2[0x17] = (b1[0x17] - b1[0x14]) * cos0; - b2[0x15] = b1[0x15] + b1[0x16]; - b2[0x16] = (b1[0x16] - b1[0x15]) * cos1; - - b2[0x18] = b1[0x18] + b1[0x1B]; - b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0; - b2[0x19] = b1[0x19] + b1[0x1A]; - b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1; - - b2[0x1C] = b1[0x1C] + b1[0x1F]; - b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0; - b2[0x1D] = b1[0x1D] + b1[0x1E]; - b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1; - } - - { - register real const cos0 = pnts[4][0]; - - b1[0x00] = b2[0x00] + b2[0x01]; - b1[0x01] = (b2[0x00] - b2[0x01]) * cos0; - b1[0x02] = b2[0x02] + b2[0x03]; - b1[0x03] = (b2[0x03] - b2[0x02]) * cos0; - b1[0x02] += b1[0x03]; - - b1[0x04] = b2[0x04] + b2[0x05]; - b1[0x05] = (b2[0x04] - b2[0x05]) * cos0; - b1[0x06] = b2[0x06] + b2[0x07]; - b1[0x07] = (b2[0x07] - b2[0x06]) * cos0; - b1[0x06] += b1[0x07]; - b1[0x04] += b1[0x06]; - b1[0x06] += b1[0x05]; - b1[0x05] += b1[0x07]; - - b1[0x08] = b2[0x08] + b2[0x09]; - b1[0x09] = (b2[0x08] - b2[0x09]) * cos0; - b1[0x0A] = b2[0x0A] + b2[0x0B]; - b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0; - b1[0x0A] += b1[0x0B]; - - b1[0x0C] = b2[0x0C] + b2[0x0D]; - b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0; - b1[0x0E] = b2[0x0E] + b2[0x0F]; - b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0; - b1[0x0E] += b1[0x0F]; - b1[0x0C] += b1[0x0E]; - b1[0x0E] += b1[0x0D]; - b1[0x0D] += b1[0x0F]; - - b1[0x10] = b2[0x10] + b2[0x11]; - b1[0x11] = (b2[0x10] - b2[0x11]) * cos0; - b1[0x12] = b2[0x12] + b2[0x13]; - b1[0x13] = (b2[0x13] - b2[0x12]) * cos0; - b1[0x12] += b1[0x13]; - - b1[0x14] = b2[0x14] + b2[0x15]; - b1[0x15] = (b2[0x14] - b2[0x15]) * cos0; - b1[0x16] = b2[0x16] + b2[0x17]; - b1[0x17] = (b2[0x17] - b2[0x16]) * cos0; - b1[0x16] += b1[0x17]; - b1[0x14] += b1[0x16]; - b1[0x16] += b1[0x15]; - b1[0x15] += b1[0x17]; - - b1[0x18] = b2[0x18] + b2[0x19]; - b1[0x19] = (b2[0x18] - b2[0x19]) * cos0; - b1[0x1A] = b2[0x1A] + b2[0x1B]; - b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0; - b1[0x1A] += b1[0x1B]; - - b1[0x1C] = b2[0x1C] + b2[0x1D]; - b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0; - b1[0x1E] = b2[0x1E] + b2[0x1F]; - b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0; - b1[0x1E] += b1[0x1F]; - b1[0x1C] += b1[0x1E]; - b1[0x1E] += b1[0x1D]; - b1[0x1D] += b1[0x1F]; - } - - out0[0x10*16] = b1[0x00]; - out0[0x10*12] = b1[0x04]; - out0[0x10* 8] = b1[0x02]; - out0[0x10* 4] = b1[0x06]; - out0[0x10* 0] = b1[0x01]; - out1[0x10* 0] = b1[0x01]; - out1[0x10* 4] = b1[0x05]; - out1[0x10* 8] = b1[0x03]; - out1[0x10*12] = b1[0x07]; - - b1[0x08] += b1[0x0C]; - out0[0x10*14] = b1[0x08]; - b1[0x0C] += b1[0x0a]; - out0[0x10*10] = b1[0x0C]; - b1[0x0A] += b1[0x0E]; - out0[0x10* 6] = b1[0x0A]; - b1[0x0E] += b1[0x09]; - out0[0x10* 2] = b1[0x0E]; - b1[0x09] += b1[0x0D]; - out1[0x10* 2] = b1[0x09]; - b1[0x0D] += b1[0x0B]; - out1[0x10* 6] = b1[0x0D]; - b1[0x0B] += b1[0x0F]; - out1[0x10*10] = b1[0x0B]; - out1[0x10*14] = b1[0x0F]; - - b1[0x18] += b1[0x1C]; - out0[0x10*15] = b1[0x10] + b1[0x18]; - out0[0x10*13] = b1[0x18] + b1[0x14]; - b1[0x1C] += b1[0x1a]; - out0[0x10*11] = b1[0x14] + b1[0x1C]; - out0[0x10* 9] = b1[0x1C] + b1[0x12]; - b1[0x1A] += b1[0x1E]; - out0[0x10* 7] = b1[0x12] + b1[0x1A]; - out0[0x10* 5] = b1[0x1A] + b1[0x16]; - b1[0x1E] += b1[0x19]; - out0[0x10* 3] = b1[0x16] + b1[0x1E]; - out0[0x10* 1] = b1[0x1E] + b1[0x11]; - b1[0x19] += b1[0x1D]; - out1[0x10* 1] = b1[0x11] + b1[0x19]; - out1[0x10* 3] = b1[0x19] + b1[0x15]; - b1[0x1D] += b1[0x1B]; - out1[0x10* 5] = b1[0x15] + b1[0x1D]; - out1[0x10* 7] = b1[0x1D] + b1[0x13]; - b1[0x1B] += b1[0x1F]; - out1[0x10* 9] = b1[0x13] + b1[0x1B]; - out1[0x10*11] = b1[0x1B] + b1[0x17]; - out1[0x10*13] = b1[0x17] + b1[0x1F]; - out1[0x10*15] = b1[0x1F]; -} - -/* - * the call via dct64 is a trick to force GCC to use - * (new) registers for the b1,b2 pointer to the bufs[xx] field - */ -void dct64(real *a,real *b,real *c) -{ - real bufs[0x40]; - dct64_1(a,b,bufs,bufs+0x20,c); -} - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/decode_i386.c b/Engine/libsrc/almp3-2.0.5/decoder/decode_i386.c deleted file mode 100644 index 86a61325253..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/decode_i386.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Mpeg Layer-1,2,3 audio decoder - * ------------------------------ - * copyright (c) 1995,1996,1997 by Michael Hipp, All rights reserved. - * See also 'README' - * - * slighlty optimized for machines without autoincrement/decrement. - * The performance is highly compiler dependend. Maybe - * the decode.c version for 'normal' processor may be faster - * even for Intel processors. - */ - -#include -#include -#include - -#include "mpg123.h" -#include "mpglib.h" - - /* old WRITE_SAMPLE */ -#define WRITE_SAMPLE(samples,sum,clip) \ - if( (sum) > 32767.0) { *(samples) = 32767; (clip)++; } \ - else if( (sum) < -32768.0) { *(samples) = -32768; (clip)++; } \ - else { *(samples) = (short)sum; } - -int synth_1to1_mono(void *mp,real *bandPtr,unsigned char *samples,int *pnt) -{ - short samples_tmp[64]; - short *tmp1 = samples_tmp; - int i,ret; - int pnt1 = 0; - - ret = synth_1to1(mp,bandPtr,0,(unsigned char *) samples_tmp,&pnt1); - samples += *pnt; - - for(i=0;i<32;i++) { - *( (short *) samples) = *tmp1; - samples += 2; - tmp1 += 2; - } - *pnt += 64; - - return ret; -} - - -int synth_1to1(void *mp,real *bandPtr,int channel,unsigned char *out,int *pnt) -{ - struct mpstr *gmp = mp; - - static const int step = 2; - int bo; - short *samples = (short *) (out + *pnt); - - real *b0,(*buf)[0x110]; - int clip = 0; - int bo1; - - bo = gmp->synth_bo; - - if(!channel) { - bo--; - bo &= 0xf; - buf = gmp->synth_buffs[0]; - } - else { - samples++; - buf = gmp->synth_buffs[1]; - } - - if(bo & 0x1) { - b0 = buf[0]; - bo1 = bo; - dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr); - } - else { - b0 = buf[1]; - bo1 = bo+1; - dct64(buf[0]+bo,buf[1]+bo+1,bandPtr); - } - - gmp->synth_bo = bo; - - { - register int j; - real *window = decwin + 16 - bo1; - - for (j=16;j;j--,b0+=0x10,window+=0x20,samples+=step) - { - real sum; - sum = window[0x0] * b0[0x0]; - sum -= window[0x1] * b0[0x1]; - sum += window[0x2] * b0[0x2]; - sum -= window[0x3] * b0[0x3]; - sum += window[0x4] * b0[0x4]; - sum -= window[0x5] * b0[0x5]; - sum += window[0x6] * b0[0x6]; - sum -= window[0x7] * b0[0x7]; - sum += window[0x8] * b0[0x8]; - sum -= window[0x9] * b0[0x9]; - sum += window[0xA] * b0[0xA]; - sum -= window[0xB] * b0[0xB]; - sum += window[0xC] * b0[0xC]; - sum -= window[0xD] * b0[0xD]; - sum += window[0xE] * b0[0xE]; - sum -= window[0xF] * b0[0xF]; - - WRITE_SAMPLE(samples,sum,clip); - } - - { - real sum; - sum = window[0x0] * b0[0x0]; - sum += window[0x2] * b0[0x2]; - sum += window[0x4] * b0[0x4]; - sum += window[0x6] * b0[0x6]; - sum += window[0x8] * b0[0x8]; - sum += window[0xA] * b0[0xA]; - sum += window[0xC] * b0[0xC]; - sum += window[0xE] * b0[0xE]; - WRITE_SAMPLE(samples,sum,clip); - b0-=0x10,window-=0x20,samples+=step; - } - window += bo1<<1; - - for (j=15;j;j--,b0-=0x10,window-=0x20,samples+=step) - { - real sum; - sum = -window[-0x1] * b0[0x0]; - sum -= window[-0x2] * b0[0x1]; - sum -= window[-0x3] * b0[0x2]; - sum -= window[-0x4] * b0[0x3]; - sum -= window[-0x5] * b0[0x4]; - sum -= window[-0x6] * b0[0x5]; - sum -= window[-0x7] * b0[0x6]; - sum -= window[-0x8] * b0[0x7]; - sum -= window[-0x9] * b0[0x8]; - sum -= window[-0xA] * b0[0x9]; - sum -= window[-0xB] * b0[0xA]; - sum -= window[-0xC] * b0[0xB]; - sum -= window[-0xD] * b0[0xC]; - sum -= window[-0xE] * b0[0xD]; - sum -= window[-0xF] * b0[0xE]; - sum -= window[-0x0] * b0[0xF]; - - WRITE_SAMPLE(samples,sum,clip); - } - } - *pnt += 128; - - return clip; -} - - - - - - -int tsynth_1to1(real *bandPtr,int channel,unsigned char *out,int *pnt) -{ - static real buffs[2][2][0x110]; - static const int step = 2; - static int bo = 1; - short *samples = (short *) (out + *pnt); - - real *b0,(*buf)[0x110]; - int clip = 0; - int bo1; - - if(!channel) { - bo--; - bo &= 0xf; - buf = buffs[0]; - } - else { - samples++; - buf = buffs[1]; - } - - if(bo & 0x1) { - b0 = buf[0]; - bo1 = bo; - dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr); - } - else { - b0 = buf[1]; - bo1 = bo+1; - dct64(buf[0]+bo,buf[1]+bo+1,bandPtr); - } - - { - register int j; - real *window = decwin + 16 - bo1; - - for (j=16;j;j--,b0+=0x10,window+=0x20,samples+=step) - { - real sum; - sum = window[0x0] * b0[0x0]; - sum -= window[0x1] * b0[0x1]; - sum += window[0x2] * b0[0x2]; - sum -= window[0x3] * b0[0x3]; - sum += window[0x4] * b0[0x4]; - sum -= window[0x5] * b0[0x5]; - sum += window[0x6] * b0[0x6]; - sum -= window[0x7] * b0[0x7]; - sum += window[0x8] * b0[0x8]; - sum -= window[0x9] * b0[0x9]; - sum += window[0xA] * b0[0xA]; - sum -= window[0xB] * b0[0xB]; - sum += window[0xC] * b0[0xC]; - sum -= window[0xD] * b0[0xD]; - sum += window[0xE] * b0[0xE]; - sum -= window[0xF] * b0[0xF]; - - WRITE_SAMPLE(samples,sum,clip); - } - - { - real sum; - sum = window[0x0] * b0[0x0]; - sum += window[0x2] * b0[0x2]; - sum += window[0x4] * b0[0x4]; - sum += window[0x6] * b0[0x6]; - sum += window[0x8] * b0[0x8]; - sum += window[0xA] * b0[0xA]; - sum += window[0xC] * b0[0xC]; - sum += window[0xE] * b0[0xE]; - WRITE_SAMPLE(samples,sum,clip); - b0-=0x10,window-=0x20,samples+=step; - } - window += bo1<<1; - - for (j=15;j;j--,b0-=0x10,window-=0x20,samples+=step) - { - real sum; - sum = -window[-0x1] * b0[0x0]; - sum -= window[-0x2] * b0[0x1]; - sum -= window[-0x3] * b0[0x2]; - sum -= window[-0x4] * b0[0x3]; - sum -= window[-0x5] * b0[0x4]; - sum -= window[-0x6] * b0[0x5]; - sum -= window[-0x7] * b0[0x6]; - sum -= window[-0x8] * b0[0x7]; - sum -= window[-0x9] * b0[0x8]; - sum -= window[-0xA] * b0[0x9]; - sum -= window[-0xB] * b0[0xA]; - sum -= window[-0xC] * b0[0xB]; - sum -= window[-0xD] * b0[0xC]; - sum -= window[-0xE] * b0[0xD]; - sum -= window[-0xF] * b0[0xE]; - sum -= window[-0x0] * b0[0xF]; - - WRITE_SAMPLE(samples,sum,clip); - } - } - *pnt += 128; - - return clip; -} - - - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/huffman.h b/Engine/libsrc/almp3-2.0.5/decoder/huffman.h deleted file mode 100644 index 7fec0d589ec..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/huffman.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * huffman tables ... recalcualted to work with my optimzed - * decoder scheme (MH) - * - * probably we could save a few bytes of memory, because the - * smaller tables are often the part of a bigger table - */ - -struct newhuff -{ - unsigned int linbits; - short *table; -}; - -static short tab0[] = -{ - 0 -}; - -static short tab1[] = -{ - -5, -3, -1, 17, 1, 16, 0 -}; - -static short tab2[] = -{ - -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, - 16, 0 -}; - -static short tab3[] = -{ - -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, - 1, 0 -}; - -static short tab5[] = -{ - -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, - 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, - 0 -}; - -static short tab6[] = -{ - -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, - 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, - 0 -}; - -static short tab7[] = -{ - -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, - -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, - 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, - -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, - -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 -}; - -static short tab8[] = -{ - -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, - -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, - 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, - 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, - 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 -}; - -static short tab9[] = -{ - -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, - 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, - -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, - -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, - 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 -}; - -static short tab10[] = -{ --125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, - 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, - -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, - 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, - -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, - -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, - -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, - 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, - 2, 32, 17, -1, 1, 16, 0 -}; - -static short tab11[] = -{ --121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, - -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, - -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, - -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, - -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, - 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, - 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, - -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, - 32, 17, -3, -1, 1, 16, 0 -}; - -static short tab12[] = -{ --115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, - 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, - 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, - 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, - -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, - 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, - 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, - -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, - 2, 32, 0, 17, -1, 1, 16 -}; - -static short tab13[] = -{ --509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, - -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, - 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, - 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, - 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, - -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, - 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, - 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, - 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, - -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, - 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, - 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, - 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, - -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, - 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, - -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, - 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, - 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, - 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, - -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, - -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, - -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, - 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, - -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, - -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, - 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, - 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, - 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, - -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, - -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, - 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, - -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, - -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, - -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, - 0 -}; - -static short tab15[] = -{ --495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, - -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, - 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, - -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, - -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, - -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, - -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, - -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, - 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, - 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, - 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, - -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, - -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, - 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, - 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, - -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, - -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, - 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, - -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, - -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, - -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, - -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, - 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, - 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, - -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, - -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, - -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, - -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, - 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, - -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, - -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, - 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, - 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, - 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, - 0 -}; - -static short tab16[] = -{ --509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, - 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, - -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, - -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, - -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, - 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, - -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, - 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, - -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, - -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, - -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, - 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, - -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, - -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, - 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, - 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, - 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, - -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, - -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, - -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, - 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, - 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, - -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, - -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, - -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, - 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, - -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, - 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, - -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, - 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, - -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, - -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, - -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, - 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, - 0 -}; - -static short tab24[] = -{ --451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, - 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, - -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, - 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, - 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, - 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, - -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, - -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, --143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, - -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, - -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, - 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, - 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, - 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, - -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, - -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, - -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, - 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, - 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, - 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, - 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, - 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, - -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, - -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, - -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, - -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, - -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, - 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, - -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, - -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, - 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, - 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, - -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, - 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, - 0 -}; - -static short tab_c0[] = -{ - -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, - 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, - 0 -}; - -static short tab_c1[] = -{ - -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, - 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, - 0 -}; - - - -static struct newhuff ht[] = -{ - { /* 0 */ 0 , tab0 } , - { /* 2 */ 0 , tab1 } , - { /* 3 */ 0 , tab2 } , - { /* 3 */ 0 , tab3 } , - { /* 0 */ 0 , tab0 } , - { /* 4 */ 0 , tab5 } , - { /* 4 */ 0 , tab6 } , - { /* 6 */ 0 , tab7 } , - { /* 6 */ 0 , tab8 } , - { /* 6 */ 0 , tab9 } , - { /* 8 */ 0 , tab10 } , - { /* 8 */ 0 , tab11 } , - { /* 8 */ 0 , tab12 } , - { /* 16 */ 0 , tab13 } , - { /* 0 */ 0 , tab0 } , - { /* 16 */ 0 , tab15 } , - - { /* 16 */ 1 , tab16 } , - { /* 16 */ 2 , tab16 } , - { /* 16 */ 3 , tab16 } , - { /* 16 */ 4 , tab16 } , - { /* 16 */ 6 , tab16 } , - { /* 16 */ 8 , tab16 } , - { /* 16 */ 10, tab16 } , - { /* 16 */ 13, tab16 } , - { /* 16 */ 4 , tab24 } , - { /* 16 */ 5 , tab24 } , - { /* 16 */ 6 , tab24 } , - { /* 16 */ 7 , tab24 } , - { /* 16 */ 8 , tab24 } , - { /* 16 */ 9 , tab24 } , - { /* 16 */ 11, tab24 } , - { /* 16 */ 13, tab24 } -}; - -static struct newhuff htc[] = -{ - { /* 1 , 1 , */ 0 , tab_c0 } , - { /* 1 , 1 , */ 0 , tab_c1 } -}; - - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/interface.c b/Engine/libsrc/almp3-2.0.5/decoder/interface.c deleted file mode 100644 index d6440e641a4..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/interface.c +++ /dev/null @@ -1,217 +0,0 @@ -#include -#include - -#include "mpg123.h" -#include "mpglib.h" - - -volatile int init = 0; - - -int InitMP3(struct mpstr *mp) -{ - memset(mp,0,sizeof(struct mpstr)); - - mp->framesize = 0; - mp->fsizeold = -1; - mp->bsize = 0; - mp->head = mp->tail = NULL; - mp->fr.single = -1; - mp->bsnum = 0; - mp->synth_bo = 1; - - if (!init) { - make_decode_tables(32767); - init_layer3(SBLIMIT); - - mp->fr.II_sblimit=SBLIMIT; - init_layer2(); - - init = 1; - } - - return !0; -} - -void ExitMP3(struct mpstr *mp) -{ - struct buf *b,*bn; - - b = mp->tail; - while(b) { - free(b->pnt); - bn = b->next; - free(b); - b = bn; - } -} - -static struct buf *addbuf(struct mpstr *mp,char *buf,int size) -{ - struct buf *nbuf; - - nbuf = (struct buf*) malloc( sizeof(struct buf) ); - if(!nbuf) { - return NULL; - } - nbuf->pnt = (unsigned char*) malloc(size); - if(!nbuf->pnt) { - free(nbuf); - return NULL; - } - nbuf->size = size; - memcpy(nbuf->pnt,buf,size); - nbuf->next = NULL; - nbuf->prev = mp->head; - nbuf->pos = 0; - - if(!mp->tail) { - mp->tail = nbuf; - } - else { - mp->head->next = nbuf; - } - - mp->head = nbuf; - mp->bsize += size; - - return nbuf; -} - -static void remove_buf(struct mpstr *mp) -{ - struct buf *buf = mp->tail; - - mp->tail = buf->next; - if(mp->tail) - mp->tail->prev = NULL; - else { - mp->tail = mp->head = NULL; - } - - free(buf->pnt); - free(buf); - -} - -static int read_buf_byte(struct mpstr *mp) -{ - unsigned int b; - - int pos; - - pos = mp->tail->pos; - while(pos >= mp->tail->size) { - remove_buf(mp); - pos = mp->tail->pos; - if(!mp->tail) { - exit(1); - } - } - - b = mp->tail->pnt[pos]; - mp->bsize--; - mp->tail->pos++; - - - return b; -} - -static void read_head(struct mpstr *mp) -{ - unsigned long head; - - head = read_buf_byte(mp); - head <<= 8; - head |= read_buf_byte(mp); - head <<= 8; - head |= read_buf_byte(mp); - head <<= 8; - head |= read_buf_byte(mp); - - mp->header = head; -} - -int decodeMP3(struct mpstr *mp, char *in, int isize, - char *out, int osize, int *done) -{ - int len; - - if(osize < 4608) { - return MP3_ERR; - } - - if(in) { - if(addbuf(mp, in, isize) == NULL) { - return MP3_ERR; - } - } - - - /* First decode header */ - if(mp->framesize == 0) { - if(mp->bsize < 4) { - return MP3_NEED_MORE; - } - read_head(mp); - if (!head_check(mp->header)) - return MP3_ERR; - if (decode_header(&mp->fr,mp->header) <= 0) - return MP3_ERR; - - mp->framesize = mp->fr.framesize; - } - - if(mp->fr.framesize > mp->bsize) { - return MP3_NEED_MORE; - } - wordpointer = mp->bsspace[mp->bsnum] + 512; - mp->bsnum = (mp->bsnum + 1) & 0x1; - bitindex = 0; - - len = 0; - while(len < mp->framesize) { - int nlen; - int blen = mp->tail->size - mp->tail->pos; - if( (mp->framesize - len) <= blen) { - nlen = mp->framesize-len; - } - else { - nlen = blen; - } - memcpy(wordpointer+len,mp->tail->pnt+mp->tail->pos,nlen); - len += nlen; - mp->tail->pos += nlen; - mp->bsize -= nlen; - if(mp->tail->pos == mp->tail->size) { - remove_buf(mp); - } - } - - *done = 0; - if (mp->fr.error_protection) - getbits(16); - - if ((&mp->fr)->do_layer(mp, &mp->fr, (unsigned char*) out, done) < 0) - return MP3_ERR; - - mp->fsizeold = mp->framesize; - mp->framesize = 0; - return MP3_OK; -} - -int almp3_set_pointer(void *mp, long backstep) -{ - struct mpstr *gmp = mp; - - unsigned char *bsbufold; - if(gmp->fsizeold < 0 && backstep > 0) { - return MP3_ERR; - } - bsbufold = gmp->bsspace[gmp->bsnum] + 512; - wordpointer -= backstep; - if (backstep) - memcpy(wordpointer,bsbufold+gmp->fsizeold-backstep,backstep); - bitindex = 0; - return MP3_OK; -} diff --git a/Engine/libsrc/almp3-2.0.5/decoder/l2tables.h b/Engine/libsrc/almp3-2.0.5/decoder/l2tables.h deleted file mode 100644 index 2164a05cfc7..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/l2tables.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Layer 2 Alloc tables .. - * most other tables are calculated on program start (which is (of course) - * not ISO-conform) .. - * Layer-3 huffman table is in huffman.h - */ - - /* Layer 2 */ -struct al_table -{ - short bits; - short d; -}; - - - -struct al_table alloc_0[] = { - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767} }; - -struct al_table alloc_1[] = { - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, - {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767}, - {2,0},{5,3},{7,5},{16,-32767} }; - -struct al_table alloc_2[] = { - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; - -struct al_table alloc_3[] = { - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, - {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; - -struct al_table alloc_4[] = { - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, - {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9}, - {2,0},{5,3},{7,5},{10,9} }; - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/layer2.c b/Engine/libsrc/almp3-2.0.5/decoder/layer2.c deleted file mode 100644 index 1c0d42e54cf..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/layer2.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Mpeg Layer-2 audio decoder - * -------------------------- - * copyright (c) 1995 by Michael Hipp, All rights reserved. See also 'README' - * - */ - -#include "mpg123.h" -#include "l2tables.h" - -static int grp_3tab[32 * 3] = { 0, }; /* used: 27 */ -static int grp_5tab[128 * 3] = { 0, }; /* used: 125 */ -static int grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ - -real muls[27][64]; /* also used by layer 1 */ - -void init_layer2(void) -{ - static double mulmul[27] = { - 0.0 , -2.0/3.0 , 2.0/3.0 , - 2.0/7.0 , 2.0/15.0 , 2.0/31.0, 2.0/63.0 , 2.0/127.0 , 2.0/255.0 , - 2.0/511.0 , 2.0/1023.0 , 2.0/2047.0 , 2.0/4095.0 , 2.0/8191.0 , - 2.0/16383.0 , 2.0/32767.0 , 2.0/65535.0 , - -4.0/5.0 , -2.0/5.0 , 2.0/5.0, 4.0/5.0 , - -8.0/9.0 , -4.0/9.0 , -2.0/9.0 , 2.0/9.0 , 4.0/9.0 , 8.0/9.0 }; - - static int base[3][9] = { - { 1 , 0, 2 , } , - { 17, 18, 0 , 19, 20 , } , - { 21, 1, 22, 23, 0, 24, 25, 2, 26 } }; - - int i,j,k,l,len; - real *table; - static int tablen[3] = { 3 , 5 , 9 }; - static int *itable,*tables[3] = { grp_3tab , grp_5tab , grp_9tab }; - - for(i=0;i<3;i++) - { - itable = tables[i]; - len = tablen[i]; - for(j=0;jstereo-1; - int sblimit = fr->II_sblimit; - int jsbound = fr->jsbound; - int sblimit2 = fr->II_sblimit<alloc; - int i; - static unsigned int scfsi_buf[64]; - unsigned int *scfsi,*bita; - int sc,step; - - bita = bit_alloc; - if(stereo) - { - for (i=jsbound;i;i--,alloc1+=(1<bits); - *bita++ = (char) getbits(step); - } - for (i=sblimit-jsbound;i;i--,alloc1+=(1<bits); - bita[1] = bita[0]; - bita+=2; - } - bita = bit_alloc; - scfsi=scfsi_buf; - for (i=sblimit2;i;i--) - if (*bita++) - *scfsi++ = (char) getbits_fast(2); - } - else /* mono */ - { - for (i=sblimit;i;i--,alloc1+=(1<bits); - bita = bit_alloc; - scfsi=scfsi_buf; - for (i=sblimit;i;i--) - if (*bita++) - *scfsi++ = (char) getbits_fast(2); - } - - bita = bit_alloc; - scfsi=scfsi_buf; - for (i=sblimit2;i;i--) - if (*bita++) - switch (*scfsi++) - { - case 0: - *scale++ = getbits_fast(6); - *scale++ = getbits_fast(6); - *scale++ = getbits_fast(6); - break; - case 1 : - *scale++ = sc = getbits_fast(6); - *scale++ = sc; - *scale++ = getbits_fast(6); - break; - case 2: - *scale++ = sc = getbits_fast(6); - *scale++ = sc; - *scale++ = sc; - break; - default: /* case 3 */ - *scale++ = getbits_fast(6); - *scale++ = sc = getbits_fast(6); - *scale++ = sc; - break; - } - -} - -void II_step_two(unsigned int *bit_alloc,real fraction[2][4][SBLIMIT],int *scale,struct frame *fr,int x1) -{ - int i,j,k,ba; - int stereo = fr->stereo; - int sblimit = fr->II_sblimit; - int jsbound = fr->jsbound; - struct al_table *alloc2,*alloc1 = fr->alloc; - unsigned int *bita=bit_alloc; - int d1,step; - - for (i=0;ibits; - for (j=0;jbits; - if( (d1=alloc2->d) < 0) - { - real cm=muls[k][scale[x1]]; - fraction[j][0][i] = ((real) ((int)getbits(k) + d1)) * cm; - fraction[j][1][i] = ((real) ((int)getbits(k) + d1)) * cm; - fraction[j][2][i] = ((real) ((int)getbits(k) + d1)) * cm; - } - else - { - static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab }; - unsigned int idx,*tab,m=scale[x1]; - idx = (unsigned int) getbits(k); - tab = (unsigned int *) (table[d1] + idx + idx + idx); - fraction[j][0][i] = muls[*tab++][m]; - fraction[j][1][i] = muls[*tab++][m]; - fraction[j][2][i] = muls[*tab][m]; - } - scale+=3; - } - else - fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; - } - } - - for (i=jsbound;ibits; - bita++; /* channel 1 and channel 2 bitalloc are the same */ - if ( (ba=*bita++) ) - { - k=(alloc2 = alloc1+ba)->bits; - if( (d1=alloc2->d) < 0) - { - real cm; - cm=muls[k][scale[x1+3]]; - fraction[1][0][i] = (fraction[0][0][i] = (real) ((int)getbits(k) + d1) ) * cm; - fraction[1][1][i] = (fraction[0][1][i] = (real) ((int)getbits(k) + d1) ) * cm; - fraction[1][2][i] = (fraction[0][2][i] = (real) ((int)getbits(k) + d1) ) * cm; - cm=muls[k][scale[x1]]; - fraction[0][0][i] *= cm; fraction[0][1][i] *= cm; fraction[0][2][i] *= cm; - } - else - { - static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab }; - unsigned int idx,*tab,m1,m2; - m1 = scale[x1]; m2 = scale[x1+3]; - idx = (unsigned int) getbits(k); - tab = (unsigned int *) (table[d1] + idx + idx + idx); - fraction[0][0][i] = muls[*tab][m1]; fraction[1][0][i] = muls[*tab++][m2]; - fraction[0][1][i] = muls[*tab][m1]; fraction[1][1][i] = muls[*tab++][m2]; - fraction[0][2][i] = muls[*tab][m1]; fraction[1][2][i] = muls[*tab][m2]; - } - scale+=6; - } - else { - fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = - fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; - } -/* - should we use individual scalefac for channel 2 or - is the current way the right one , where we just copy channel 1 to - channel 2 ?? - The current 'strange' thing is, that we throw away the scalefac - values for the second channel ...!! --> changed .. now we use the scalefac values of channel one !! -*/ - } - -// if(sblimit > (fr->down_sample_sblimit) ) -// sblimit = fr->down_sample_sblimit; - - if(sblimit > (fr->II_sblimit) ) - sblimit = fr->II_sblimit; - - for(i=sblimit;ilsf) - table = 4; - else - table = translate[fr->sampling_frequency][2-fr->stereo][fr->bitrate_index]; - - sblim = sblims[table]; - - fr->alloc = tables[table]; - fr->II_sblimit = sblim; -} - - - - -int do_layer2(void *mp,struct frame *fr,unsigned char *pcm_sample,int *pcm_point) -{ - int clip=0; - int i,j; - int stereo = fr->stereo; - real fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */ - unsigned int bit_alloc[64]; - int scale[192]; - int single = fr->single; - - II_select_table(fr); - fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? - (fr->mode_ext<<2)+4 : fr->II_sblimit; - - if(stereo == 1 || single == 3) - single = 0; - - II_step_one(bit_alloc, scale, fr); - - for (i=0;i>2); - for (j=0;j<3;j++) - { - if(single >= 0) - { - clip += synth_1to1_mono(mp,fraction[single][j],pcm_sample,pcm_point); - } - else { - int p1 = *pcm_point; - clip += synth_1to1(mp,fraction[0][j],0,pcm_sample,&p1); - clip += synth_1to1(mp,fraction[1][j],1,pcm_sample,pcm_point); - } - } - } - return clip; -} - - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/layer3.c b/Engine/libsrc/almp3-2.0.5/decoder/layer3.c deleted file mode 100644 index d03657bbc50..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/layer3.c +++ /dev/null @@ -1,1619 +0,0 @@ -/* - * Mpeg Layer-3 audio decoder - * -------------------------- - * copyright (c) 1995,1996,1997 by Michael Hipp. - * All rights reserved. See also 'README' - */ - -#include -#include "mpg123.h" -#include "mpglib.h" -#include "huffman.h" - -#define MPEG1 - - -static real ispow[8207]; -static real aa_ca[8],aa_cs[8]; -static real COS1[12][6]; -static real win[4][36]; -static real win1[4][36]; -static real gainpow2[256+118+4]; -static real COS9[9]; -static real COS6_1,COS6_2; -static real tfcos36[9]; -static real tfcos12[3]; - -struct bandInfoStruct { - short longIdx[23]; - short longDiff[22]; - short shortIdx[14]; - short shortDiff[13]; -}; - -int longLimit[9][23]; -int shortLimit[9][14]; - -struct bandInfoStruct bandInfo[9] = { - -/* MPEG 1.0 */ - { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576}, - {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158}, - {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3}, - {4,4,4,4,6,8,10,12,14,18,22,30,56} } , - - { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576}, - {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192}, - {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3}, - {4,4,4,4,6,6,10,12,14,16,20,26,66} } , - - { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} , - {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} , - {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} , - {4,4,4,4,6,8,12,16,20,26,34,42,12} } , - -/* MPEG 2.0 */ - { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, - {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } , - {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} , - {4,4,4,6,6,8,10,14,18,26,32,42,18 } } , - /* docs: 332. mpg123: 330 */ - { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576}, - {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,52,64,70,76,36 } , - {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} , - {4,4,4,6,8,10,12,14,18,24,32,44,12 } } , - - { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, - {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 }, - {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3}, - {4,4,4,6,8,10,12,14,18,24,30,40,18 } } , -/* MPEG 2.5 */ - { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , - {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, - {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, - {4,4,4,6,8,10,12,14,18,24,30,40,18} }, - { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , - {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, - {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, - {4,4,4,6,8,10,12,14,18,24,30,40,18} }, - { {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, - {12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2}, - {0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576}, - {8,8,8,12,16,20,24,28,36,2,2,2,26} } , -}; - -static int mapbuf0[9][152]; -static int mapbuf1[9][156]; -static int mapbuf2[9][44]; -static int *map[9][3]; -static int *mapend[9][3]; - -static unsigned int n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ -static unsigned int i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ - -static real tan1_1[16],tan2_1[16],tan1_2[16],tan2_2[16]; -static real pow1_1[2][16],pow2_1[2][16],pow1_2[2][16],pow2_2[2][16]; - -static unsigned int get1bit(void) -{ - unsigned char rval; - rval = *wordpointer << bitindex; - - bitindex++; - wordpointer += (bitindex>>3); - bitindex &= 7; - - return rval>>7; -} - - - - -/* - * init tables for layer-3 - */ -void init_layer3(int down_sample_sblimit) -{ - int i,j,k,l; - - for(i=-256;i<118+4;i++) - gainpow2[i+256] = pow((double)2.0,-0.25 * (double) (i+210) ); - - for(i=0;i<8207;i++) - ispow[i] = pow((double)i,(double)4.0/3.0); - - for (i=0;i<8;i++) - { - static double Ci[8]={-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037}; - double sq=sqrt(1.0+Ci[i]*Ci[i]); - aa_cs[i] = 1.0/sq; - aa_ca[i] = Ci[i]/sq; - } - - for(i=0;i<18;i++) - { - win[0][i] = win[1][i] = 0.5 * sin( M_PI / 72.0 * (double) (2*(i+0) +1) ) / cos ( M_PI * (double) (2*(i+0) +19) / 72.0 ); - win[0][i+18] = win[3][i+18] = 0.5 * sin( M_PI / 72.0 * (double) (2*(i+18)+1) ) / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 ); - } - for(i=0;i<6;i++) - { - win[1][i+18] = 0.5 / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 ); - win[3][i+12] = 0.5 / cos ( M_PI * (double) (2*(i+12)+19) / 72.0 ); - win[1][i+24] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+13) ) / cos ( M_PI * (double) (2*(i+24)+19) / 72.0 ); - win[1][i+30] = win[3][i] = 0.0; - win[3][i+6 ] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+1) ) / cos ( M_PI * (double) (2*(i+6 )+19) / 72.0 ); - } - - for(i=0;i<9;i++) - COS9[i] = cos( M_PI / 18.0 * (double) i); - - for(i=0;i<9;i++) - tfcos36[i] = 0.5 / cos ( M_PI * (double) (i*2+1) / 36.0 ); - for(i=0;i<3;i++) - tfcos12[i] = 0.5 / cos ( M_PI * (double) (i*2+1) / 12.0 ); - - COS6_1 = cos( M_PI / 6.0 * (double) 1); - COS6_2 = cos( M_PI / 6.0 * (double) 2); - - for(i=0;i<12;i++) - { - win[2][i] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+1) ) / cos ( M_PI * (double) (2*i+7) / 24.0 ); - for(j=0;j<6;j++) - COS1[i][j] = cos( M_PI / 24.0 * (double) ((2*i+7)*(2*j+1)) ); - } - - for(j=0;j<4;j++) { - static int len[4] = { 36,36,12,36 }; - for(i=0;i 0) { - if( i & 1 ) - p1 = pow(base,(i+1.0)*0.5); - else - p2 = pow(base,i*0.5); - } - pow1_1[j][i] = p1; - pow2_1[j][i] = p2; - pow1_2[j][i] = M_SQRT2 * p1; - pow2_2[j][i] = M_SQRT2 * p2; - } - } - - for(j=0;j<9;j++) - { - struct bandInfoStruct *bi = &bandInfo[j]; - int *mp; - int cb,lwin; - short *bdf; - - mp = map[j][0] = mapbuf0[j]; - bdf = bi->longDiff; - for(i=0,cb = 0; cb < 8 ; cb++,i+=*bdf++) { - *mp++ = (*bdf) >> 1; - *mp++ = i; - *mp++ = 3; - *mp++ = cb; - } - bdf = bi->shortDiff+3; - for(cb=3;cb<13;cb++) { - int l = (*bdf++) >> 1; - for(lwin=0;lwin<3;lwin++) { - *mp++ = l; - *mp++ = i + lwin; - *mp++ = lwin; - *mp++ = cb; - } - i += 6*l; - } - mapend[j][0] = mp; - - mp = map[j][1] = mapbuf1[j]; - bdf = bi->shortDiff+0; - for(i=0,cb=0;cb<13;cb++) { - int l = (*bdf++) >> 1; - for(lwin=0;lwin<3;lwin++) { - *mp++ = l; - *mp++ = i + lwin; - *mp++ = lwin; - *mp++ = cb; - } - i += 6*l; - } - mapend[j][1] = mp; - - mp = map[j][2] = mapbuf2[j]; - bdf = bi->longDiff; - for(cb = 0; cb < 22 ; cb++) { - *mp++ = (*bdf++) >> 1; - *mp++ = cb; - } - mapend[j][2] = mp; - - } - - for(j=0;j<9;j++) { - for(i=0;i<23;i++) { - longLimit[j][i] = (bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1; - if(longLimit[j][i] > (down_sample_sblimit) ) - longLimit[j][i] = down_sample_sblimit; - } - for(i=0;i<14;i++) { - shortLimit[j][i] = (bandInfo[j].shortIdx[i] - 1) / 18 + 1; - if(shortLimit[j][i] > (down_sample_sblimit) ) - shortLimit[j][i] = down_sample_sblimit; - } - } - - for(i=0;i<5;i++) { - for(j=0;j<6;j++) { - for(k=0;k<6;k++) { - int n = k + j * 6 + i * 36; - i_slen2[n] = i|(j<<3)|(k<<6)|(3<<12); - } - } - } - for(i=0;i<4;i++) { - for(j=0;j<4;j++) { - for(k=0;k<4;k++) { - int n = k + j * 4 + i * 16; - i_slen2[n+180] = i|(j<<3)|(k<<6)|(4<<12); - } - } - } - for(i=0;i<4;i++) { - for(j=0;j<3;j++) { - int n = j + i * 3; - i_slen2[n+244] = i|(j<<3) | (5<<12); - n_slen2[n+500] = i|(j<<3) | (2<<12) | (1<<15); - } - } - - for(i=0;i<5;i++) { - for(j=0;j<5;j++) { - for(k=0;k<4;k++) { - for(l=0;l<4;l++) { - int n = l + k * 4 + j * 16 + i * 80; - n_slen2[n] = i|(j<<3)|(k<<6)|(l<<9)|(0<<12); - } - } - } - } - for(i=0;i<5;i++) { - for(j=0;j<5;j++) { - for(k=0;k<4;k++) { - int n = k + j * 4 + i * 20; - n_slen2[n+400] = i|(j<<3)|(k<<6)|(1<<12); - } - } - } -} - -/* - * read additional side information - */ -#ifdef MPEG1 -static int III_get_side_info_1(struct III_sideinfo *si,int stereo, - int ms_stereo,long sfreq,int single) -{ - int ch, gr; - int powdiff = (single == 3) ? 4 : 0; - - si->main_data_begin = getbits(9); - if (stereo == 1) - si->private_bits = getbits_fast(5); - else - si->private_bits = getbits_fast(3); - - for (ch=0; chch[ch].gr[0].scfsi = -1; - si->ch[ch].gr[1].scfsi = getbits_fast(4); - } - - for (gr=0; gr<2; gr++) - { - for (ch=0; chch[ch].gr[gr]); - - gr_info->part2_3_length = getbits(12); - gr_info->big_values = getbits_fast(9); - if(gr_info->big_values > 288) { - gr_info->big_values = 288; - } - { - unsigned int qss = getbits_fast(8); - gr_info->pow2gain = gainpow2+256 - qss + powdiff; - } - if(ms_stereo) - gr_info->pow2gain += 2; - gr_info->scalefac_compress = getbits_fast(4); -/* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ - if(get1bit()) - { - int i; - gr_info->block_type = getbits_fast(2); - gr_info->mixed_block_flag = get1bit(); - gr_info->table_select[0] = getbits_fast(5); - gr_info->table_select[1] = getbits_fast(5); - - - /* - * table_select[2] not needed, because there is no region2, - * but to satisfy some verifications tools we set it either. - */ - gr_info->table_select[2] = 0; - for(i=0;i<3;i++) { - unsigned int sbg = (getbits_fast(3)<<3); - gr_info->full_gain[i] = gr_info->pow2gain + sbg; - } - - - if(gr_info->block_type == 0) { - return -1; - } - /* region_count/start parameters are implicit in this case. */ - gr_info->region1start = 36>>1; - gr_info->region2start = 576>>1; - } - else - { - int i,r0c,r1c; - for (i=0; i<3; i++) - gr_info->table_select[i] = getbits_fast(5); - r0c = getbits_fast(4); - r1c = getbits_fast(3); - gr_info->region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ; - gr_info->region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1; - gr_info->block_type = 0; - gr_info->mixed_block_flag = 0; - } - gr_info->preflag = get1bit(); - gr_info->scalefac_scale = get1bit(); - gr_info->count1table_select = get1bit(); - } - } - return 0; -} -#endif - -/* - * Side Info for MPEG 2.0 / LSF - */ -static int III_get_side_info_2(struct III_sideinfo *si,int stereo, - int ms_stereo,long sfreq,int single) -{ - int ch; - int powdiff = (single == 3) ? 4 : 0; - - si->main_data_begin = getbits(8); - if (stereo == 1) - si->private_bits = get1bit(); - else - si->private_bits = getbits_fast(2); - - for (ch=0; chch[ch].gr[0]); - unsigned int qss; - - gr_info->part2_3_length = getbits(12); - gr_info->big_values = getbits_fast(9); - if(gr_info->big_values > 288) { - gr_info->big_values = 288; - } - qss=getbits_fast(8); - gr_info->pow2gain = gainpow2+256 - qss + powdiff; - - if(ms_stereo) - gr_info->pow2gain += 2; - gr_info->scalefac_compress = getbits(9); -/* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ - if(get1bit()) - { - int i; - gr_info->block_type = getbits_fast(2); - gr_info->mixed_block_flag = get1bit(); - gr_info->table_select[0] = getbits_fast(5); - gr_info->table_select[1] = getbits_fast(5); - /* - * table_select[2] not needed, because there is no region2, - * but to satisfy some verifications tools we set it either. - */ - gr_info->table_select[2] = 0; - for(i=0;i<3;i++) { - unsigned int sbg = (getbits_fast(3)<<3); - gr_info->full_gain[i] = gr_info->pow2gain + sbg; - } - - if(gr_info->block_type == 0) { - return -1; - } - /* region_count/start parameters are implicit in this case. */ -/* check this again! */ - if(gr_info->block_type == 2) - gr_info->region1start = 36>>1; - else if(sfreq == 8) -/* check this for 2.5 and sfreq=8 */ - gr_info->region1start = 108>>1; - else - gr_info->region1start = 54>>1; - gr_info->region2start = 576>>1; - } - else - { - int i,r0c,r1c; - for (i=0; i<3; i++) - gr_info->table_select[i] = getbits_fast(5); - r0c = getbits_fast(4); - r1c = getbits_fast(3); - gr_info->region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ; - gr_info->region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1; - gr_info->block_type = 0; - gr_info->mixed_block_flag = 0; - } - gr_info->scalefac_scale = get1bit(); - gr_info->count1table_select = get1bit(); - } - return 0; -} - -/* - * read scalefactors - */ -#ifdef MPEG1 -static int III_get_scale_factors_1(int *scf,struct gr_info_s *gr_info) -{ - static unsigned char slen[2][16] = { - {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, - {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3} - }; - int numbits; - int num0 = slen[0][gr_info->scalefac_compress]; - int num1 = slen[1][gr_info->scalefac_compress]; - - if (gr_info->block_type == 2) - { - int i=18; - numbits = (num0 + num1) * 18; - - if (gr_info->mixed_block_flag) { - for (i=8;i;i--) - *scf++ = getbits_fast(num0); - i = 9; - numbits -= num0; /* num0 * 17 + num1 * 18 */ - } - - for (;i;i--) - *scf++ = getbits_fast(num0); - for (i = 18; i; i--) - *scf++ = getbits_fast(num1); - *scf++ = 0; *scf++ = 0; *scf++ = 0; /* short[13][0..2] = 0 */ - } - else - { - int i; - int scfsi = gr_info->scfsi; - - if(scfsi < 0) { /* scfsi < 0 => granule == 0 */ - for(i=11;i;i--) - *scf++ = getbits_fast(num0); - for(i=10;i;i--) - *scf++ = getbits_fast(num1); - numbits = (num0 + num1) * 10 + num0; - } - else { - numbits = 0; - if(!(scfsi & 0x8)) { - for (i=6;i;i--) - *scf++ = getbits_fast(num0); - numbits += num0 * 6; - } - else { - scf += 6; - } - - if(!(scfsi & 0x4)) { - for (i=5;i;i--) - *scf++ = getbits_fast(num0); - numbits += num0 * 5; - } - else { - scf += 5; - } - - if(!(scfsi & 0x2)) { - for(i=5;i;i--) - *scf++ = getbits_fast(num1); - numbits += num1 * 5; - } - else { - scf += 5; - } - - if(!(scfsi & 0x1)) { - for (i=5;i;i--) - *scf++ = getbits_fast(num1); - numbits += num1 * 5; - } - else { - scf += 5; - } - } - - *scf++ = 0; /* no l[21] in original sources */ - } - return numbits; -} -#endif - -static int III_get_scale_factors_2(int *scf,struct gr_info_s *gr_info,int i_stereo) -{ - unsigned char *pnt; - int i,j; - unsigned int slen; - int n = 0; - int numbits = 0; - - static unsigned char stab[3][6][4] = { - { { 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0} , - { 7, 7, 7,0 } , { 6, 6, 6,3 } , { 8, 8,5,0} } , - { { 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0} , - {12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0} } , - { { 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0} , - { 6,15,12,0 } , { 6,12, 9,6 } , { 6,18,9,0} } }; - - if(i_stereo) /* i_stereo AND second channel -> do_layer3() checks this */ - slen = i_slen2[gr_info->scalefac_compress>>1]; - else - slen = n_slen2[gr_info->scalefac_compress]; - - gr_info->preflag = (slen>>15) & 0x1; - - n = 0; - if( gr_info->block_type == 2 ) { - n++; - if(gr_info->mixed_block_flag) - n++; - } - - pnt = stab[n][(slen>>12)&0x7]; - - for(i=0;i<4;i++) { - int num = slen & 0x7; - slen >>= 3; - if(num) { - for(j=0;j<(int)(pnt[i]);j++) - *scf++ = getbits_fast(num); - numbits += pnt[i] * num; - } - else { - for(j=0;j<(int)(pnt[i]);j++) - *scf++ = 0; - } - } - - n = (n << 1) + 1; - for(i=0;iscalefac_scale; - real *xrpnt = (real *) xr; - int l[3],l3; - int part2remain = gr_info->part2_3_length - part2bits; - int *me; - - { - int bv = gr_info->big_values; - int region1 = gr_info->region1start; - int region2 = gr_info->region2start; - - l3 = ((576>>1)-bv)>>1; -/* - * we may lose the 'odd' bit here !! - * check this later again - */ - if(bv <= region1) { - l[0] = bv; l[1] = 0; l[2] = 0; - } - else { - l[0] = region1; - if(bv <= region2) { - l[1] = bv - l[0]; l[2] = 0; - } - else { - l[1] = region2 - l[0]; l[2] = bv - region2; - } - } - } - - if(gr_info->block_type == 2) { - /* - * decoding with short or mixed mode BandIndex table - */ - int i,max[4]; - int step=0,lwin=0,cb=0; - register real v = 0.0; - register int *m,mc; - - if(gr_info->mixed_block_flag) { - max[3] = -1; - max[0] = max[1] = max[2] = 2; - m = map[sfreq][0]; - me = mapend[sfreq][0]; - } - else { - max[0] = max[1] = max[2] = max[3] = -1; - /* max[3] not really needed in this case */ - m = map[sfreq][1]; - me = mapend[sfreq][1]; - } - - mc = 0; - for(i=0;i<2;i++) { - int lp = l[i]; - struct newhuff *h = ht+gr_info->table_select[i]; - for(;lp;lp--,mc--) { - register int x,y; - if( (!mc) ) { - mc = *m++; - xrpnt = ((real *) xr) + (*m++); - lwin = *m++; - cb = *m++; - if(lwin == 3) { - v = gr_info->pow2gain[(*scf++) << shift]; - step = 1; - } - else { - v = gr_info->full_gain[lwin][(*scf++) << shift]; - step = 3; - } - } - { - register short *val = h->table; - while((y=*val++)<0) { - if (get1bit()) - val -= y; - part2remain--; - } - x = y >> 4; - y &= 0xf; - } - if(x == 15) { - max[lwin] = cb; - part2remain -= h->linbits+1; - x += getbits(h->linbits); - if(get1bit()) - *xrpnt = -ispow[x] * v; - else - *xrpnt = ispow[x] * v; - } - else if(x) { - max[lwin] = cb; - if(get1bit()) - *xrpnt = -ispow[x] * v; - else - *xrpnt = ispow[x] * v; - part2remain--; - } - else - *xrpnt = 0.0; - xrpnt += step; - if(y == 15) { - max[lwin] = cb; - part2remain -= h->linbits+1; - y += getbits(h->linbits); - if(get1bit()) - *xrpnt = -ispow[y] * v; - else - *xrpnt = ispow[y] * v; - } - else if(y) { - max[lwin] = cb; - if(get1bit()) - *xrpnt = -ispow[y] * v; - else - *xrpnt = ispow[y] * v; - part2remain--; - } - else - *xrpnt = 0.0; - xrpnt += step; - } - } - for(;l3 && (part2remain > 0);l3--) { - struct newhuff *h = htc+gr_info->count1table_select; - register short *val = h->table,a; - - while((a=*val++)<0) { - part2remain--; - if(part2remain < 0) { - part2remain++; - a = 0; - break; - } - if (get1bit()) - val -= a; - } - for(i=0;i<4;i++) { - if(!(i & 1)) { - if(!mc) { - mc = *m++; - xrpnt = ((real *) xr) + (*m++); - lwin = *m++; - cb = *m++; - if(lwin == 3) { - v = gr_info->pow2gain[(*scf++) << shift]; - step = 1; - } - else { - v = gr_info->full_gain[lwin][(*scf++) << shift]; - step = 3; - } - } - mc--; - } - if( (a & (0x8>>i)) ) { - max[lwin] = cb; - part2remain--; - if(part2remain < 0) { - part2remain++; - break; - } - if(get1bit()) - *xrpnt = -v; - else - *xrpnt = v; - } - else - *xrpnt = 0.0; - xrpnt += step; - } - } - - while( m < me ) { - if(!mc) { - mc = *m++; - xrpnt = ((real *) xr) + *m++; - if( (*m++) == 3) - step = 1; - else - step = 3; - m++; /* cb */ - } - mc--; - *xrpnt = 0.0; - xrpnt += step; - *xrpnt = 0.0; - xrpnt += step; -/* we could add a little opt. here: - * if we finished a band for window 3 or a long band - * further bands could copied in a simple loop without a - * special 'map' decoding - */ - } - - gr_info->maxband[0] = max[0]+1; - gr_info->maxband[1] = max[1]+1; - gr_info->maxband[2] = max[2]+1; - gr_info->maxbandl = max[3]+1; - - { - int rmax = max[0] > max[1] ? max[0] : max[1]; - rmax = (rmax > max[2] ? rmax : max[2]) + 1; - gr_info->maxb = rmax ? shortLimit[sfreq][rmax] : longLimit[sfreq][max[3]+1]; - } - - } - else { - /* - * decoding with 'long' BandIndex table (block_type != 2) - */ - int *pretab = gr_info->preflag ? pretab1 : pretab2; - int i,max = -1; - int cb = 0; - register int *m = map[sfreq][2]; - register real v = 0.0; - register int mc = 0; -#if 0 - me = mapend[sfreq][2]; -#endif - - /* - * long hash table values - */ - for(i=0;i<3;i++) { - int lp = l[i]; - struct newhuff *h = ht+gr_info->table_select[i]; - - for(;lp;lp--,mc--) { - int x,y; - - if(!mc) { - mc = *m++; - v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift]; - cb = *m++; - } - { - register short *val = h->table; - while((y=*val++)<0) { - if (get1bit()) - val -= y; - part2remain--; - } - x = y >> 4; - y &= 0xf; - } - if (x == 15) { - max = cb; - part2remain -= h->linbits+1; - x += getbits(h->linbits); - if(get1bit()) - *xrpnt++ = -ispow[x] * v; - else - *xrpnt++ = ispow[x] * v; - } - else if(x) { - max = cb; - if(get1bit()) - *xrpnt++ = -ispow[x] * v; - else - *xrpnt++ = ispow[x] * v; - part2remain--; - } - else - *xrpnt++ = 0.0; - - if (y == 15) { - max = cb; - part2remain -= h->linbits+1; - y += getbits(h->linbits); - if(get1bit()) - *xrpnt++ = -ispow[y] * v; - else - *xrpnt++ = ispow[y] * v; - } - else if(y) { - max = cb; - if(get1bit()) - *xrpnt++ = -ispow[y] * v; - else - *xrpnt++ = ispow[y] * v; - part2remain--; - } - else - *xrpnt++ = 0.0; - } - } - - /* - * short (count1table) values - */ - for(;l3 && (part2remain > 0);l3--) { - struct newhuff *h = htc+gr_info->count1table_select; - register short *val = h->table,a; - - while((a=*val++)<0) { - part2remain--; - if(part2remain < 0) { - part2remain++; - a = 0; - break; - } - if (get1bit()) - val -= a; - } - for(i=0;i<4;i++) { - if(!(i & 1)) { - if(!mc) { - mc = *m++; - cb = *m++; - v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift]; - } - mc--; - } - if ( (a & (0x8>>i)) ) { - max = cb; - part2remain--; - if(part2remain < 0) { - part2remain++; - break; - } - if(get1bit()) - *xrpnt++ = -v; - else - *xrpnt++ = v; - } - else - *xrpnt++ = 0.0; - } - } - - /* - * zero part - */ - for(i=(&xr[SBLIMIT][0]-xrpnt)>>1;i;i--) { - *xrpnt++ = 0.0; - *xrpnt++ = 0.0; - } - - gr_info->maxbandl = max+1; - gr_info->maxb = longLimit[sfreq][gr_info->maxbandl]; - } - - while( part2remain > 16 ) { - getbits(16); /* Dismiss stuffing Bits */ - part2remain -= 16; - } - if(part2remain > 0) - getbits(part2remain); - else if(part2remain < 0) { - return 1; /* -> error */ - } - return 0; -} - - -/* - * III_stereo: calculate real channel values for Joint-I-Stereo-mode - */ -static void III_i_stereo(real xr_buf[2][SBLIMIT][SSLIMIT],int *scalefac, - struct gr_info_s *gr_info,int sfreq,int ms_stereo,int lsf) -{ - real (*xr)[SBLIMIT*SSLIMIT] = (real (*)[SBLIMIT*SSLIMIT] ) xr_buf; - struct bandInfoStruct *bi = &bandInfo[sfreq]; - real *tab1,*tab2; - - if(lsf) { - int p = gr_info->scalefac_compress & 0x1; - if(ms_stereo) { - tab1 = pow1_2[p]; tab2 = pow2_2[p]; - } - else { - tab1 = pow1_1[p]; tab2 = pow2_1[p]; - } - } - else { - if(ms_stereo) { - tab1 = tan1_2; tab2 = tan2_2; - } - else { - tab1 = tan1_1; tab2 = tan2_1; - } - } - - if (gr_info->block_type == 2) - { - int lwin,do_l = 0; - if( gr_info->mixed_block_flag ) - do_l = 1; - - for (lwin=0;lwin<3;lwin++) /* process each window */ - { - /* get first band with zero values */ - int is_p,sb,idx,sfb = gr_info->maxband[lwin]; /* sfb is minimal 3 for mixed mode */ - if(sfb > 3) - do_l = 0; - - for(;sfb<12;sfb++) - { - is_p = scalefac[sfb*3+lwin-gr_info->mixed_block_flag]; /* scale: 0-15 */ - if(is_p != 7) { - real t1,t2; - sb = bi->shortDiff[sfb]; - idx = bi->shortIdx[sfb] + lwin; - t1 = tab1[is_p]; t2 = tab2[is_p]; - for (; sb > 0; sb--,idx+=3) - { - real v = xr[0][idx]; - xr[0][idx] = v * t1; - xr[1][idx] = v * t2; - } - } - } - -#if 1 -/* in the original: copy 10 to 11 , here: copy 11 to 12 -maybe still wrong??? (copy 12 to 13?) */ - is_p = scalefac[11*3+lwin-gr_info->mixed_block_flag]; /* scale: 0-15 */ - sb = bi->shortDiff[12]; - idx = bi->shortIdx[12] + lwin; -#else - is_p = scalefac[10*3+lwin-gr_info->mixed_block_flag]; /* scale: 0-15 */ - sb = bi->shortDiff[11]; - idx = bi->shortIdx[11] + lwin; -#endif - if(is_p != 7) - { - real t1,t2; - t1 = tab1[is_p]; t2 = tab2[is_p]; - for ( ; sb > 0; sb--,idx+=3 ) - { - real v = xr[0][idx]; - xr[0][idx] = v * t1; - xr[1][idx] = v * t2; - } - } - } /* end for(lwin; .. ; . ) */ - - if (do_l) - { -/* also check l-part, if ALL bands in the three windows are 'empty' - * and mode = mixed_mode - */ - int sfb = gr_info->maxbandl; - int idx = bi->longIdx[sfb]; - - for ( ; sfb<8; sfb++ ) - { - int sb = bi->longDiff[sfb]; - int is_p = scalefac[sfb]; /* scale: 0-15 */ - if(is_p != 7) { - real t1,t2; - t1 = tab1[is_p]; t2 = tab2[is_p]; - for ( ; sb > 0; sb--,idx++) - { - real v = xr[0][idx]; - xr[0][idx] = v * t1; - xr[1][idx] = v * t2; - } - } - else - idx += sb; - } - } - } - else /* ((gr_info->block_type != 2)) */ - { - int sfb = gr_info->maxbandl; - int is_p,idx = bi->longIdx[sfb]; - for ( ; sfb<21; sfb++) - { - int sb = bi->longDiff[sfb]; - is_p = scalefac[sfb]; /* scale: 0-15 */ - if(is_p != 7) { - real t1,t2; - t1 = tab1[is_p]; t2 = tab2[is_p]; - for ( ; sb > 0; sb--,idx++) - { - real v = xr[0][idx]; - xr[0][idx] = v * t1; - xr[1][idx] = v * t2; - } - } - else - idx += sb; - } - - is_p = scalefac[20]; /* copy l-band 20 to l-band 21 */ - if(is_p != 7) - { - int sb; - real t1 = tab1[is_p],t2 = tab2[is_p]; - - for ( sb = bi->longDiff[21]; sb > 0; sb--,idx++ ) - { - real v = xr[0][idx]; - xr[0][idx] = v * t1; - xr[1][idx] = v * t2; - } - } - } /* ... */ -} - -static void III_antialias(real xr[SBLIMIT][SSLIMIT],struct gr_info_s *gr_info) -{ - int sblim; - - if(gr_info->block_type == 2) - { - if(!gr_info->mixed_block_flag) - return; - sblim = 1; - } - else { - sblim = gr_info->maxb-1; - } - - /* 31 alias-reduction operations between each pair of sub-bands */ - /* with 8 butterflies between each pair */ - - { - int sb; - real *xr1=(real *) xr[1]; - - for(sb=sblim;sb;sb--,xr1+=10) - { - int ss; - real *cs=aa_cs,*ca=aa_ca; - real *xr2 = xr1; - - for(ss=7;ss>=0;ss--) - { /* upper and lower butterfly inputs */ - register real bu = *--xr2,bd = *xr1; - *xr2 = (bu * (*cs) ) - (bd * (*ca) ); - *xr1++ = (bd * (*cs++) ) + (bu * (*ca++) ); - } - } - } -} - -/* - DCT insipired by Jeff Tsay's DCT from the maplay package - this is an optimized version with manual unroll. - - References: - [1] S. Winograd: "On Computing the Discrete Fourier Transform", - Mathematics of Computation, Volume 32, Number 141, January 1978, - Pages 175-199 -*/ - -static void dct36(real *inbuf,real *o1,real *o2,real *wintab,real *tsbuf) -{ - { - register real *in = inbuf; - - in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; - in[14]+=in[13]; in[13]+=in[12]; in[12]+=in[11]; - in[11]+=in[10]; in[10]+=in[9]; in[9] +=in[8]; - in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; - in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; - in[2] +=in[1]; in[1] +=in[0]; - - in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; - in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; - - - { - -#define MACRO0(v) { \ - real tmp; \ - out2[9+(v)] = (tmp = sum0 + sum1) * w[27+(v)]; \ - out2[8-(v)] = tmp * w[26-(v)]; } \ - sum0 -= sum1; \ - ts[SBLIMIT*(8-(v))] = out1[8-(v)] + sum0 * w[8-(v)]; \ - ts[SBLIMIT*(9+(v))] = out1[9+(v)] + sum0 * w[9+(v)]; -#define MACRO1(v) { \ - real sum0,sum1; \ - sum0 = tmp1a + tmp2a; \ - sum1 = (tmp1b + tmp2b) * tfcos36[(v)]; \ - MACRO0(v); } -#define MACRO2(v) { \ - real sum0,sum1; \ - sum0 = tmp2a - tmp1a; \ - sum1 = (tmp2b - tmp1b) * tfcos36[(v)]; \ - MACRO0(v); } - - register const real *c = COS9; - register real *out2 = o2; - register real *w = wintab; - register real *out1 = o1; - register real *ts = tsbuf; - - real ta33,ta66,tb33,tb66; - - ta33 = in[2*3+0] * c[3]; - ta66 = in[2*6+0] * c[6]; - tb33 = in[2*3+1] * c[3]; - tb66 = in[2*6+1] * c[6]; - - { - real tmp1a,tmp2a,tmp1b,tmp2b; - tmp1a = in[2*1+0] * c[1] + ta33 + in[2*5+0] * c[5] + in[2*7+0] * c[7]; - tmp1b = in[2*1+1] * c[1] + tb33 + in[2*5+1] * c[5] + in[2*7+1] * c[7]; - tmp2a = in[2*0+0] + in[2*2+0] * c[2] + in[2*4+0] * c[4] + ta66 + in[2*8+0] * c[8]; - tmp2b = in[2*0+1] + in[2*2+1] * c[2] + in[2*4+1] * c[4] + tb66 + in[2*8+1] * c[8]; - - MACRO1(0); - MACRO2(8); - } - - { - real tmp1a,tmp2a,tmp1b,tmp2b; - tmp1a = ( in[2*1+0] - in[2*5+0] - in[2*7+0] ) * c[3]; - tmp1b = ( in[2*1+1] - in[2*5+1] - in[2*7+1] ) * c[3]; - tmp2a = ( in[2*2+0] - in[2*4+0] - in[2*8+0] ) * c[6] - in[2*6+0] + in[2*0+0]; - tmp2b = ( in[2*2+1] - in[2*4+1] - in[2*8+1] ) * c[6] - in[2*6+1] + in[2*0+1]; - - MACRO1(1); - MACRO2(7); - } - - { - real tmp1a,tmp2a,tmp1b,tmp2b; - tmp1a = in[2*1+0] * c[5] - ta33 - in[2*5+0] * c[7] + in[2*7+0] * c[1]; - tmp1b = in[2*1+1] * c[5] - tb33 - in[2*5+1] * c[7] + in[2*7+1] * c[1]; - tmp2a = in[2*0+0] - in[2*2+0] * c[8] - in[2*4+0] * c[2] + ta66 + in[2*8+0] * c[4]; - tmp2b = in[2*0+1] - in[2*2+1] * c[8] - in[2*4+1] * c[2] + tb66 + in[2*8+1] * c[4]; - - MACRO1(2); - MACRO2(6); - } - - { - real tmp1a,tmp2a,tmp1b,tmp2b; - tmp1a = in[2*1+0] * c[7] - ta33 + in[2*5+0] * c[1] - in[2*7+0] * c[5]; - tmp1b = in[2*1+1] * c[7] - tb33 + in[2*5+1] * c[1] - in[2*7+1] * c[5]; - tmp2a = in[2*0+0] - in[2*2+0] * c[4] + in[2*4+0] * c[8] + ta66 - in[2*8+0] * c[2]; - tmp2b = in[2*0+1] - in[2*2+1] * c[4] + in[2*4+1] * c[8] + tb66 - in[2*8+1] * c[2]; - - MACRO1(3); - MACRO2(5); - } - - { - real sum0,sum1; - sum0 = in[2*0+0] - in[2*2+0] + in[2*4+0] - in[2*6+0] + in[2*8+0]; - sum1 = (in[2*0+1] - in[2*2+1] + in[2*4+1] - in[2*6+1] + in[2*8+1] ) * tfcos36[4]; - MACRO0(4); - } - } - - } -} - -/* - * new DCT12 - */ -static void dct12(real *in,real *rawout1,real *rawout2,register real *wi,register real *ts) -{ -#define DCT12_PART1 \ - in5 = in[5*3]; \ - in5 += (in4 = in[4*3]); \ - in4 += (in3 = in[3*3]); \ - in3 += (in2 = in[2*3]); \ - in2 += (in1 = in[1*3]); \ - in1 += (in0 = in[0*3]); \ - \ - in5 += in3; in3 += in1; \ - \ - in2 *= COS6_1; \ - in3 *= COS6_1; \ - -#define DCT12_PART2 \ - in0 += in4 * COS6_2; \ - \ - in4 = in0 + in2; \ - in0 -= in2; \ - \ - in1 += in5 * COS6_2; \ - \ - in5 = (in1 + in3) * tfcos12[0]; \ - in1 = (in1 - in3) * tfcos12[2]; \ - \ - in3 = in4 + in5; \ - in4 -= in5; \ - \ - in2 = in0 + in1; \ - in0 -= in1; - - - { - real in0,in1,in2,in3,in4,in5; - register real *out1 = rawout1; - ts[SBLIMIT*0] = out1[0]; ts[SBLIMIT*1] = out1[1]; ts[SBLIMIT*2] = out1[2]; - ts[SBLIMIT*3] = out1[3]; ts[SBLIMIT*4] = out1[4]; ts[SBLIMIT*5] = out1[5]; - - DCT12_PART1 - - { - real tmp0,tmp1 = (in0 - in4); - { - real tmp2 = (in1 - in5) * tfcos12[1]; - tmp0 = tmp1 + tmp2; - tmp1 -= tmp2; - } - ts[(17-1)*SBLIMIT] = out1[17-1] + tmp0 * wi[11-1]; - ts[(12+1)*SBLIMIT] = out1[12+1] + tmp0 * wi[6+1]; - ts[(6 +1)*SBLIMIT] = out1[6 +1] + tmp1 * wi[1]; - ts[(11-1)*SBLIMIT] = out1[11-1] + tmp1 * wi[5-1]; - } - - DCT12_PART2 - - ts[(17-0)*SBLIMIT] = out1[17-0] + in2 * wi[11-0]; - ts[(12+0)*SBLIMIT] = out1[12+0] + in2 * wi[6+0]; - ts[(12+2)*SBLIMIT] = out1[12+2] + in3 * wi[6+2]; - ts[(17-2)*SBLIMIT] = out1[17-2] + in3 * wi[11-2]; - - ts[(6+0)*SBLIMIT] = out1[6+0] + in0 * wi[0]; - ts[(11-0)*SBLIMIT] = out1[11-0] + in0 * wi[5-0]; - ts[(6+2)*SBLIMIT] = out1[6+2] + in4 * wi[2]; - ts[(11-2)*SBLIMIT] = out1[11-2] + in4 * wi[5-2]; - } - - in++; - - { - real in0,in1,in2,in3,in4,in5; - register real *out2 = rawout2; - - DCT12_PART1 - - { - real tmp0,tmp1 = (in0 - in4); - { - real tmp2 = (in1 - in5) * tfcos12[1]; - tmp0 = tmp1 + tmp2; - tmp1 -= tmp2; - } - out2[5-1] = tmp0 * wi[11-1]; - out2[0+1] = tmp0 * wi[6+1]; - ts[(12+1)*SBLIMIT] += tmp1 * wi[1]; - ts[(17-1)*SBLIMIT] += tmp1 * wi[5-1]; - } - - DCT12_PART2 - - out2[5-0] = in2 * wi[11-0]; - out2[0+0] = in2 * wi[6+0]; - out2[0+2] = in3 * wi[6+2]; - out2[5-2] = in3 * wi[11-2]; - - ts[(12+0)*SBLIMIT] += in0 * wi[0]; - ts[(17-0)*SBLIMIT] += in0 * wi[5-0]; - ts[(12+2)*SBLIMIT] += in4 * wi[2]; - ts[(17-2)*SBLIMIT] += in4 * wi[5-2]; - } - - in++; - - { - real in0,in1,in2,in3,in4,in5; - register real *out2 = rawout2; - out2[12]=out2[13]=out2[14]=out2[15]=out2[16]=out2[17]=0.0; - - DCT12_PART1 - - { - real tmp0,tmp1 = (in0 - in4); - { - real tmp2 = (in1 - in5) * tfcos12[1]; - tmp0 = tmp1 + tmp2; - tmp1 -= tmp2; - } - out2[11-1] = tmp0 * wi[11-1]; - out2[6 +1] = tmp0 * wi[6+1]; - out2[0+1] += tmp1 * wi[1]; - out2[5-1] += tmp1 * wi[5-1]; - } - - DCT12_PART2 - - out2[11-0] = in2 * wi[11-0]; - out2[6 +0] = in2 * wi[6+0]; - out2[6 +2] = in3 * wi[6+2]; - out2[11-2] = in3 * wi[11-2]; - - out2[0+0] += in0 * wi[0]; - out2[5-0] += in0 * wi[5-0]; - out2[0+2] += in4 * wi[2]; - out2[5-2] += in4 * wi[5-2]; - } -} - -/* - * III_hybrid - */ -static void III_hybrid(void *mp,real fsIn[SBLIMIT][SSLIMIT],real tsOut[SSLIMIT][SBLIMIT], - int ch,struct gr_info_s *gr_info) -{ - struct mpstr *gmp = mp; - - real *tspnt = (real *) tsOut; - real (*block)[2][SBLIMIT*SSLIMIT] = gmp->hybrid_block; - int *blc = gmp->hybrid_blc; - real *rawout1,*rawout2; - int bt; - unsigned int sb = 0; - - { - int b = blc[ch]; - rawout1=block[b][ch]; - b=-b+1; - rawout2=block[b][ch]; - blc[ch] = b; - } - - - if(gr_info->mixed_block_flag) { - sb = 2; - dct36(fsIn[0],rawout1,rawout2,win[0],tspnt); - dct36(fsIn[1],rawout1+18,rawout2+18,win1[0],tspnt+1); - rawout1 += 36; rawout2 += 36; tspnt += 2; - } - - bt = gr_info->block_type; - if(bt == 2) { - for (; sbmaxb; sb+=2,tspnt+=2,rawout1+=36,rawout2+=36) { - dct12(fsIn[sb],rawout1,rawout2,win[2],tspnt); - dct12(fsIn[sb+1],rawout1+18,rawout2+18,win1[2],tspnt+1); - } - } - else { - for (; sbmaxb; sb+=2,tspnt+=2,rawout1+=36,rawout2+=36) { - dct36(fsIn[sb],rawout1,rawout2,win[bt],tspnt); - dct36(fsIn[sb+1],rawout1+18,rawout2+18,win1[bt],tspnt+1); - } - } - - for(;sbstereo; - int single = fr->single; - int ms_stereo,i_stereo; - int sfreq = fr->sampling_frequency; - int stereo1,granules; - - - - if(stereo == 1) { /* stream is mono */ - stereo1 = 1; - single = 0; - } - else if(single >= 0) /* stream is stereo, but force to mono */ - stereo1 = 1; - else - stereo1 = 2; - - if(fr->mode == MPG_MD_JOINT_STEREO) { - ms_stereo = fr->mode_ext & 0x2; - i_stereo = fr->mode_ext & 0x1; - } - else - ms_stereo = i_stereo = 0; - - - if(fr->lsf) { - granules = 1; - if (III_get_side_info_2(&sideinfo,stereo,ms_stereo,sfreq,single)) - return -1; - } - else { - granules = 2; -#ifdef MPEG1 - if (III_get_side_info_1(&sideinfo,stereo,ms_stereo,sfreq,single)) - return -1; -#endif - } - - if(almp3_set_pointer(mp,sideinfo.main_data_begin) == MP3_ERR) - return 0; - - - for (gr=0;grlsf) - part2bits = III_get_scale_factors_2(scalefacs[0],gr_info,0); - else { -#ifdef MPEG1 - part2bits = III_get_scale_factors_1(scalefacs[0],gr_info); -#endif - } - if(III_dequantize_sample(hybridIn[0], scalefacs[0],gr_info,sfreq,part2bits)) - return 0; - } - if(stereo == 2) { - struct gr_info_s *gr_info = &(sideinfo.ch[1].gr[gr]); - long part2bits; - if(fr->lsf) - part2bits = III_get_scale_factors_2(scalefacs[1],gr_info,i_stereo); - else { -#ifdef MPEG1 - part2bits = III_get_scale_factors_1(scalefacs[1],gr_info); -#endif - } - - if(III_dequantize_sample(hybridIn[1],scalefacs[1],gr_info,sfreq,part2bits)) - return 0; - - if(ms_stereo) { - int i; - for(i=0;ilsf); - - if(ms_stereo || i_stereo || (single == 3) ) { - if(gr_info->maxb > sideinfo.ch[0].gr[gr].maxb) - sideinfo.ch[0].gr[gr].maxb = gr_info->maxb; - else - gr_info->maxb = sideinfo.ch[0].gr[gr].maxb; - } - - switch(single) { - case 3: - { - register unsigned int i; - register real *in0 = (real *) hybridIn[0],*in1 = (real *) hybridIn[1]; - for(i=0;imaxb;i++,in0++) - *in0 = (*in0 + *in1++); /* *0.5 done by pow-scale */ - } - break; - case 1: - { - register unsigned int i; - register real *in0 = (real *) hybridIn[0],*in1 = (real *) hybridIn[1]; - for(i=0;imaxb;i++) - *in0++ = *in1++; - } - break; - } - } - - - for(ch=0;ch= 0) { - clip += synth_1to1_mono(mp,hybridOut[0][ss],pcm_sample,pcm_point); - } - else { - int p1 = *pcm_point; - clip += synth_1to1(mp,hybridOut[0][ss],0,pcm_sample,&p1); - clip += synth_1to1(mp,hybridOut[1][ss],1,pcm_sample,pcm_point); - } - } - } - - return 0; -} - diff --git a/Engine/libsrc/almp3-2.0.5/decoder/mpg123.h b/Engine/libsrc/almp3-2.0.5/decoder/mpg123.h deleted file mode 100644 index 410e514f298..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/mpg123.h +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include - -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif - -#ifndef M_SQRT2 -# define M_SQRT2 1.41421356237309504880 -#endif - - -#ifdef REAL_IS_FLOAT -# define real float -#elif defined(REAL_IS_LONG_DOUBLE) -# define real long double -#else -# define real double -#endif - - -/* AUDIOBUFSIZE = n*64 with n=1,2,3 ... */ -#define AUDIOBUFSIZE 16384 - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -#define SBLIMIT 32 -#define SSLIMIT 18 - -#define SCALE_BLOCK 12 /* Layer 2 */ - -#define MPG_MD_STEREO 0 -#define MPG_MD_JOINT_STEREO 1 -#define MPG_MD_DUAL_CHANNEL 2 -#define MPG_MD_MONO 3 - -#define MAXFRAMESIZE 1792 - - -/* Pre Shift fo 16 to 8 bit converter table */ -#define AUSHIFT (3) - - - - - -struct frame { - int stereo; - int jsbound; - int single; - int lsf; - int mpeg25; - int header_change; - int lay; - int error_protection; - int bitrate_index; - int sampling_frequency; - int padding; - int extension; - int mode; - int mode_ext; - int copyright; - int original; - int emphasis; - int framesize; /* computed framesize */ - int II_sblimit; /* Layer 2 */ - struct al_table *alloc; /* Layer 2 */ - int (*do_layer)(void *mp,struct frame *fr,unsigned char *, int *);/* Layer 2 */ -}; - -/* extern unsigned int get1bit(void);*/ -extern unsigned int getbits(int); -extern unsigned int getbits_fast(int); -extern int almp3_set_pointer(void *,long); - -extern unsigned char *wordpointer; -extern int bitindex; - -extern int do_layer3(void *mp,struct frame *fr,unsigned char *,int *); -extern int do_layer2(void *mp,struct frame *fr,unsigned char *,int *); - -extern int decode_header(struct frame *fr,unsigned long newhead); -extern int head_check(unsigned long head); - -struct gr_info_s { - int scfsi; - unsigned part2_3_length; - unsigned big_values; - unsigned scalefac_compress; - unsigned block_type; - unsigned mixed_block_flag; - unsigned table_select[3]; - unsigned subblock_gain[3]; - unsigned maxband[3]; - unsigned maxbandl; - unsigned maxb; - unsigned region1start; - unsigned region2start; - unsigned preflag; - unsigned scalefac_scale; - unsigned count1table_select; - real *full_gain[3]; - real *pow2gain; -}; - -struct III_sideinfo -{ - unsigned main_data_begin; - unsigned private_bits; - struct { - struct gr_info_s gr[2]; - } ch[2]; -}; - -extern int synth_1to1 (void *,real *,int,unsigned char *,int *); -extern int tsynth_1to1 (real *,int,unsigned char *,int *); -extern int synth_1to1_mono (void *,real *,unsigned char *,int *); - -extern void init_layer3(int); -extern void init_layer2(void); -extern void make_decode_tables(long scale); -extern void dct64(real *,real *,real *); - -extern long almp3freqs[9]; -extern int almp3tabsel_123[2][3][16]; -extern real muls[27][64]; -extern real decwin[512+32]; -extern real *pnts[5]; diff --git a/Engine/libsrc/almp3-2.0.5/decoder/mpglib.h b/Engine/libsrc/almp3-2.0.5/decoder/mpglib.h deleted file mode 100644 index af5e279027a..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/mpglib.h +++ /dev/null @@ -1,49 +0,0 @@ - -struct buf { - unsigned char *pnt; - long size; - long pos; - struct buf *next; - struct buf *prev; -}; - -struct framebuf { - struct buf *buf; - long pos; - struct frame *next; - struct frame *prev; -}; - -struct mpstr { - struct buf *head,*tail; - int bsize; - int framesize; - int fsizeold; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - real hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - real synth_buffs[2][2][0x110]; - int synth_bo; -}; - - -#define MP3_ERR -1 -#define MP3_OK 0 -#define MP3_NEED_MORE 1 - - -#ifdef __cplusplus -extern "C" { -#endif - -int InitMP3(struct mpstr *mp); -int decodeMP3(struct mpstr *mp,char *inmemory,int inmemsize, - char *outmemory,int outmemsize,int *done); -void ExitMP3(struct mpstr *mp); - -#ifdef __cplusplus -} -#endif diff --git a/Engine/libsrc/almp3-2.0.5/decoder/tabinit.c b/Engine/libsrc/almp3-2.0.5/decoder/tabinit.c deleted file mode 100644 index f0fa1150181..00000000000 --- a/Engine/libsrc/almp3-2.0.5/decoder/tabinit.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "mpg123.h" - -real decwin[512+32]; -static real cos64[16],cos32[8],cos16[4],cos8[2],cos4[1]; -real *pnts[] = { cos64,cos32,cos16,cos8,cos4 }; - -#if 0 -static unsigned char *conv16to8_buf = NULL; -unsigned char *conv16to8; -#endif - -static long intwinbase[] = { - 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, - -2, -3, -3, -4, -4, -5, -5, -6, -7, -7, - -8, -9, -10, -11, -13, -14, -16, -17, -19, -21, - -24, -26, -29, -31, -35, -38, -41, -45, -49, -53, - -58, -63, -68, -73, -79, -85, -91, -97, -104, -111, - -117, -125, -132, -139, -147, -154, -161, -169, -176, -183, - -190, -196, -202, -208, -213, -218, -222, -225, -227, -228, - -228, -227, -224, -221, -215, -208, -200, -189, -177, -163, - -146, -127, -106, -83, -57, -29, 2, 36, 72, 111, - 153, 197, 244, 294, 347, 401, 459, 519, 581, 645, - 711, 779, 848, 919, 991, 1064, 1137, 1210, 1283, 1356, - 1428, 1498, 1567, 1634, 1698, 1759, 1817, 1870, 1919, 1962, - 2001, 2032, 2057, 2075, 2085, 2087, 2080, 2063, 2037, 2000, - 1952, 1893, 1822, 1739, 1644, 1535, 1414, 1280, 1131, 970, - 794, 605, 402, 185, -45, -288, -545, -814, -1095, -1388, - -1692, -2006, -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788, - -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, -7910, -8209, - -8491, -8755, -8998, -9219, -9416, -9585, -9727, -9838, -9916, -9959, - -9966, -9935, -9863, -9750, -9592, -9389, -9139, -8840, -8492, -8092, - -7640, -7134, -6574, -5959, -5288, -4561, -3776, -2935, -2037, -1082, - -70, 998, 2122, 3300, 4533, 5818, 7154, 8540, 9975, 11455, - 12980, 14548, 16155, 17799, 19478, 21189, 22929, 24694, 26482, 28289, - 30112, 31947, 33791, 35640, 37489, 39336, 41176, 43006, 44821, 46617, - 48390, 50137, 51853, 53534, 55178, 56778, 58333, 59838, 61289, 62684, - 64019, 65290, 66494, 67629, 68692, 69679, 70590, 71420, 72169, 72835, - 73415, 73908, 74313, 74630, 74856, 74992, 75038 }; - -void make_decode_tables(long scaleval) -{ - int i,j,k,kr,divv; - real *table,*costab; - - - for(i=0;i<5;i++) - { - kr=0x10>>i; divv=0x40>>i; - costab = pnts[i]; - for(k=0;k - -#include "almp3dll.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* common define */ - -#define ALMP3_MAJOR_VERSION 2 -#define ALMP3_MINOR_VERSION 0 -#define ALMP3_SUB_VERSION 4 -#define ALMP3_VERSION_STR "2.0.4" -#define ALMP3_DATE_STR "08/04/2003" -#define ALMP3_DATE 20030408 /* yyyymmdd */ - -/* error codes */ - -#define ALMP3_OK 0 - -#define ALMP3_PLAY_BUFFERTOOSMALL -1 - -#define ALMP3_POLL_PLAYJUSTFINISHED 1 -#define ALMP3_POLL_NOTPLAYING -1 -#define ALMP3_POLL_FRAMECORRUPT -2 -#define ALMP3_POLL_BUFFERUNDERRUN -3 -#define ALMP3_POLL_INTERNALERROR -4 - - -/* API - MP3 */ - -typedef struct ALMP3_MP3 ALMP3_MP3; - - -ALMP3_DLL_DECLSPEC ALMP3_MP3 *almp3_create_mp3(void *data, int data_len); -ALMP3_DLL_DECLSPEC void almp3_destroy_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC int almp3_play_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan); -ALMP3_DLL_DECLSPEC int almp3_play_ex_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan, int speed, int loop); -ALMP3_DLL_DECLSPEC void almp3_stop_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC void almp3_rewind_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_frames_mp3(ALMP3_MP3 *mp3, int frame); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_msecs_mp3(ALMP3_MP3 *mp3, int msecs); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_secs_mp3(ALMP3_MP3 *mp3, int secs); -ALMP3_DLL_DECLSPEC void almp3_seek_abs_bytes_mp3(ALMP3_MP3 *mp3, int bytes); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_frames_mp3(ALMP3_MP3 *mp3, int frame); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_msecs_mp3(ALMP3_MP3 *mp3, int msec); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_secs_mp3(ALMP3_MP3 *mp3, int sec); -ALMP3_DLL_DECLSPEC void almp3_seek_rel_bytes_mp3(ALMP3_MP3 *mp3, int bytes); -ALMP3_DLL_DECLSPEC void almp3_adjust_mp3(ALMP3_MP3 *mp3, int vol, int pan, int speed, int loop); - -ALMP3_DLL_DECLSPEC int almp3_poll_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC void almp3_start_autopoll_mp3(ALMP3_MP3 *mp3, int speed); -ALMP3_DLL_DECLSPEC void almp3_stop_autopoll_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC int almp3_get_pos_frames_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_msecs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_secs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_bytes_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_frames_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_secs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_msecs_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_length_bytes_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_msecs_per_frame_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_bitrate_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_layer_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_is_stereo_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_bits_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_is_stereo_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_freq_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC SAMPLE *almp3_create_sample_from_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC void *almp3get_output_wave_mp3(ALMP3_MP3 *mp3, int *buffer_size); - -ALMP3_DLL_DECLSPEC int almp3_is_playing_mp3(ALMP3_MP3 *mp3); -ALMP3_DLL_DECLSPEC int almp3_is_looping_mp3(ALMP3_MP3 *mp3); - -ALMP3_DLL_DECLSPEC AUDIOSTREAM *almp3_get_audiostream_mp3(ALMP3_MP3 *mp3); - - - -/* API - MP3STREAM */ - -typedef struct ALMP3_MP3STREAM ALMP3_MP3STREAM; - - -ALMP3_DLL_DECLSPEC ALMP3_MP3STREAM *almp3_create_mp3stream(void *first_data_buffer, int data_buffer_len, int last_block); -ALMP3_DLL_DECLSPEC ALMP3_MP3STREAM *almp3_create_mp3stream_ex(void *first_data_buffer, int data_buffer_len, int last_block, int downsample, int downmix); -ALMP3_DLL_DECLSPEC void almp3_destroy_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC int almp3_play_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan); -ALMP3_DLL_DECLSPEC int almp3_play_ex_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan, int speed); -ALMP3_DLL_DECLSPEC void almp3_stop_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void almp3_adjust_mp3stream(ALMP3_MP3STREAM *mp3, int vol, int pan, int speed); - -ALMP3_DLL_DECLSPEC int almp3_poll_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void almp3_start_autopoll_mp3stream(ALMP3_MP3STREAM *mp3, int speed); -ALMP3_DLL_DECLSPEC void almp3_stop_autopoll_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void *almp3_get_mp3stream_buffer(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC void almp3_free_mp3stream_buffer(ALMP3_MP3STREAM *mp3, int bytes_used); - -ALMP3_DLL_DECLSPEC int almp3_get_length_frames_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_length_secs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_length_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_length_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); -ALMP3_DLL_DECLSPEC int almp3_get_pos_frames_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_msecs_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_secs_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_pos_bytes_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_msecs_per_frame_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_bitrate_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_layer_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_bits_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3); -ALMP3_DLL_DECLSPEC int almp3_get_wave_freq_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC void *almp3_get_output_wave_mp3stream(ALMP3_MP3STREAM *mp3, int *buffer_size); - -ALMP3_DLL_DECLSPEC int almp3_is_playing_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC AUDIOSTREAM *almp3_get_audiostream_mp3stream(ALMP3_MP3STREAM *mp3); - -ALMP3_DLL_DECLSPEC int almp3_seek_abs_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_abs_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msecs, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_abs_secs_mp3stream(ALMP3_MP3STREAM *mp3, int secs, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_abs_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msec, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_secs_mp3stream(ALMP3_MP3STREAM *mp3, int sec, int total_size); -ALMP3_DLL_DECLSPEC int almp3_seek_rel_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/libsrc/almp3-2.0.5/include/almp3dll.h b/Engine/libsrc/almp3-2.0.5/include/almp3dll.h deleted file mode 100644 index a69c03f66a0..00000000000 --- a/Engine/libsrc/almp3-2.0.5/include/almp3dll.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Allegro MP3 - a wrapper for mpglib from mpg123 */ -/* to play MP3 files with Allegro */ - -/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ -/* Allegro MP3 is copyright (c) 2001, 2002 Javier Gonz lez */ - -/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ - - -#ifndef ALMP3_DLL_DECLSPEC -# ifdef ALMP3_DLL -# ifdef ALMP3_DLL_EXPORTS -# define ALMP3_DLL_DECLSPEC __declspec(dllexport) -# else -# define ALMP3_DLL_DECLSPEC __declspec(dllimport) -# endif -# else -# define ALMP3_DLL_DECLSPEC -# endif -#endif diff --git a/Engine/libsrc/almp3-2.0.5/src/almp3.c b/Engine/libsrc/almp3-2.0.5/src/almp3.c deleted file mode 100644 index c5b1d864410..00000000000 --- a/Engine/libsrc/almp3-2.0.5/src/almp3.c +++ /dev/null @@ -1,2025 +0,0 @@ -/* Allegro MP3 - a wrapper for mpglib from mpg123 */ -/* to play MP3 files with Allegro */ - -/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ -/* Allegro MP3 is copyright (c) 2001, 2002 Javier González */ - -/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ - - -#include -#include -#include -#include "decoder/mpg123.h" -#include "decoder/mpglib.h" - - -/* structures */ - -/* struct typically used in VBR (Variable Bitrate) MP3s */ - -#define XING_FRAMES_FLAG 1 -#define XING_BYTES_FLAG 2 -#define XING_TOC_FLAG 4 -#define XING_VBR_SCALE_FLAG 8 - -typedef struct XING_HEADER { - int flags; - int frames; /* number of frames the MP3 has */ - int bytes; /* number of bytes the file has */ - int vbr_scale; /* encoded vbr scale */ - unsigned char toc[100]; /* used for seeking */ -} XING_HEADER; - - -/* standard ALMP3_MP3 structure */ - -struct ALMP3_MP3 { - /* data info */ - void *data; /* mp3 data */ - char *data_cursor; /* pointer to data being read */ - int data_len; /* size of the data */ - int data_start_skipped; /* used when ID3v2 headers are present */ - /* and we are asked to seek or get the */ - /* pos in bytes */ - int data_end_skipped; /* used when ID3v1 headers are present */ - /* and we are asked to seek or get the */ - /* pos in bytes */ - /* decoder info */ - struct mpstr mpeg; /* decoder handler */ - XING_HEADER *xing_header; /* xing header if available */ - int dec_reinit; /* true if the decoder needs to be */ - /* reinitialized in next poll */ - /* mp3 info */ - int outbytes_per_frame; /* bytes created per frame */ - int framebytes; /* decoder first framebytes */ - int bitrate, layer; /* mp3 general info */ - int total_frames; /* number of frames the mp3 has */ - int current_frame; /* frame currently being played */ - /* playing info */ - AUDIOSTREAM *audiostream; /* the audiostream we are using to play */ - /* also used to know when it's playing */ - int freq, stereo, bits, loop; /* audio general info */ - int frames_per_poll; /* number of frames per play poll */ - int auto_polling; /* set if the mp3 is auto polling */ - int auto_poll_speed; /* auto poll speed in msecs */ - int wait_for_audio_stop; /* set if we are just waiting for the - audiobuffer to stop plaing the last - frame */ -}; - - -/* standard ALMP3_MP3STREAM structure */ - -struct ALMP3_MP3STREAM { - /* data info */ - void *databuf1, *databuf2; /* data buffers */ - char *full_databuf; /* to be used when the 2 buffers are filled */ - int data_cursor; /* pointer to data being read */ - int databuf_selector; /* 1 = databuf1, -1 = databuf2 */ - int databuf_len; /* size of the data buffer */ - int unsel_databuf_free; /* TRUE when the unselected databuffer */ - /* is free and needs to be filled */ - int bytes_used; /* number of bytes to use from the buffer */ - /* or -1 if the full buffer */ - int data_start_skipped; /* used when ID3v2 headers are present */ - /* and we are asked to seek or get the */ - /* pos in bytes */ - /* decoder info */ - struct mpstr mpeg; /* decoder handler */ - XING_HEADER *xing_header; /* xing header if available */ - int dec_reinit; /* true if the decoder needs to be */ - /* reinitialized in next poll */ - /* mp3 info */ - int outbytes_per_frame; /* bytes created per frame */ - int framebytes; /* decoder first framebytes */ - int bitrate, layer; /* mp3 general info */ - int current_frame; /* frame currently being played */ - int current_byte; /* byte currently being decoded */ - int total_frames; /* number of frames the mp3 has */ - /* playing info */ - AUDIOSTREAM *audiostream; /* the audiostream we are using to play */ - /* also used to know when it's playing */ - int freq, stereo, bits; /* audio general info */ - int frames_per_poll; /* number of frames per play poll */ - int auto_polling; /* set if the mp3 is auto polling */ - int auto_poll_speed; /* auto poll speed in msecs */ - int wait_for_audio_stop; /* set if we are just waiting for the - audiobuffer to stop plaing the last - frame */ -}; - - -/* common functions */ - - -static int almp3_check_frame_validity(unsigned int header) { - /* return 0 if invalid, -1 if valid */ - - /* test sync */ - if ((header & 0xFFE00000) != 0xFFE00000) - return 0; - - /* mpeg version */ - if ((header & 0x180000) == 0x80000) - return 0; - - /* mpeg layer */ - if (((header & 0x60000) != 0x20000) && ((header & 0x60000) != 0x10000)) - return 0; - - /* bitrate */ - if (((header & 0xF000) == 0xF000) || ((header & 0xF000) == 0x0000)) - return 0; - - /* freq */ - if ((header & 0xC00) == 0xC00) - return 0; - - /* emphasis */ -/*if ((header & 0x3) == 0x2) - return 0;*/ - - return -1; -} - - -static int almp3_get_big_endian(unsigned char *p) { - int x; - x = *p; x <<= 8; - x |= *(p + 1); x <<= 8; - x |= *(p + 2); x <<= 8; - x |= *(p + 3); - return x; -} - - -static int almp3_get_id3v2_skip_bytes(unsigned char *p) { - int id3v2_skip_size = 0; - /* test for ID3v2 and if exists, skip it */ - if (memcmp((unsigned char *)p, "ID3", 3) == 0) { - int footer_present = p[5] & 0x10; - p += 6; - id3v2_skip_size = *(p + 3) | (*(p + 2) << 7) | (*(p + 1) << 14) | (*p << 21); - if (footer_present) - id3v2_skip_size += 20; - else - id3v2_skip_size += 10; - } - else - id3v2_skip_size = 0; - - return id3v2_skip_size; -} - - - -/* API - MP3 */ - -/* function called in an interrupt */ - -static void almp3_autopoll_mp3(void *mp3) { - almp3_poll_mp3((ALMP3_MP3 *)mp3); -} -END_OF_FUNCTION(almp3_autopoll_mp3); - - -/* helper functions */ - -static int almp3_reinit_decoder_mp3(ALMP3_MP3 *mp3) { - /* reinitialize the decoder */ - ExitMP3(&(mp3->mpeg)); - InitMP3(&(mp3->mpeg)); - mp3->dec_reinit = FALSE; - - return 0; -} - - -static void almp3_convert_to_unsigned_format_mp3(ALMP3_MP3 *mp3, void *buf) { - /* convert to allegro unsigned format */ - if (mp3->bits == 16) { - unsigned int i, *j, k; - k = (mp3->outbytes_per_frame * mp3->frames_per_poll) / 4; - for (i = 0, j = (unsigned int *)buf; i < k; i++, j++) - *j ^= 0x80008000; - } -} - - -static int almp3_get_bytes_at_frame_using_toc_mp3(ALMP3_MP3 *mp3, int frame) { - int tof[100], i, flags; - int bytesmin, bytesmax, bytesdif, bytes; - int framemin, framemax, framedif; - - /* check for missing data */ - if (mp3->xing_header == NULL) - return -1; - flags = mp3->xing_header->flags; - if (!(flags & XING_FRAMES_FLAG) || !(flags & XING_TOC_FLAG)) - return -1; - if ((frame >= mp3->xing_header->frames) || (frame < 0)) - return -1; - - /* create a table of frames */ - for (i = 0; i < 100; i++) - tof[i] = (mp3->xing_header->toc[i] * mp3->xing_header->frames) / 256; - - /* check in what part of the table of frames is our frame */ - for (i = 0; i < 100; i++) { - if (frame <= tof[i]) - break; - } - - /* our frame is between the i% and (i + 1)% of the file */ - /* let's do more calcules for a "fine" seeking */ - if (i == 100) - return mp3->data_len; - bytesmin = (mp3->data_len * i) / 100; - framemin = tof[i]; - if (i < 99) { - bytesmax = (mp3->data_len * (i + 1)) / 100; - framemax = tof[i + 1]; - } - else { - bytesmax = mp3->data_len - 1; - framemax = mp3->xing_header->frames - 1; - } - bytesdif = bytesmax - bytesmin; - framedif = framemax - framemin; - - bytes = bytesmin; - if (framedif) - bytes += (((frame - framemin) * bytesdif) / framedif); - - return bytes; -} - - -static int almp3_get_outbytes_per_sec_mp3(ALMP3_MP3 *mp3) { - int bytes_out; - bytes_out = (mp3->stereo ? 2 : 1) * (mp3->bits / 8) * mp3->freq; - return bytes_out; -} - - -static int almp3_decode_frame_mp3(ALMP3_MP3 *mp3, char *inbuf, char *outbuf, int *size_done, int *inread) { - /* send bytes until it has enough to render a frame */ - int ret; - *inread = 0; - - ret = decodeMP3(&(mp3->mpeg), NULL, 0, outbuf, 8192, size_done); - if (ret == MP3_NEED_MORE) { - int chunk_size, data_left; - - if (mp3->xing_header) - chunk_size = MAXFRAMESIZE; - else - chunk_size = mp3->framebytes + 4; - - data_left = mp3->data_len - ((char *)mp3->data_cursor - (char *)mp3->data); - do { - if (data_left <= 0) - break; - - if (data_left < chunk_size) { - ret = decodeMP3(&(mp3->mpeg), inbuf, data_left, outbuf, 8192, size_done); - inbuf += data_left; - *inread += data_left; - data_left = 0; - } - else { - ret = decodeMP3(&(mp3->mpeg), inbuf, chunk_size, outbuf, 8192, size_done); - data_left -= chunk_size; - inbuf += chunk_size; - *inread += chunk_size; - } - } while (ret == MP3_NEED_MORE); - } - - { - int val = almp3_check_frame_validity((mp3->mpeg).header); - - if (ret == MP3_NEED_MORE) - return -3; - - if ((ret == MP3_ERR) || (val == 0) || ((mp3->mpeg).fr.framesize <= 0)) - return 0; - else - return -1; - } -} - - -/* API functions */ - -ALMP3_MP3 *almp3_create_mp3(void *data_, int data_len) { - char *data=(char*)data_; - ALMP3_MP3 *mp3; - struct mpstr test_mpeg; - unsigned char *p = (unsigned char *)data; - int data_end_skipped, data_start_skipped; - int ret; - char test_outbuf[8192]; - int test_size, framebytes; - - /* test for ID3v1 and if exists, skip it */ - if (memcmp((void *)&p[data_len - 128], "TAG", 3) == 0) { - data_len -= 128; - data_end_skipped = 128; - } - else - data_end_skipped = 0; - - /* test for ID3v2 and if exists, skip it */ - data_start_skipped = almp3_get_id3v2_skip_bytes(p); - data += data_start_skipped; - data_len -= data_start_skipped; - - /* test the next 16 * MAXFRAMESIZE bytes after ID3v2 until we find one valid frame */ - { - int found, max, skipbytes; - if (data_len >= (16 * MAXFRAMESIZE)) - max = 16 * MAXFRAMESIZE; - else - max = data_len; - - found = FALSE; - skipbytes = 0; - while (!found && (skipbytes < max)) { - int data_left = max - skipbytes; - char *p = (char *)data + skipbytes; - - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) == -1) { - /* probably found, check */ - InitMP3(&test_mpeg); - ret = decodeMP3(&test_mpeg, p, data_left, test_outbuf, 8192, &test_size); - if ((ret == MP3_OK) && (test_mpeg.fr.framesize > 0)) { - char *p2 = p + test_mpeg.fr.framesize + 4; - if (p2 < ((char *)data + max)) { - /* check the next frame to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p2)) != 0) - found = TRUE; - } - else { - /* guess it is right */ - found = TRUE; - } - } - - if (!found) - ExitMP3(&test_mpeg); - } - - if (!found) - skipbytes++; - } - - if (!found) { - return NULL; - } - - data_start_skipped += skipbytes; - data_len -= skipbytes; - data += skipbytes; - } - - /* must be layer III or II */ - if ((test_mpeg.fr.lay != 3) && (test_mpeg.fr.lay != 2)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* the mp3 is ok, get some info */ - framebytes = test_mpeg.fr.framesize + 4; - if ((framebytes <= 4)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* create a new mp3 struct and init the real decoder */ - mp3 = (ALMP3_MP3 *)malloc(sizeof(ALMP3_MP3)); - if (mp3 == NULL) { - ExitMP3(&test_mpeg); - return NULL; - } - InitMP3(&(mp3->mpeg)); - - - /* fill in the mp3 struct */ - mp3->data_start_skipped = data_start_skipped; - mp3->data_end_skipped = data_end_skipped; - mp3->freq = almp3freqs[test_mpeg.fr.sampling_frequency]; - if (test_mpeg.fr.stereo >= 2) - mp3->stereo = TRUE; - else - mp3->stereo = FALSE; - mp3->bits = 16; - mp3->outbytes_per_frame = test_size; - mp3->audiostream = NULL; - mp3->data = data; - mp3->data_cursor = (char *)data; - mp3->data_len = data_len; - mp3->current_frame = 0; - mp3->auto_polling = FALSE; - mp3->dec_reinit = FALSE; - mp3->bitrate = almp3tabsel_123[test_mpeg.fr.lsf][test_mpeg.fr.lay - 1][test_mpeg.fr.bitrate_index] * 1000; - mp3->layer = test_mpeg.fr.lay; - if (mp3->layer <= 0) - mp3->layer = -1; - mp3->xing_header = NULL; - mp3->framebytes = framebytes; - - /* if outbytes_per_frame is incorrect, correct it */ - if (mp3->outbytes_per_frame <= 0) { - int samples = 1152; - if (mp3->layer == 2) - samples = 1152; - if (mp3->layer == 3) { - if ((mp3->freq >= 32000) && (mp3->freq < 48000)) - samples = 1152; - else if ((mp3->freq >= 8000) && (mp3->freq < 24000)) - samples = 576; - } - mp3->outbytes_per_frame = samples * (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - } - - /* check for the xing header */ - p = (unsigned char *)data; - if (!test_mpeg.fr.lsf) { /* mpeg1 */ - if (test_mpeg.fr.mode != 3) - p += 32 + 4; - else - p += 17 + 4; - } - else { /* mpeg2 */ - if (test_mpeg.fr.mode != 3) - p += 17 + 4; - else - p += 9 + 4; - } - - if (memcmp(p, "Xing", 4) == 0) { - - /* found */ - int x; - p += 4; - mp3->xing_header = (XING_HEADER *)malloc(sizeof(XING_HEADER)); - x = mp3->xing_header->flags = almp3_get_big_endian(p); - p += 4; - if (x & XING_FRAMES_FLAG) { - mp3->xing_header->frames = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_BYTES_FLAG) { - mp3->xing_header->bytes = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_TOC_FLAG) { - int j; - for (j = 0; j < 100; j++, p++) - mp3->xing_header->toc[j] = *p; - } - mp3->xing_header->vbr_scale = -1; - if (x & XING_VBR_SCALE_FLAG) { - mp3->xing_header->vbr_scale = almp3_get_big_endian(p); - p += 4; - } - - } - - /* calculate the number of total frames */ - if ((mp3->xing_header != NULL) && (mp3->xing_header->flags & XING_FRAMES_FLAG)) - mp3->total_frames = mp3->xing_header->frames; - else - mp3->total_frames = mp3->data_len / mp3->framebytes; - - /* deinit the test mpeg */ - ExitMP3(&test_mpeg); - - return mp3; -} - - -void almp3_destroy_mp3(ALMP3_MP3 *mp3) { - if (mp3 == NULL) - return; - - almp3_stop_mp3(mp3); /* note almp3_stop_mp3 will also remove */ - /* autopolling interrupts */ - ExitMP3(&(mp3->mpeg)); - if (mp3->xing_header) - free(mp3->xing_header); - free(mp3); -} - - -int almp3_play_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan) { - return almp3_play_ex_mp3(mp3, buffer_len, vol, pan, 1000, FALSE); -} - - -int almp3_play_ex_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan, int speed, int loop) { - int samples; - - /* continue only if we are not already playing it */ - if (almp3_is_playing_mp3(mp3)) - return ALMP3_OK; - - /* calculate the frames we can decode for each poll */ - /* using the given buffer_len */ - mp3->frames_per_poll = buffer_len / mp3->outbytes_per_frame; - if (mp3->frames_per_poll <= 0) - return ALMP3_PLAY_BUFFERTOOSMALL; - - /* create a new audiostream and play it */ - samples = (mp3->outbytes_per_frame * mp3->frames_per_poll) / (mp3->stereo ? 2 : 1) / (mp3->bits / 8); - mp3->audiostream = play_audio_stream(samples, mp3->bits, mp3->stereo, mp3->freq, vol, pan); - if (!mp3->audiostream) { - return ALMP3_POLL_INTERNALERROR; - } - - if (speed != 1000) - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); - - mp3->loop = loop; - mp3->wait_for_audio_stop = 0; - - /* if the user asked for autopolling, install the interrupt now */ - if (mp3->auto_polling) { - LOCK_FUNCTION(almp3_autopoll_mp3); - install_param_int(&almp3_autopoll_mp3, (void *)mp3, mp3->auto_poll_speed); - } - - return ALMP3_OK; -} - - -void almp3_stop_mp3(ALMP3_MP3 *mp3) { - /* continue if we are playing it */ - if (!almp3_is_playing_mp3(mp3)) - return; - - /* remove the interrupt, if we were using autopolling */ - if (mp3->auto_polling) - remove_param_int(&almp3_autopoll_mp3, (void *)mp3); - - /* stop the audio stream */ - stop_audio_stream(mp3->audiostream); - mp3->audiostream = NULL; -} - - -void almp3_rewind_mp3(ALMP3_MP3 *mp3) { - mp3->data_cursor = (char *)mp3->data; - mp3->current_frame = 0; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_abs_frames_mp3(ALMP3_MP3 *mp3, int frame) { - int bytes; - - /* check if the frame is valid */ - if ((frame < 0) || (frame >= mp3->total_frames)) - return; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3(mp3, frame); - - /* seems like we are using it */ - if (bytes >= 0) - mp3->data_cursor = (char *)mp3->data + bytes; - - /* no, use normal method */ - else - mp3->data_cursor = (char *)mp3->data + (frame * mp3->framebytes); - - mp3->current_frame = frame; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_abs_msecs_mp3(ALMP3_MP3 *mp3, int msec) { - int frame; - frame = msec / almp3_get_msecs_per_frame_mp3(mp3); - almp3_seek_abs_frames_mp3(mp3, frame); -} - - -void almp3_seek_abs_secs_mp3(ALMP3_MP3 *mp3, int sec) { - almp3_seek_abs_msecs_mp3(mp3, sec * 1000); -} - - -void almp3_seek_abs_bytes_mp3(ALMP3_MP3 *mp3, int bytes) { - /* check the pos in bytes is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((bytes < -mp3->data_start_skipped) || (bytes >= mp3->data_len)) - return; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (bytes < 0) - bytes = 0; - - /* set the cursor to the new position */ - mp3->data_cursor = (char *)mp3->data + bytes; - - mp3->current_frame = bytes / mp3->framebytes; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_rel_frames_mp3(ALMP3_MP3 *mp3, int frame) { - int bytes; - int wanted_frame = mp3->current_frame + frame; - - /* check the frame is valid */ - if ((wanted_frame < 0) || (wanted_frame >= mp3->total_frames)) - return; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3(mp3, wanted_frame); - - /* seems like we are using it */ - if (bytes >= 0) - mp3->data_cursor = (char *)mp3->data + bytes; - - /* no, use normal method */ - else - mp3->data_cursor += frame * mp3->framebytes; - - mp3->current_frame = wanted_frame; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_rel_msecs_mp3(ALMP3_MP3 *mp3, int msec) { - int frame; - frame = msec / almp3_get_msecs_per_frame_mp3(mp3); - almp3_seek_rel_frames_mp3(mp3, frame); -} - - -void almp3_seek_rel_secs_mp3(ALMP3_MP3 *mp3, int sec) { - almp3_seek_rel_msecs_mp3(mp3, sec * 1000); -} - - -void almp3_seek_rel_bytes_mp3(ALMP3_MP3 *mp3, int bytes) { - int current_byte = mp3->data_cursor - (char *)mp3->data; - int wanted_byte = current_byte + bytes; - - /* check the byte is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((wanted_byte < -mp3->data_start_skipped) || (wanted_byte >= mp3->data_len)) - return; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (wanted_byte < 0) - wanted_byte = 0; - - /* set the cursor to the new position */ - mp3->data_cursor = (char *)mp3->data + wanted_byte; - - mp3->current_frame = wanted_byte / mp3->framebytes; - mp3->dec_reinit = TRUE; -} - - -int almp3_poll_mp3(ALMP3_MP3 *mp3) { - void *audiobuf; - char *audiobuf_p; - int i, num_data_cursor, size_done; - - /* continue only if we are playing it */ - if (!almp3_is_playing_mp3(mp3)) - return ALMP3_POLL_NOTPLAYING; - - /* get the audio stream buffer and only continue if we need to fill it */ - audiobuf = get_audio_stream_buffer(mp3->audiostream); - if (audiobuf == NULL) - return ALMP3_OK; - - /* clear the buffer */ - memset(audiobuf, 0, mp3->outbytes_per_frame * mp3->frames_per_poll); - - /* if we need to fill it, but we were just waiting for it to finish */ - if (!mp3->loop) { - if (mp3->wait_for_audio_stop > 0) { - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - if (--mp3->wait_for_audio_stop == 0) { - /* stop it */ - almp3_stop_mp3(mp3); - return ALMP3_POLL_PLAYJUSTFINISHED; - } - else - return ALMP3_OK; - } - } - - /* reinitialize the decoder if needed */ - if (mp3->dec_reinit) { - mp3->wait_for_audio_stop = 0; - if (almp3_reinit_decoder_mp3(mp3) < 0) { - /* an error while reinitializing */ - almp3_stop_mp3(mp3); - almp3_rewind_mp3(mp3); - return ALMP3_POLL_INTERNALERROR; - } - } - - audiobuf_p = (char *)audiobuf; - size_done = 0; - for (i = 0; i < (mp3->outbytes_per_frame * mp3->frames_per_poll); i += size_done) { - int ret, inread; - /* if we have reached the end */ - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - if (num_data_cursor >= mp3->data_len) { - almp3_rewind_mp3(mp3); - if (!mp3->loop) { - /* we don't want clicks at the end, so we convert our empty buffer */ - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - mp3->dec_reinit = FALSE; - } - - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, audiobuf_p, &size_done, &inread); - - /* probably it needs more */ - if ((ret == -3) && mp3->loop) { - /* rewind and give it more */ - almp3_rewind_mp3(mp3); - mp3->dec_reinit = FALSE; - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, audiobuf_p, &size_done, &inread); - } - - /* check if the decoding was not successful */ - if (ret == 0) { - /* damn, seems like this frame is corrupt */ - /* check the next 16kb just to be sure */ - int j, got_error = TRUE, max, left; - max = 16 * 1024; - - left = mp3->data_len - num_data_cursor; - - if (!mp3->loop && (max > left)) - max = left; - - for (j = 0; (j < max) && (got_error); j++) { - - /* check if we have to check the start again */ - if (mp3->loop && (j == left)) { - almp3_rewind_mp3(mp3); - mp3->dec_reinit = FALSE; - } - - /* check the header */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(mp3->data_cursor)) == -1) { - /* try to decode it */ - almp3_reinit_decoder_mp3(mp3); - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, audiobuf_p, &size_done, &inread); - if (ret == -1) { - char *p = mp3->data_cursor + (mp3->mpeg).fr.framesize + 4; - if (p < ((char *)mp3->data + mp3->data_len)) { - /* check the next header too just to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) != 0) - got_error = FALSE; - } - else { - /* if we don't have enough data to check, assume it is */ - got_error = FALSE; - } - } - } - - if (got_error) - mp3->data_cursor++; - } - - /* if we were unlucky, this is probably corrupt */ - /* (don't take it so seriously if it is the last frame) <- thanks to Bruno Dupuis */ - if (got_error && ((mp3->data_len - num_data_cursor) > (mp3->mpeg).fr.framesize)) { - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - almp3_stop_mp3(mp3); - almp3_rewind_mp3(mp3); - return ALMP3_POLL_FRAMECORRUPT; - } - } - - audiobuf_p += size_done; - mp3->current_frame++; - mp3->data_cursor += inread; - } - - /* convert to allegro unsigned format */ - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - - /* lock the buffer */ - free_audio_stream_buffer(mp3->audiostream); - - /* if we have reached the end */ - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - if (num_data_cursor >= mp3->data_len) { - almp3_rewind_mp3(mp3); - if (!mp3->loop) - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - - return ALMP3_OK; -} - - -void almp3_start_autopoll_mp3(ALMP3_MP3 *mp3, int speed) { - /* return if we are already auto polling */ - if (mp3->auto_polling) - return; - - mp3->auto_polling = TRUE; - mp3->auto_poll_speed = speed; - - /* only install the interrupt if we are already playing */ - /* otherwise, play will do */ - if (almp3_is_playing_mp3(mp3)) { - LOCK_FUNCTION(almp3_autopoll_mp3); - install_param_int(&almp3_autopoll_mp3, (void *)mp3, mp3->auto_poll_speed); - } -} - - -void almp3_stop_autopoll_mp3(ALMP3_MP3 *mp3) { - /* return if we are already not auto polling */ - if (!mp3->auto_polling) - return; - - mp3->auto_polling = FALSE; - - /* only remove the interrupt if we were already playing */ - /* otherwise, stop will do*/ - if (almp3_is_playing_mp3(mp3)) - remove_param_int(&almp3_autopoll_mp3, (void *)mp3); -} - - -int almp3_get_pos_frames_mp3(ALMP3_MP3 *mp3) { - return mp3->current_frame; -} - - -int almp3_get_pos_msecs_mp3(ALMP3_MP3 *mp3) { - float second; - second = mp3->current_frame * mp3->outbytes_per_frame; - second /= (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - second /= (float)mp3->freq; - return (int)(1000 * second); -} - - -int almp3_get_pos_secs_mp3(ALMP3_MP3 *mp3) { - return (almp3_get_pos_msecs_mp3(mp3) / 1000); -} - - -int almp3_get_length_frames_mp3(ALMP3_MP3 *mp3) { - return mp3->total_frames; -} - - -int almp3_get_pos_bytes_mp3(ALMP3_MP3 *mp3) { - return (mp3->data_cursor - (char *)mp3->data) + mp3->data_start_skipped; -} - - -int almp3_get_length_msecs_mp3(ALMP3_MP3 *mp3) { - int msecs; - msecs = almp3_get_length_frames_mp3(mp3) * almp3_get_msecs_per_frame_mp3(mp3); - return msecs; -} - - -int almp3_get_length_secs_mp3(ALMP3_MP3 *mp3) { - return (almp3_get_length_msecs_mp3(mp3) / 1000); -} - - -int almp3_get_length_bytes_mp3(ALMP3_MP3 *mp3) { - return (mp3->data_len + mp3->data_start_skipped + mp3->data_end_skipped); -} - - -int almp3_get_msecs_per_frame_mp3(ALMP3_MP3 *mp3) { - int msecs; - msecs = (int)((double)mp3->outbytes_per_frame / (double)almp3_get_outbytes_per_sec_mp3(mp3) * (double)1000); - return msecs; -} - - -int almp3_get_bitrate_mp3(ALMP3_MP3 *mp3) { - return mp3->bitrate; -} - - -int almp3_get_layer_mp3(ALMP3_MP3 *mp3) { - return mp3->layer; -} - - -int almp3_get_wave_bits_mp3(ALMP3_MP3 *mp3) { - return mp3->bits; -} - - -int almp3_get_wave_is_stereo_mp3(ALMP3_MP3 *mp3) { - return mp3->stereo; -} - - -int almp3_get_wave_freq_mp3(ALMP3_MP3 *mp3) { - return mp3->freq; -} - - -SAMPLE *almp3_create_sample_from_mp3(ALMP3_MP3 *mp3) { - SAMPLE *sample; - char *data; - int num_data_cursor, sample_len, sample_len_bytes, size_done; - - /* first we need to calculate the len of the sample (in frames and bytes) */ - sample_len_bytes = almp3_get_length_frames_mp3(mp3) * mp3->outbytes_per_frame; - sample_len = (sample_len_bytes / (mp3->bits / 8)) / (mp3->stereo ? 2 : 1); - - /* create the sample */ - sample = create_sample(mp3->bits, mp3->stereo, mp3->freq, sample_len); - - /* return NULL if we were not able to allocate the memory for it */ - if (sample == NULL) - return NULL; - - /* we need to stop and rewind the mp3 */ - almp3_stop_mp3(mp3); - almp3_rewind_mp3(mp3); - - /* reinitialize the decoded if neecesary */ - if (mp3->dec_reinit) { - if (almp3_reinit_decoder_mp3(mp3) < 0) { - /* an error while reinitializing */ - return NULL; - } - } - - /* set our pointer */ - data = (char *)sample->data; - /* clear the sample buffer */ - memset(data, 0, sample_len_bytes); - - /* decode */ - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - size_done = 0; - while (num_data_cursor < mp3->data_len) { - int ret, inread; - - /* send bytes until it has enough to render a frame */ - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, data, &size_done, &inread); - - /* check if the decoding was not successful */ - if (ret == 0) { - /* damn, seems like this frame is corrupt */ - /* check the next 16kb just to be sure */ - int j, got_error = TRUE, max, left; - - max = 16 * 1024; - - left = mp3->data_len - num_data_cursor; - - if (max > left) - max = left; - - for (j = 0; (j < max) && got_error; j++) { - /* check the header */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(mp3->data_cursor)) == -1) { - /* try to decode it */ - almp3_reinit_decoder_mp3(mp3); - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, data, &size_done, &inread); - if (ret == -1) { - char *p = mp3->data_cursor + (mp3->mpeg).fr.framesize + 4; - if (p < ((char *)mp3->data + mp3->data_len)) { - /* check the next header too just to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) != 0) - got_error = FALSE; - } - else { - /* if we don't have enough data to check, assume it is */ - got_error = FALSE; - } - } - } - - if (got_error) - mp3->data_cursor++; - } - - /* if we were unlucky, this is probably corrupt */ - /* (don't take it so seriously if it is the last frame) <- thanks to Bruno Dupuis */ - if (got_error && ((mp3->data_len - num_data_cursor) > (mp3->mpeg).fr.framesize)) { - almp3_rewind_mp3(mp3); - destroy_sample(sample); - return NULL; - } - } - - data += size_done; - mp3->data_cursor += inread; - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - mp3->current_frame++; - } - - almp3_rewind_mp3(mp3); - - /* convert to allegro unsigned format */ - if (mp3->bits == 16) { - void *buf = sample->data; - unsigned int i, *j, k; - k = sample_len_bytes / 4; - for (i = 0, j = (unsigned int *)buf; i < k; i++, j++) - *j ^= 0x80008000; - } - - return sample; -} - - -void almp3_adjust_mp3(ALMP3_MP3 *mp3, int vol, int pan, int speed, int loop) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3(mp3)) - return; - - /* adjust the sample */ - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); - mp3->loop = loop; -} - - -void *almp3_get_output_wave_mp3(ALMP3_MP3 *mp3, int *buffer_size) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3(mp3)) - return NULL; - - /* set the buffer_size */ - *buffer_size = mp3->outbytes_per_frame * mp3->frames_per_poll; - - /* return the current audiostream sample data */ - return (mp3->audiostream->samp->data); -} - - -int almp3_is_playing_mp3(ALMP3_MP3 *mp3) { - if (mp3->audiostream == NULL) - return FALSE; - else - return TRUE; -} - - -int almp3_is_looping_mp3(ALMP3_MP3 *mp3) { - if (!almp3_is_playing_mp3(mp3)) - return FALSE; - return mp3->loop; -} - - -void almp3_set_loop_mp3(ALMP3_MP3 *mp3, int loop) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3(mp3)) - return; - - mp3->loop = loop; -} - - -AUDIOSTREAM *almp3_get_audiostream_mp3(ALMP3_MP3 *mp3) { - return mp3->audiostream; -} - - - - -/* API - MP3STREAM */ - -/* function called in an interrupt */ - -static void almp3_autopoll_mp3stream(void *mp3) { - almp3_poll_mp3stream((ALMP3_MP3STREAM *)mp3); -} -END_OF_FUNCTION(almp3_autopoll_mp3stream); - - -/* helper functions */ - -static int almp3_reinit_decoder_mp3stream(ALMP3_MP3STREAM *mp3) { - /* reinitialize the decoder */ - ExitMP3(&(mp3->mpeg)); - InitMP3(&(mp3->mpeg)); - - mp3->dec_reinit = FALSE; - - return 0; -} - - -static void almp3_convert_to_unsigned_format_mp3stream(ALMP3_MP3STREAM *mp3, void *buf) { - /* convert to allegro unsigned format */ - if (mp3->bits == 16) { - unsigned int i, *j, k; - k = (mp3->outbytes_per_frame * mp3->frames_per_poll) / 4; - for (i = 0, j = (unsigned int *)buf; i < k; i++, j++) - *j ^= 0x80008000; - } -} - - -static int almp3_get_bytes_at_frame_using_toc_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int data_len) { - int tof[100], i, flags; - int bytesmin, bytesmax, bytesdif, bytes; - int framemin, framemax, framedif; - - /* check for missing data */ - if (mp3->xing_header == NULL) - return -1; - flags = mp3->xing_header->flags; - if (!(flags & XING_FRAMES_FLAG) || !(flags & XING_TOC_FLAG)) - return -1; - if ((frame >= mp3->xing_header->frames) || (frame < 0)) - return -1; - - /* create a table of frames */ - for (i = 0; i < 100; i++) - tof[i] = (mp3->xing_header->toc[i] * mp3->xing_header->frames) / 256; - - /* check in what part of the table of frames is our frame */ - for (i = 0; i < 100; i++) { - if (frame <= tof[i]) - break; - } - - /* our frame is between the i% and (i + 1)% of the file */ - /* let's do more calcules for a "fine" seeking */ - if (i == 100) - return data_len; - bytesmin = (data_len * i) / 100; - framemin = tof[i]; - if (i < 99) { - bytesmax = (data_len * (i + 1)) / 100; - framemax = tof[i + 1]; - } - else { - bytesmax = data_len - 1; - framemax = mp3->xing_header->frames - 1; - } - bytesdif = bytesmax - bytesmin; - framedif = framemax - framemin; - - bytes = bytesmin + (((frame - framemin) * bytesdif) / framedif); - - return bytes; -} - - -static int almp3_get_outbytes_per_sec_mp3stream(ALMP3_MP3STREAM *mp3) { - int bytes_out; - bytes_out = (mp3->stereo ? 2 : 1) * (mp3->bits / 8) * mp3->freq; - return bytes_out; -} - - -static int almp3_decode_frame_mp3stream(ALMP3_MP3STREAM *mp3, char *inbuf, int inlen, char *outbuf, int *size_done, int *inread) { - /* send bytes until it has enough to render a frame */ - int ret; - *inread = 0; - ret = decodeMP3(&(mp3->mpeg), NULL, 0, outbuf, 8192, size_done); - if (ret == MP3_NEED_MORE) { - int chunk_size; - - if (mp3->xing_header) - chunk_size = MAXFRAMESIZE; - else - chunk_size = mp3->framebytes + 4; - - do { - if (inlen <= 0) - break; - - else if (inlen < chunk_size) { - ret = decodeMP3(&(mp3->mpeg), inbuf, inlen, outbuf, 8192, size_done); - inbuf += inlen; - *inread += inlen; - inlen = 0; - } - else { - ret = decodeMP3(&(mp3->mpeg), inbuf, chunk_size, outbuf, 8192, size_done); - inlen -= chunk_size; - inbuf += chunk_size; - *inread += chunk_size; - } - } while (ret == MP3_NEED_MORE); - } - - { - int val = almp3_check_frame_validity((mp3->mpeg).header); - if ((ret == MP3_ERR) || (val == 0) || ((mp3->mpeg).fr.framesize <= 0)) - return 0; - else - return -1; - } - -} - - - -/* API functions */ - -ALMP3_MP3STREAM *almp3_create_mp3stream(void *first_data_buffer, int data_buffer_len, int last_block) { - ALMP3_MP3STREAM *mp3; - struct mpstr test_mpeg; - unsigned char *p = (unsigned char *)first_data_buffer; - int skipbytes; - void *databuf1, *databuf2, *full_databuf; - int ret; - char test_outbuf[8192]; - int test_size, framebytes; - - /* test the first 16 * MAXFRAMESIZE bytes until we find one valid */ - { - int found, max; - if (data_buffer_len >= (16 * MAXFRAMESIZE)) - max = 16 * MAXFRAMESIZE; - else - max = data_buffer_len; - - found = FALSE; - skipbytes = 0; - while (!found && (skipbytes < max)) { - int data_left = max - skipbytes; - char *p = (char *)first_data_buffer + skipbytes; - - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) == -1) { - /* probably found, check */ - InitMP3(&test_mpeg); - ret = decodeMP3(&test_mpeg, p, data_left, test_outbuf, 8192, &test_size); - if ((ret == MP3_OK) && (test_mpeg.fr.framesize > 0)) { - char *p2 = p + test_mpeg.fr.framesize + 4; - if (p2 < ((char *)first_data_buffer + max)) { - /* check the next frame to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p2)) != 0) - found = TRUE; - } - else { - /* guess it is right */ - found = TRUE; - } - } - - if (!found) - ExitMP3(&test_mpeg); - } - - if (!found) - skipbytes++; - } - - if (!found) { - return NULL; - } - } - - /* must be layer III or II */ - if ((test_mpeg.fr.lay != 3) && (test_mpeg.fr.lay != 2)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* the mp3 is ok, get some info */ - framebytes = test_mpeg.fr.framesize + 4; - if ((framebytes <= 4)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* allocate the buffers */ - databuf1 = malloc(data_buffer_len); - if (databuf1 == NULL) { - ExitMP3(&test_mpeg); - return NULL; - } - databuf2 = malloc(data_buffer_len); - if (databuf2 == NULL) { - ExitMP3(&test_mpeg); - free(databuf1); - return NULL; - } - full_databuf = malloc(data_buffer_len * 2); - if (full_databuf == NULL) { - ExitMP3(&test_mpeg); - free(databuf1); - free(databuf2); - return NULL; - } - - /* copy the first data */ - memcpy(databuf1, first_data_buffer, data_buffer_len); - - /* create a new mp3 struct */ - mp3 = (ALMP3_MP3STREAM *)malloc(sizeof(ALMP3_MP3STREAM)); - if (mp3 == NULL) { - ExitMP3(&test_mpeg); - free(databuf1); - free(databuf2); - free(full_databuf); - return NULL; - } - - /* init the real decoder */ - InitMP3(&(mp3->mpeg)); - - /* fill in the mp3 struct */ - mp3->data_start_skipped = skipbytes; - mp3->databuf1 = databuf1; - mp3->databuf2 = databuf2; - mp3->full_databuf = (char *)full_databuf; - mp3->data_cursor = skipbytes; - mp3->databuf_selector = 1; - mp3->databuf_len = data_buffer_len; - mp3->unsel_databuf_free = TRUE; - if (last_block) - mp3->bytes_used = data_buffer_len; - else - mp3->bytes_used = -1; - - mp3->freq = almp3freqs[test_mpeg.fr.sampling_frequency]; - if (test_mpeg.fr.stereo >= 2) - mp3->stereo = TRUE; - else - mp3->stereo = FALSE; - mp3->bits = 16; - mp3->outbytes_per_frame = test_size; - mp3->audiostream = NULL; - mp3->current_frame = 0; - mp3->current_byte = skipbytes; - mp3->auto_polling = FALSE; - mp3->bitrate = almp3tabsel_123[test_mpeg.fr.lsf][test_mpeg.fr.lay - 1][test_mpeg.fr.bitrate_index] * 1000; - mp3->layer = test_mpeg.fr.lay; - if (mp3->layer <= 0) - mp3->layer = -1; - mp3->dec_reinit = FALSE; - mp3->framebytes = framebytes; - mp3->xing_header = NULL; - - /* if outbytes_per_frame is incorrect, correct it */ - if (mp3->outbytes_per_frame <= 0) { - int samples = 1152; - if (mp3->layer == 2) - samples = 1152; - if (mp3->layer == 3) { - if ((mp3->freq >= 32000) && (mp3->freq < 48000)) - samples = 1152; - else if ((mp3->freq >= 8000) && (mp3->freq < 24000)) - samples = 576; - } - mp3->outbytes_per_frame = samples * (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - } - - /* check for the xing header */ - p = (unsigned char *)((char *)first_data_buffer + skipbytes); - if (!test_mpeg.fr.lsf) { /* mpeg1 */ - if (test_mpeg.fr.mode != 3) - p += 32 + 4; - else - p += 17 + 4; - } - else { /* mpeg2 */ - if (test_mpeg.fr.mode != 3) - p += 17 + 4; - else - p += 9 + 4; - } - - if (memcmp(p, "Xing", 4) == 0) { - - /* found */ - int x; - p += 4; - mp3->xing_header = (XING_HEADER *)malloc(sizeof(XING_HEADER)); - x = mp3->xing_header->flags = almp3_get_big_endian(p); - p += 4; - if (x & XING_FRAMES_FLAG) { - mp3->xing_header->frames = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_BYTES_FLAG) { - mp3->xing_header->bytes = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_TOC_FLAG) { - int j; - for (j = 0; j < 100; j++, p++) - mp3->xing_header->toc[j] = *p; - } - mp3->xing_header->vbr_scale = -1; - if (x & XING_VBR_SCALE_FLAG) { - mp3->xing_header->vbr_scale = almp3_get_big_endian(p); - p += 4; - } - - } - - /* get the number of total frames if we are using a XING header*/ - if ((mp3->xing_header != NULL) && (mp3->xing_header->flags & XING_FRAMES_FLAG)) - mp3->total_frames = mp3->xing_header->frames; - /* else we don't know it */ - else - mp3->total_frames = -1; - - /* deinit the test decoder */ - ExitMP3(&test_mpeg); - - return mp3; -} - - -void almp3_destroy_mp3stream(ALMP3_MP3STREAM *mp3) { - if (mp3 == NULL) - return; - - almp3_stop_mp3stream(mp3); /* note almp3_stop_mp3stream will */ - /* remove autopolling interrupts */ - ExitMP3(&(mp3->mpeg)); - if (mp3->xing_header) - free(mp3->xing_header); - free(mp3->full_databuf); - free(mp3->databuf1); - free(mp3->databuf2); - free(mp3); -} - - -int almp3_play_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan) { - return almp3_play_ex_mp3stream(mp3, buffer_len, vol, pan, 1000); -} - - -int almp3_play_ex_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan, int speed) { - int samples; - - /* continue only if we are not already playing it */ - if (almp3_is_playing_mp3stream(mp3)) - return ALMP3_OK; - - /* calculate the frames we can decode for each poll */ - /* using the given buffer_len */ - mp3->frames_per_poll = buffer_len / mp3->outbytes_per_frame; - if (mp3->frames_per_poll <= 0) - return ALMP3_PLAY_BUFFERTOOSMALL; - - /* create a new audiostream and play it */ - samples = (mp3->outbytes_per_frame * mp3->frames_per_poll) / (mp3->stereo ? 2 : 1) / (mp3->bits / 8); - mp3->audiostream = play_audio_stream(samples, mp3->bits, mp3->stereo, mp3->freq, vol, pan); - if (!mp3->audiostream) { - return ALMP3_POLL_INTERNALERROR; - } - - mp3->wait_for_audio_stop = 0; - - if (speed != 1000) - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); - - /* if the user asked for autopolling, install the interrupt now */ - if (mp3->auto_polling) { - LOCK_FUNCTION(almp3_autopoll_mp3stream); - install_param_int(&almp3_autopoll_mp3stream, (void *)mp3, mp3->auto_poll_speed); - } - - return ALMP3_OK; -} - - -void almp3_stop_mp3stream(ALMP3_MP3STREAM *mp3) { - /* continue if we are playing it */ - if (!almp3_is_playing_mp3stream(mp3)) - return; - - /* remove the interrupt, if we were using autopolling */ - if (mp3->auto_polling) - remove_param_int(&almp3_autopoll_mp3stream, (void *)mp3); - - /* stop the audio stream */ - stop_audio_stream(mp3->audiostream); - mp3->audiostream = NULL; -} - - -int almp3_poll_mp3stream(ALMP3_MP3STREAM *mp3) { - void *audiobuf; - char *audiobuf_p; - char *temp_databuf; - int temp_buf_size, using_full_databuf; - int i, size_done; - int last_block; - - /* continue only if we are playing it */ - if (!almp3_is_playing_mp3stream(mp3)) - return ALMP3_POLL_NOTPLAYING; - - /* get the audio stream buffer and only continue if we need to fill it */ - audiobuf = get_audio_stream_buffer(mp3->audiostream); - if (audiobuf == NULL) - return ALMP3_OK; - - /* clear the buffer */ - memset(audiobuf, 0, mp3->outbytes_per_frame * mp3->frames_per_poll); - - /* if we need to fill it, but we were just waiting for it to finish */ - if (mp3->wait_for_audio_stop > 0) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - if (--mp3->wait_for_audio_stop == 0) { - /* stop it */ - almp3_stop_mp3stream(mp3); - return ALMP3_POLL_PLAYJUSTFINISHED; - } - else - return ALMP3_OK; - } - - /* get if this will be the last block to be processed */ - if (mp3->bytes_used != -1) - last_block = TRUE; - else - last_block = FALSE; - - /* if the 2 buffers are available, use the concatenated one */ - if (!mp3->unsel_databuf_free) { - temp_databuf = mp3->full_databuf; - using_full_databuf = TRUE; - if (!last_block) - temp_buf_size = mp3->databuf_len * 2; - else - temp_buf_size = mp3->databuf_len + mp3->bytes_used; - } - /* else just point to the current buffer */ - else { - using_full_databuf = FALSE; - if (mp3->databuf_selector == 1) - temp_databuf = (char *)mp3->databuf1; - else - temp_databuf = (char *)mp3->databuf2; - if (!last_block) - temp_buf_size = mp3->databuf_len; - else - temp_buf_size = mp3->bytes_used; - } - - /* reinitialize the decoder if needed */ - if (mp3->dec_reinit) { - mp3->wait_for_audio_stop = 0; - if (almp3_reinit_decoder_mp3stream(mp3) < 0) { - /* an error while reinitializing */ - almp3_stop_mp3stream(mp3); - return ALMP3_POLL_INTERNALERROR; - } - } - - audiobuf_p = (char *)audiobuf; - size_done = 0; - for (i = 0; i < (mp3->outbytes_per_frame * mp3->frames_per_poll); i += size_done) { - int ret, temp_buf_left, inread; - - /* check for a ID1 tag - note we do this here cause ID1 tags */ - /* go at the end of file and we have no way to know where is the end */ - if (memcmp(temp_databuf + mp3->data_cursor, "TAG", 3) == 0) { - mp3->data_cursor += 128; - mp3->current_byte += 128; - almp3_reinit_decoder_mp3stream(mp3); - } - - /* check for buffer underrun or end of the mp3 */ - temp_buf_left = temp_buf_size - mp3->data_cursor; - if (temp_buf_left <= 0) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALMP3_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - } - - ret = almp3_decode_frame_mp3stream(mp3, (char *)temp_databuf + mp3->data_cursor, temp_buf_left, audiobuf_p, &size_done, &inread); - - /* check if the decoding was not successful */ - if (ret == 0) { - /* damn, seems like this frame is corrupt */ - /* check the next 16kb just to be sure */ - int j, max, got_error = TRUE, left; - - max = 16 * 1024; - - left = temp_buf_left; - - if (max > left) - max = left; - - - for (j = 0; (j < max) && (got_error); j++) { - char *p; - - /* check for buffer underrun or end of the mp3 */ - if (mp3->data_cursor >= temp_buf_size) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALMP3_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - } - - /* check the header */ - p = (char *)temp_databuf + mp3->data_cursor; - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) == -1) { - /* try to decode it */ - almp3_reinit_decoder_mp3stream(mp3); - ret = almp3_decode_frame_mp3stream(mp3, p, temp_buf_left, audiobuf_p, &size_done, &inread); - if (ret == -1) { - char *p = (char *)temp_databuf + mp3->data_cursor + (mp3->mpeg).fr.framesize + 4; - if (p < ((char *)temp_databuf + temp_buf_size)) { - /* check the next header too just to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) != 0) - got_error = FALSE; - } - else { - /* if we don't have enough data to check, assume it is */ - got_error = FALSE; - } - } - } - - if (got_error) { - mp3->data_cursor++; - mp3->current_byte++; - temp_buf_left--; - } - - } - /* if we are still unlucky, this is probably corrupt */ - if (got_error) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - almp3_stop_mp3stream(mp3); - return ALMP3_POLL_FRAMECORRUPT; - } - } - - mp3->data_cursor += inread; - mp3->current_byte += inread; - audiobuf_p += size_done; - mp3->current_frame++; - } - - /* convert to allegro unsigned format */ - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - - /* lock the buffer */ - free_audio_stream_buffer(mp3->audiostream); - - /* if we were using the full_databuf */ - if (using_full_databuf) { - /* if the cursor passed the first buffer len */ - if (mp3->data_cursor >= mp3->databuf_len) { - /* set the cursor to a good position and mark as free the old buffer */ - mp3->data_cursor -= mp3->databuf_len; - mp3->databuf_selector = -mp3->databuf_selector; - mp3->unsel_databuf_free = TRUE; - } - } - /* using only one buffer */ - else { - if (mp3->data_cursor >= mp3->databuf_len) { - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALMP3_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - } - } - - return ALMP3_OK; -} - - -void almp3_start_autopoll_mp3stream(ALMP3_MP3STREAM *mp3, int speed) { - /* return if we are already auto polling */ - if (mp3->auto_polling) - return; - - mp3->auto_polling = TRUE; - mp3->auto_poll_speed = speed; - - /* only install the interrupt if we are already playing */ - /* otherwise, play will do */ - if (almp3_is_playing_mp3stream(mp3)) { - LOCK_FUNCTION(almp3_autopoll_mp3stream); - install_param_int(&almp3_autopoll_mp3stream, (void *)mp3, mp3->auto_poll_speed); - } -} - - -void almp3_stop_autopoll_mp3stream(ALMP3_MP3STREAM *mp3) { - /* return if we are already not auto polling */ - if (!mp3->auto_polling) - return; - - mp3->auto_polling = FALSE; - - /* only remove the interrupt if we were already playing */ - /* otherwise, stop will do*/ - if (almp3_is_playing_mp3stream(mp3)) - remove_param_int(&almp3_autopoll_mp3stream, (void *)mp3); -} - - -void *almp3_get_mp3stream_buffer(ALMP3_MP3STREAM *mp3) { - if (!mp3->unsel_databuf_free) - return NULL; - - /* if the last block was already passed, we don't need more data */ - if (mp3->bytes_used != -1) - return NULL; - - if (mp3->databuf_selector == 1) - return mp3->databuf2; - else - return mp3->databuf1; -} - - -void almp3_free_mp3stream_buffer(ALMP3_MP3STREAM *mp3, int bytes_used) { - if (mp3->unsel_databuf_free) { - mp3->unsel_databuf_free = FALSE; - mp3->bytes_used = bytes_used; - if (mp3->databuf_selector == 1) { - memcpy(mp3->full_databuf, mp3->databuf1, mp3->databuf_len); - memcpy(mp3->full_databuf + mp3->databuf_len, mp3->databuf2, mp3->databuf_len); - } - else { - memcpy(mp3->full_databuf, mp3->databuf2, mp3->databuf_len); - memcpy(mp3->full_databuf + mp3->databuf_len, mp3->databuf1, mp3->databuf_len); - } - } -} - - -int almp3_get_pos_frames_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->current_frame; -} - - -int almp3_get_pos_msecs_mp3stream(ALMP3_MP3STREAM *mp3) { - float second; - second = mp3->current_frame * mp3->outbytes_per_frame; - second /= (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - second /= (float)mp3->freq; - return (int)(1000 * second); -} - - -int almp3_get_pos_secs_mp3stream(ALMP3_MP3STREAM *mp3) { - return (almp3_get_pos_msecs_mp3stream(mp3) / 1000); -} - - -int almp3_get_pos_bytes_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->current_byte; -} - - -int almp3_get_msecs_per_frame_mp3stream(ALMP3_MP3STREAM *mp3) { - int msecs; - msecs = (int)((double)mp3->outbytes_per_frame / (double)almp3_get_outbytes_per_sec_mp3stream(mp3) * (double)1000); - return msecs; -} - - -int almp3_get_bitrate_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->bitrate; -} - - -int almp3_get_layer_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->layer; -} - - -int almp3_get_wave_bits_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->bits; -} - - -int almp3_get_wave_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->stereo; -} - - -int almp3_get_wave_freq_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->freq; -} - - -void almp3_adjust_mp3stream(ALMP3_MP3STREAM *mp3, int vol, int pan, int speed) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3stream(mp3)) - return; - - /* adjust the sample */ - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); -} - - -void *almp3_get_output_wave_mp3stream(ALMP3_MP3STREAM *mp3, int *buffer_size) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3stream(mp3)) - return NULL; - - /* set the buffer_size */ - *buffer_size = mp3->outbytes_per_frame * mp3->frames_per_poll; - - /* return the current audiostream sample data */ - return (mp3->audiostream->samp->data); -} - - -int almp3_get_length_frames_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - /* if we have the frames from the XING header, use it */ - if (mp3->total_frames != -1) - return mp3->total_frames; - else - return (total_size / mp3->framebytes); -} - - -int almp3_get_length_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - int msecs; - msecs = almp3_get_length_frames_mp3stream(mp3, total_size) * almp3_get_msecs_per_frame_mp3stream(mp3); - return msecs; -} - - -int almp3_get_length_secs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - return (almp3_get_length_msecs_mp3stream(mp3, total_size) / 1000); -} - - -int almp3_get_length_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - return total_size; -} - - -int almp3_is_playing_mp3stream(ALMP3_MP3STREAM *mp3) { - if (mp3->audiostream == NULL) - return FALSE; - else - return TRUE; -} - - -AUDIOSTREAM *almp3_get_audiostream_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->audiostream; -} - - -int almp3_seek_abs_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size) { - int bytes; - int total_frames; - - /* get the number of total frames */ - total_frames = almp3_get_length_frames_mp3stream(mp3, total_size); - - /* check if the frame is valid */ - if ((frame < 0) || (frame >= total_frames)) - return -1; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3stream(mp3, frame, total_size); - - /* seems like we are using it */ - if (bytes >= 0) - return bytes; - - /* no, use normal method */ - else - return (frame * mp3->framebytes); -} - - -int almp3_seek_abs_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msecs, int total_size) { - int frame; - frame = msecs / almp3_get_msecs_per_frame_mp3stream(mp3); - return almp3_seek_abs_frames_mp3stream(mp3, frame, total_size); -} - - -int almp3_seek_abs_secs_mp3stream(ALMP3_MP3STREAM *mp3, int secs, int total_size){ - return almp3_seek_abs_msecs_mp3stream(mp3, secs * 1000, total_size); -} - - -int almp3_seek_abs_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size) { - /* check the pos in bytes is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((bytes < -mp3->data_start_skipped) || (bytes >= total_size)) - return -1; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (bytes < 0) - bytes = 0; - - return bytes; -} - - -int almp3_seek_rel_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size) { - int bytes; - int wanted_frame = mp3->current_frame + frame; - int total_frames; - - /* get total frames */ - total_frames = almp3_get_length_frames_mp3stream(mp3, total_size); - - /* check the frame is valid */ - if ((wanted_frame < 0) || (wanted_frame >= total_frames)) - return -1; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3stream(mp3, wanted_frame, total_size); - - /* seems like we are using it */ - if (bytes >= 0) - return bytes; - - /* no, use normal method */ - else - return (frame * mp3->framebytes); -} - - -int almp3_seek_rel_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msec, int total_size) { - int frame; - frame = msec / almp3_get_msecs_per_frame_mp3stream(mp3); - return almp3_seek_rel_frames_mp3stream(mp3, frame, total_size); -} - - -int almp3_seek_rel_secs_mp3stream(ALMP3_MP3STREAM *mp3, int sec, int total_size) { - return almp3_seek_rel_msecs_mp3stream(mp3, sec * 1000, total_size); -} - - -int almp3_seek_rel_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size) { - int current_byte = almp3_get_pos_bytes_mp3stream(mp3); - int wanted_byte = current_byte + bytes; - - /* check the byte is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((wanted_byte < -mp3->data_start_skipped) || (wanted_byte >= total_size)) - return -1; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (wanted_byte < 0) - wanted_byte = 0; - - return wanted_byte; -} diff --git a/Engine/libsrc/almp3/almp3.c b/Engine/libsrc/almp3/almp3.c deleted file mode 100644 index 34d3d59024c..00000000000 --- a/Engine/libsrc/almp3/almp3.c +++ /dev/null @@ -1,2025 +0,0 @@ -/* Allegro MP3 - a wrapper for mpglib from mpg123 */ -/* to play MP3 files with Allegro */ - -/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ -/* Allegro MP3 is copyright (c) 2001, 2002 Javier Gonz lez */ - -/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ - - -#include -#include -#include -#include "libsrc/almp3-2.0.5/decoder/mpg123.h" -#include "libsrc/almp3-2.0.5/decoder/mpglib.h" - - -/* structures */ - -/* struct typically used in VBR (Variable Bitrate) MP3s */ - -#define XING_FRAMES_FLAG 1 -#define XING_BYTES_FLAG 2 -#define XING_TOC_FLAG 4 -#define XING_VBR_SCALE_FLAG 8 - -typedef struct XING_HEADER { - int flags; - int frames; /* number of frames the MP3 has */ - int bytes; /* number of bytes the file has */ - int vbr_scale; /* encoded vbr scale */ - unsigned char toc[100]; /* used for seeking */ -} XING_HEADER; - - -/* standard ALMP3_MP3 structure */ - -struct ALMP3_MP3 { - /* data info */ - void *data; /* mp3 data */ - char *data_cursor; /* pointer to data being read */ - int data_len; /* size of the data */ - int data_start_skipped; /* used when ID3v2 headers are present */ - /* and we are asked to seek or get the */ - /* pos in bytes */ - int data_end_skipped; /* used when ID3v1 headers are present */ - /* and we are asked to seek or get the */ - /* pos in bytes */ - /* decoder info */ - struct mpstr mpeg; /* decoder handler */ - XING_HEADER *xing_header; /* xing header if available */ - int dec_reinit; /* true if the decoder needs to be */ - /* reinitialized in next poll */ - /* mp3 info */ - int outbytes_per_frame; /* bytes created per frame */ - int framebytes; /* decoder first framebytes */ - int bitrate, layer; /* mp3 general info */ - int total_frames; /* number of frames the mp3 has */ - int current_frame; /* frame currently being played */ - /* playing info */ - AUDIOSTREAM *audiostream; /* the audiostream we are using to play */ - /* also used to know when it's playing */ - int freq, stereo, bits, loop; /* audio general info */ - int frames_per_poll; /* number of frames per play poll */ - int auto_polling; /* set if the mp3 is auto polling */ - int auto_poll_speed; /* auto poll speed in msecs */ - int wait_for_audio_stop; /* set if we are just waiting for the - audiobuffer to stop plaing the last - frame */ -}; - - -/* standard ALMP3_MP3STREAM structure */ - -struct ALMP3_MP3STREAM { - /* data info */ - void *databuf1, *databuf2; /* data buffers */ - char *full_databuf; /* to be used when the 2 buffers are filled */ - int data_cursor; /* pointer to data being read */ - int databuf_selector; /* 1 = databuf1, -1 = databuf2 */ - int databuf_len; /* size of the data buffer */ - int unsel_databuf_free; /* TRUE when the unselected databuffer */ - /* is free and needs to be filled */ - int bytes_used; /* number of bytes to use from the buffer */ - /* or -1 if the full buffer */ - int data_start_skipped; /* used when ID3v2 headers are present */ - /* and we are asked to seek or get the */ - /* pos in bytes */ - /* decoder info */ - struct mpstr mpeg; /* decoder handler */ - XING_HEADER *xing_header; /* xing header if available */ - int dec_reinit; /* true if the decoder needs to be */ - /* reinitialized in next poll */ - /* mp3 info */ - int outbytes_per_frame; /* bytes created per frame */ - int framebytes; /* decoder first framebytes */ - int bitrate, layer; /* mp3 general info */ - int current_frame; /* frame currently being played */ - int current_byte; /* byte currently being decoded */ - int total_frames; /* number of frames the mp3 has */ - /* playing info */ - AUDIOSTREAM *audiostream; /* the audiostream we are using to play */ - /* also used to know when it's playing */ - int freq, stereo, bits; /* audio general info */ - int frames_per_poll; /* number of frames per play poll */ - int auto_polling; /* set if the mp3 is auto polling */ - int auto_poll_speed; /* auto poll speed in msecs */ - int wait_for_audio_stop; /* set if we are just waiting for the - audiobuffer to stop plaing the last - frame */ -}; - - -/* common functions */ - - -static int almp3_check_frame_validity(unsigned int header) { - /* return 0 if invalid, -1 if valid */ - - /* test sync */ - if ((header & 0xFFE00000) != 0xFFE00000) - return 0; - - /* mpeg version */ - if ((header & 0x180000) == 0x80000) - return 0; - - /* mpeg layer */ - if (((header & 0x60000) != 0x20000) && ((header & 0x60000) != 0x10000)) - return 0; - - /* bitrate */ - if (((header & 0xF000) == 0xF000) || ((header & 0xF000) == 0x0000)) - return 0; - - /* freq */ - if ((header & 0xC00) == 0xC00) - return 0; - - /* emphasis */ -/*if ((header & 0x3) == 0x2) - return 0;*/ - - return -1; -} - - -static int almp3_get_big_endian(unsigned char *p) { - int x; - x = *p; x <<= 8; - x |= *(p + 1); x <<= 8; - x |= *(p + 2); x <<= 8; - x |= *(p + 3); - return x; -} - - -static int almp3_get_id3v2_skip_bytes(unsigned char *p) { - int id3v2_skip_size = 0; - /* test for ID3v2 and if exists, skip it */ - if (memcmp((unsigned char *)p, "ID3", 3) == 0) { - int footer_present = p[5] & 0x10; - p += 6; - id3v2_skip_size = *(p + 3) | (*(p + 2) << 7) | (*(p + 1) << 14) | (*p << 21); - if (footer_present) - id3v2_skip_size += 20; - else - id3v2_skip_size += 10; - } - else - id3v2_skip_size = 0; - - return id3v2_skip_size; -} - - - -/* API - MP3 */ - -/* function called in an interrupt */ - -static void almp3_autopoll_mp3(void *mp3) { - almp3_poll_mp3((ALMP3_MP3 *)mp3); -} -END_OF_FUNCTION(almp3_autopoll_mp3); - - -/* helper functions */ - -static int almp3_reinit_decoder_mp3(ALMP3_MP3 *mp3) { - /* reinitialize the decoder */ - ExitMP3(&(mp3->mpeg)); - InitMP3(&(mp3->mpeg)); - mp3->dec_reinit = FALSE; - - return 0; -} - - -static void almp3_convert_to_unsigned_format_mp3(ALMP3_MP3 *mp3, void *buf) { - /* convert to allegro unsigned format */ - if (mp3->bits == 16) { - unsigned int i, *j, k; - k = (mp3->outbytes_per_frame * mp3->frames_per_poll) / 4; - for (i = 0, j = (unsigned int *)buf; i < k; i++, j++) - *j ^= 0x80008000; - } -} - - -static int almp3_get_bytes_at_frame_using_toc_mp3(ALMP3_MP3 *mp3, int frame) { - int tof[100], i, flags; - int bytesmin, bytesmax, bytesdif, bytes; - int framemin, framemax, framedif; - - /* check for missing data */ - if (mp3->xing_header == NULL) - return -1; - flags = mp3->xing_header->flags; - if (!(flags & XING_FRAMES_FLAG) || !(flags & XING_TOC_FLAG)) - return -1; - if ((frame >= mp3->xing_header->frames) || (frame < 0)) - return -1; - - /* create a table of frames */ - for (i = 0; i < 100; i++) - tof[i] = (mp3->xing_header->toc[i] * mp3->xing_header->frames) / 256; - - /* check in what part of the table of frames is our frame */ - for (i = 0; i < 100; i++) { - if (frame <= tof[i]) - break; - } - - /* our frame is between the i% and (i + 1)% of the file */ - /* let's do more calcules for a "fine" seeking */ - if (i == 100) - return mp3->data_len; - bytesmin = (mp3->data_len * i) / 100; - framemin = tof[i]; - if (i < 99) { - bytesmax = (mp3->data_len * (i + 1)) / 100; - framemax = tof[i + 1]; - } - else { - bytesmax = mp3->data_len - 1; - framemax = mp3->xing_header->frames - 1; - } - bytesdif = bytesmax - bytesmin; - framedif = framemax - framemin; - - bytes = bytesmin; - if (framedif) - bytes += (((frame - framemin) * bytesdif) / framedif); - - return bytes; -} - - -static int almp3_get_outbytes_per_sec_mp3(ALMP3_MP3 *mp3) { - int bytes_out; - bytes_out = (mp3->stereo ? 2 : 1) * (mp3->bits / 8) * mp3->freq; - return bytes_out; -} - - -static int almp3_decode_frame_mp3(ALMP3_MP3 *mp3, char *inbuf, char *outbuf, int *size_done, int *inread) { - /* send bytes until it has enough to render a frame */ - int ret; - *inread = 0; - - ret = decodeMP3(&(mp3->mpeg), NULL, 0, outbuf, 8192, size_done); - if (ret == MP3_NEED_MORE) { - int chunk_size, data_left; - - if (mp3->xing_header) - chunk_size = MAXFRAMESIZE; - else - chunk_size = mp3->framebytes + 4; - - data_left = mp3->data_len - ((char *)mp3->data_cursor - (char *)mp3->data); - do { - if (data_left <= 0) - break; - - if (data_left < chunk_size) { - ret = decodeMP3(&(mp3->mpeg), inbuf, data_left, outbuf, 8192, size_done); - inbuf += data_left; - *inread += data_left; - data_left = 0; - } - else { - ret = decodeMP3(&(mp3->mpeg), inbuf, chunk_size, outbuf, 8192, size_done); - data_left -= chunk_size; - inbuf += chunk_size; - *inread += chunk_size; - } - } while (ret == MP3_NEED_MORE); - } - - { - int val = almp3_check_frame_validity((mp3->mpeg).header); - - if (ret == MP3_NEED_MORE) - return -3; - - if ((ret == MP3_ERR) || (val == 0) || ((mp3->mpeg).fr.framesize <= 0)) - return 0; - else - return -1; - } -} - - -/* API functions */ - -ALMP3_MP3 *almp3_create_mp3(void *data_, int data_len) { - char *data=(char*)data_; - ALMP3_MP3 *mp3; - struct mpstr test_mpeg; - unsigned char *p = (unsigned char *)data; - int data_end_skipped, data_start_skipped; - int ret; - char test_outbuf[8192]; - int test_size, framebytes; - - /* test for ID3v1 and if exists, skip it */ - if (memcmp((void *)&p[data_len - 128], "TAG", 3) == 0) { - data_len -= 128; - data_end_skipped = 128; - } - else - data_end_skipped = 0; - - /* test for ID3v2 and if exists, skip it */ - data_start_skipped = almp3_get_id3v2_skip_bytes(p); - data += data_start_skipped; - data_len -= data_start_skipped; - - /* test the next 16 * MAXFRAMESIZE bytes after ID3v2 until we find one valid frame */ - { - int found, max, skipbytes; - if (data_len >= (16 * MAXFRAMESIZE)) - max = 16 * MAXFRAMESIZE; - else - max = data_len; - - found = FALSE; - skipbytes = 0; - while (!found && (skipbytes < max)) { - int data_left = max - skipbytes; - char *p = (char *)data + skipbytes; - - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) == -1) { - /* probably found, check */ - InitMP3(&test_mpeg); - ret = decodeMP3(&test_mpeg, p, data_left, test_outbuf, 8192, &test_size); - if ((ret == MP3_OK) && (test_mpeg.fr.framesize > 0)) { - char *p2 = p + test_mpeg.fr.framesize + 4; - if (p2 < ((char *)data + max)) { - /* check the next frame to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p2)) != 0) - found = TRUE; - } - else { - /* guess it is right */ - found = TRUE; - } - } - - if (!found) - ExitMP3(&test_mpeg); - } - - if (!found) - skipbytes++; - } - - if (!found) { - return NULL; - } - - data_start_skipped += skipbytes; - data_len -= skipbytes; - data += skipbytes; - } - - /* must be layer III or II */ - if ((test_mpeg.fr.lay != 3) && (test_mpeg.fr.lay != 2)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* the mp3 is ok, get some info */ - framebytes = test_mpeg.fr.framesize + 4; - if ((framebytes <= 4)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* create a new mp3 struct and init the real decoder */ - mp3 = (ALMP3_MP3 *)malloc(sizeof(ALMP3_MP3)); - if (mp3 == NULL) { - ExitMP3(&test_mpeg); - return NULL; - } - InitMP3(&(mp3->mpeg)); - - - /* fill in the mp3 struct */ - mp3->data_start_skipped = data_start_skipped; - mp3->data_end_skipped = data_end_skipped; - mp3->freq = almp3freqs[test_mpeg.fr.sampling_frequency]; - if (test_mpeg.fr.stereo >= 2) - mp3->stereo = TRUE; - else - mp3->stereo = FALSE; - mp3->bits = 16; - mp3->outbytes_per_frame = test_size; - mp3->audiostream = NULL; - mp3->data = data; - mp3->data_cursor = (char *)data; - mp3->data_len = data_len; - mp3->current_frame = 0; - mp3->auto_polling = FALSE; - mp3->dec_reinit = FALSE; - mp3->bitrate = almp3tabsel_123[test_mpeg.fr.lsf][test_mpeg.fr.lay - 1][test_mpeg.fr.bitrate_index] * 1000; - mp3->layer = test_mpeg.fr.lay; - if (mp3->layer <= 0) - mp3->layer = -1; - mp3->xing_header = NULL; - mp3->framebytes = framebytes; - - /* if outbytes_per_frame is incorrect, correct it */ - if (mp3->outbytes_per_frame <= 0) { - int samples = 1152; - if (mp3->layer == 2) - samples = 1152; - if (mp3->layer == 3) { - if ((mp3->freq >= 32000) && (mp3->freq < 48000)) - samples = 1152; - else if ((mp3->freq >= 8000) && (mp3->freq < 24000)) - samples = 576; - } - mp3->outbytes_per_frame = samples * (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - } - - /* check for the xing header */ - p = (unsigned char *)data; - if (!test_mpeg.fr.lsf) { /* mpeg1 */ - if (test_mpeg.fr.mode != 3) - p += 32 + 4; - else - p += 17 + 4; - } - else { /* mpeg2 */ - if (test_mpeg.fr.mode != 3) - p += 17 + 4; - else - p += 9 + 4; - } - - if (memcmp(p, "Xing", 4) == 0) { - - /* found */ - int x; - p += 4; - mp3->xing_header = (XING_HEADER *)malloc(sizeof(XING_HEADER)); - x = mp3->xing_header->flags = almp3_get_big_endian(p); - p += 4; - if (x & XING_FRAMES_FLAG) { - mp3->xing_header->frames = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_BYTES_FLAG) { - mp3->xing_header->bytes = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_TOC_FLAG) { - int j; - for (j = 0; j < 100; j++, p++) - mp3->xing_header->toc[j] = *p; - } - mp3->xing_header->vbr_scale = -1; - if (x & XING_VBR_SCALE_FLAG) { - mp3->xing_header->vbr_scale = almp3_get_big_endian(p); - p += 4; - } - - } - - /* calculate the number of total frames */ - if ((mp3->xing_header != NULL) && (mp3->xing_header->flags & XING_FRAMES_FLAG)) - mp3->total_frames = mp3->xing_header->frames; - else - mp3->total_frames = mp3->data_len / mp3->framebytes; - - /* deinit the test mpeg */ - ExitMP3(&test_mpeg); - - return mp3; -} - - -void almp3_destroy_mp3(ALMP3_MP3 *mp3) { - if (mp3 == NULL) - return; - - almp3_stop_mp3(mp3); /* note almp3_stop_mp3 will also remove */ - /* autopolling interrupts */ - ExitMP3(&(mp3->mpeg)); - if (mp3->xing_header) - free(mp3->xing_header); - free(mp3); -} - - -int almp3_play_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan) { - return almp3_play_ex_mp3(mp3, buffer_len, vol, pan, 1000, FALSE); -} - - -int almp3_play_ex_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan, int speed, int loop) { - int samples; - - /* continue only if we are not already playing it */ - if (almp3_is_playing_mp3(mp3)) - return ALMP3_OK; - - /* calculate the frames we can decode for each poll */ - /* using the given buffer_len */ - mp3->frames_per_poll = buffer_len / mp3->outbytes_per_frame; - if (mp3->frames_per_poll <= 0) - return ALMP3_PLAY_BUFFERTOOSMALL; - - /* create a new audiostream and play it */ - samples = (mp3->outbytes_per_frame * mp3->frames_per_poll) / (mp3->stereo ? 2 : 1) / (mp3->bits / 8); - mp3->audiostream = play_audio_stream(samples, mp3->bits, mp3->stereo, mp3->freq, vol, pan); - if (!mp3->audiostream) { - return ALMP3_POLL_INTERNALERROR; - } - - if (speed != 1000) - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); - - mp3->loop = loop; - mp3->wait_for_audio_stop = 0; - - /* if the user asked for autopolling, install the interrupt now */ - if (mp3->auto_polling) { - LOCK_FUNCTION(almp3_autopoll_mp3); - install_param_int(&almp3_autopoll_mp3, (void *)mp3, mp3->auto_poll_speed); - } - - return ALMP3_OK; -} - - -void almp3_stop_mp3(ALMP3_MP3 *mp3) { - /* continue if we are playing it */ - if (!almp3_is_playing_mp3(mp3)) - return; - - /* remove the interrupt, if we were using autopolling */ - if (mp3->auto_polling) - remove_param_int(&almp3_autopoll_mp3, (void *)mp3); - - /* stop the audio stream */ - stop_audio_stream(mp3->audiostream); - mp3->audiostream = NULL; -} - - -void almp3_rewind_mp3(ALMP3_MP3 *mp3) { - mp3->data_cursor = (char *)mp3->data; - mp3->current_frame = 0; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_abs_frames_mp3(ALMP3_MP3 *mp3, int frame) { - int bytes; - - /* check if the frame is valid */ - if ((frame < 0) || (frame >= mp3->total_frames)) - return; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3(mp3, frame); - - /* seems like we are using it */ - if (bytes >= 0) - mp3->data_cursor = (char *)mp3->data + bytes; - - /* no, use normal method */ - else - mp3->data_cursor = (char *)mp3->data + (frame * mp3->framebytes); - - mp3->current_frame = frame; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_abs_msecs_mp3(ALMP3_MP3 *mp3, int msec) { - int frame; - frame = msec / almp3_get_msecs_per_frame_mp3(mp3); - almp3_seek_abs_frames_mp3(mp3, frame); -} - - -void almp3_seek_abs_secs_mp3(ALMP3_MP3 *mp3, int sec) { - almp3_seek_abs_msecs_mp3(mp3, sec * 1000); -} - - -void almp3_seek_abs_bytes_mp3(ALMP3_MP3 *mp3, int bytes) { - /* check the pos in bytes is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((bytes < -mp3->data_start_skipped) || (bytes >= mp3->data_len)) - return; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (bytes < 0) - bytes = 0; - - /* set the cursor to the new position */ - mp3->data_cursor = (char *)mp3->data + bytes; - - mp3->current_frame = bytes / mp3->framebytes; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_rel_frames_mp3(ALMP3_MP3 *mp3, int frame) { - int bytes; - int wanted_frame = mp3->current_frame + frame; - - /* check the frame is valid */ - if ((wanted_frame < 0) || (wanted_frame >= mp3->total_frames)) - return; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3(mp3, wanted_frame); - - /* seems like we are using it */ - if (bytes >= 0) - mp3->data_cursor = (char *)mp3->data + bytes; - - /* no, use normal method */ - else - mp3->data_cursor += frame * mp3->framebytes; - - mp3->current_frame = wanted_frame; - mp3->dec_reinit = TRUE; -} - - -void almp3_seek_rel_msecs_mp3(ALMP3_MP3 *mp3, int msec) { - int frame; - frame = msec / almp3_get_msecs_per_frame_mp3(mp3); - almp3_seek_rel_frames_mp3(mp3, frame); -} - - -void almp3_seek_rel_secs_mp3(ALMP3_MP3 *mp3, int sec) { - almp3_seek_rel_msecs_mp3(mp3, sec * 1000); -} - - -void almp3_seek_rel_bytes_mp3(ALMP3_MP3 *mp3, int bytes) { - int current_byte = mp3->data_cursor - (char *)mp3->data; - int wanted_byte = current_byte + bytes; - - /* check the byte is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((wanted_byte < -mp3->data_start_skipped) || (wanted_byte >= mp3->data_len)) - return; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (wanted_byte < 0) - wanted_byte = 0; - - /* set the cursor to the new position */ - mp3->data_cursor = (char *)mp3->data + wanted_byte; - - mp3->current_frame = wanted_byte / mp3->framebytes; - mp3->dec_reinit = TRUE; -} - - -int almp3_poll_mp3(ALMP3_MP3 *mp3) { - void *audiobuf; - char *audiobuf_p; - int i, num_data_cursor, size_done; - - /* continue only if we are playing it */ - if (!almp3_is_playing_mp3(mp3)) - return ALMP3_POLL_NOTPLAYING; - - /* get the audio stream buffer and only continue if we need to fill it */ - audiobuf = get_audio_stream_buffer(mp3->audiostream); - if (audiobuf == NULL) - return ALMP3_OK; - - /* clear the buffer */ - memset(audiobuf, 0, mp3->outbytes_per_frame * mp3->frames_per_poll); - - /* if we need to fill it, but we were just waiting for it to finish */ - if (!mp3->loop) { - if (mp3->wait_for_audio_stop > 0) { - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - if (--mp3->wait_for_audio_stop == 0) { - /* stop it */ - almp3_stop_mp3(mp3); - return ALMP3_POLL_PLAYJUSTFINISHED; - } - else - return ALMP3_OK; - } - } - - /* reinitialize the decoder if needed */ - if (mp3->dec_reinit) { - mp3->wait_for_audio_stop = 0; - if (almp3_reinit_decoder_mp3(mp3) < 0) { - /* an error while reinitializing */ - almp3_stop_mp3(mp3); - almp3_rewind_mp3(mp3); - return ALMP3_POLL_INTERNALERROR; - } - } - - audiobuf_p = (char *)audiobuf; - size_done = 0; - for (i = 0; i < (mp3->outbytes_per_frame * mp3->frames_per_poll); i += size_done) { - int ret, inread; - /* if we have reached the end */ - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - if (num_data_cursor >= mp3->data_len) { - almp3_rewind_mp3(mp3); - if (!mp3->loop) { - /* we don't want clicks at the end, so we convert our empty buffer */ - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - mp3->dec_reinit = FALSE; - } - - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, audiobuf_p, &size_done, &inread); - - /* probably it needs more */ - if ((ret == -3) && mp3->loop) { - /* rewind and give it more */ - almp3_rewind_mp3(mp3); - mp3->dec_reinit = FALSE; - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, audiobuf_p, &size_done, &inread); - } - - /* check if the decoding was not successful */ - if (ret == 0) { - /* damn, seems like this frame is corrupt */ - /* check the next 16kb just to be sure */ - int j, got_error = TRUE, max, left; - max = 16 * 1024; - - left = mp3->data_len - num_data_cursor; - - if (!mp3->loop && (max > left)) - max = left; - - for (j = 0; (j < max) && (got_error); j++) { - - /* check if we have to check the start again */ - if (mp3->loop && (j == left)) { - almp3_rewind_mp3(mp3); - mp3->dec_reinit = FALSE; - } - - /* check the header */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(mp3->data_cursor)) == -1) { - /* try to decode it */ - almp3_reinit_decoder_mp3(mp3); - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, audiobuf_p, &size_done, &inread); - if (ret == -1) { - char *p = mp3->data_cursor + (mp3->mpeg).fr.framesize + 4; - if (p < ((char *)mp3->data + mp3->data_len)) { - /* check the next header too just to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) != 0) - got_error = FALSE; - } - else { - /* if we don't have enough data to check, assume it is */ - got_error = FALSE; - } - } - } - - if (got_error) - mp3->data_cursor++; - } - - /* if we were unlucky, this is probably corrupt */ - /* (don't take it so seriously if it is the last frame) <- thanks to Bruno Dupuis */ - if (got_error && ((mp3->data_len - num_data_cursor) > (mp3->mpeg).fr.framesize)) { - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - almp3_stop_mp3(mp3); - almp3_rewind_mp3(mp3); - return ALMP3_POLL_FRAMECORRUPT; - } - } - - audiobuf_p += size_done; - mp3->current_frame++; - mp3->data_cursor += inread; - } - - /* convert to allegro unsigned format */ - almp3_convert_to_unsigned_format_mp3(mp3, audiobuf); - - /* lock the buffer */ - free_audio_stream_buffer(mp3->audiostream); - - /* if we have reached the end */ - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - if (num_data_cursor >= mp3->data_len) { - almp3_rewind_mp3(mp3); - if (!mp3->loop) - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - - return ALMP3_OK; -} - - -void almp3_start_autopoll_mp3(ALMP3_MP3 *mp3, int speed) { - /* return if we are already auto polling */ - if (mp3->auto_polling) - return; - - mp3->auto_polling = TRUE; - mp3->auto_poll_speed = speed; - - /* only install the interrupt if we are already playing */ - /* otherwise, play will do */ - if (almp3_is_playing_mp3(mp3)) { - LOCK_FUNCTION(almp3_autopoll_mp3); - install_param_int(&almp3_autopoll_mp3, (void *)mp3, mp3->auto_poll_speed); - } -} - - -void almp3_stop_autopoll_mp3(ALMP3_MP3 *mp3) { - /* return if we are already not auto polling */ - if (!mp3->auto_polling) - return; - - mp3->auto_polling = FALSE; - - /* only remove the interrupt if we were already playing */ - /* otherwise, stop will do*/ - if (almp3_is_playing_mp3(mp3)) - remove_param_int(&almp3_autopoll_mp3, (void *)mp3); -} - - -int almp3_get_pos_frames_mp3(ALMP3_MP3 *mp3) { - return mp3->current_frame; -} - - -int almp3_get_pos_msecs_mp3(ALMP3_MP3 *mp3) { - float second; - second = mp3->current_frame * mp3->outbytes_per_frame; - second /= (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - second /= (float)mp3->freq; - return (int)(1000 * second); -} - - -int almp3_get_pos_secs_mp3(ALMP3_MP3 *mp3) { - return (almp3_get_pos_msecs_mp3(mp3) / 1000); -} - - -int almp3_get_length_frames_mp3(ALMP3_MP3 *mp3) { - return mp3->total_frames; -} - - -int almp3_get_pos_bytes_mp3(ALMP3_MP3 *mp3) { - return (mp3->data_cursor - (char *)mp3->data) + mp3->data_start_skipped; -} - - -int almp3_get_length_msecs_mp3(ALMP3_MP3 *mp3) { - int msecs; - msecs = almp3_get_length_frames_mp3(mp3) * almp3_get_msecs_per_frame_mp3(mp3); - return msecs; -} - - -int almp3_get_length_secs_mp3(ALMP3_MP3 *mp3) { - return (almp3_get_length_msecs_mp3(mp3) / 1000); -} - - -int almp3_get_length_bytes_mp3(ALMP3_MP3 *mp3) { - return (mp3->data_len + mp3->data_start_skipped + mp3->data_end_skipped); -} - - -int almp3_get_msecs_per_frame_mp3(ALMP3_MP3 *mp3) { - int msecs; - msecs = (int)((double)mp3->outbytes_per_frame / (double)almp3_get_outbytes_per_sec_mp3(mp3) * (double)1000); - return msecs; -} - - -int almp3_get_bitrate_mp3(ALMP3_MP3 *mp3) { - return mp3->bitrate; -} - - -int almp3_get_layer_mp3(ALMP3_MP3 *mp3) { - return mp3->layer; -} - - -int almp3_get_wave_bits_mp3(ALMP3_MP3 *mp3) { - return mp3->bits; -} - - -int almp3_get_wave_is_stereo_mp3(ALMP3_MP3 *mp3) { - return mp3->stereo; -} - - -int almp3_get_wave_freq_mp3(ALMP3_MP3 *mp3) { - return mp3->freq; -} - - -SAMPLE *almp3_create_sample_from_mp3(ALMP3_MP3 *mp3) { - SAMPLE *sample; - char *data; - int num_data_cursor, sample_len, sample_len_bytes, size_done; - - /* first we need to calculate the len of the sample (in frames and bytes) */ - sample_len_bytes = almp3_get_length_frames_mp3(mp3) * mp3->outbytes_per_frame; - sample_len = (sample_len_bytes / (mp3->bits / 8)) / (mp3->stereo ? 2 : 1); - - /* create the sample */ - sample = create_sample(mp3->bits, mp3->stereo, mp3->freq, sample_len); - - /* return NULL if we were not able to allocate the memory for it */ - if (sample == NULL) - return NULL; - - /* we need to stop and rewind the mp3 */ - almp3_stop_mp3(mp3); - almp3_rewind_mp3(mp3); - - /* reinitialize the decoded if neecesary */ - if (mp3->dec_reinit) { - if (almp3_reinit_decoder_mp3(mp3) < 0) { - /* an error while reinitializing */ - return NULL; - } - } - - /* set our pointer */ - data = (char *)sample->data; - /* clear the sample buffer */ - memset(data, 0, sample_len_bytes); - - /* decode */ - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - size_done = 0; - while (num_data_cursor < mp3->data_len) { - int ret, inread; - - /* send bytes until it has enough to render a frame */ - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, data, &size_done, &inread); - - /* check if the decoding was not successful */ - if (ret == 0) { - /* damn, seems like this frame is corrupt */ - /* check the next 16kb just to be sure */ - int j, got_error = TRUE, max, left; - - max = 16 * 1024; - - left = mp3->data_len - num_data_cursor; - - if (max > left) - max = left; - - for (j = 0; (j < max) && got_error; j++) { - /* check the header */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(mp3->data_cursor)) == -1) { - /* try to decode it */ - almp3_reinit_decoder_mp3(mp3); - ret = almp3_decode_frame_mp3(mp3, mp3->data_cursor, data, &size_done, &inread); - if (ret == -1) { - char *p = mp3->data_cursor + (mp3->mpeg).fr.framesize + 4; - if (p < ((char *)mp3->data + mp3->data_len)) { - /* check the next header too just to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) != 0) - got_error = FALSE; - } - else { - /* if we don't have enough data to check, assume it is */ - got_error = FALSE; - } - } - } - - if (got_error) - mp3->data_cursor++; - } - - /* if we were unlucky, this is probably corrupt */ - /* (don't take it so seriously if it is the last frame) <- thanks to Bruno Dupuis */ - if (got_error && ((mp3->data_len - num_data_cursor) > (mp3->mpeg).fr.framesize)) { - almp3_rewind_mp3(mp3); - destroy_sample(sample); - return NULL; - } - } - - data += size_done; - mp3->data_cursor += inread; - num_data_cursor = mp3->data_cursor - (char *)mp3->data; - mp3->current_frame++; - } - - almp3_rewind_mp3(mp3); - - /* convert to allegro unsigned format */ - if (mp3->bits == 16) { - void *buf = sample->data; - unsigned int i, *j, k; - k = sample_len_bytes / 4; - for (i = 0, j = (unsigned int *)buf; i < k; i++, j++) - *j ^= 0x80008000; - } - - return sample; -} - - -void almp3_adjust_mp3(ALMP3_MP3 *mp3, int vol, int pan, int speed, int loop) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3(mp3)) - return; - - /* adjust the sample */ - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); - mp3->loop = loop; -} - - -void *almp3_get_output_wave_mp3(ALMP3_MP3 *mp3, int *buffer_size) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3(mp3)) - return NULL; - - /* set the buffer_size */ - *buffer_size = mp3->outbytes_per_frame * mp3->frames_per_poll; - - /* return the current audiostream sample data */ - return (mp3->audiostream->samp->data); -} - - -int almp3_is_playing_mp3(ALMP3_MP3 *mp3) { - if (mp3->audiostream == NULL) - return FALSE; - else - return TRUE; -} - - -int almp3_is_looping_mp3(ALMP3_MP3 *mp3) { - if (!almp3_is_playing_mp3(mp3)) - return FALSE; - return mp3->loop; -} - - -void almp3_set_loop_mp3(ALMP3_MP3 *mp3, int loop) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3(mp3)) - return; - - mp3->loop = loop; -} - - -AUDIOSTREAM *almp3_get_audiostream_mp3(ALMP3_MP3 *mp3) { - return mp3->audiostream; -} - - - - -/* API - MP3STREAM */ - -/* function called in an interrupt */ - -static void almp3_autopoll_mp3stream(void *mp3) { - almp3_poll_mp3stream((ALMP3_MP3STREAM *)mp3); -} -END_OF_FUNCTION(almp3_autopoll_mp3stream); - - -/* helper functions */ - -static int almp3_reinit_decoder_mp3stream(ALMP3_MP3STREAM *mp3) { - /* reinitialize the decoder */ - ExitMP3(&(mp3->mpeg)); - InitMP3(&(mp3->mpeg)); - - mp3->dec_reinit = FALSE; - - return 0; -} - - -static void almp3_convert_to_unsigned_format_mp3stream(ALMP3_MP3STREAM *mp3, void *buf) { - /* convert to allegro unsigned format */ - if (mp3->bits == 16) { - unsigned int i, *j, k; - k = (mp3->outbytes_per_frame * mp3->frames_per_poll) / 4; - for (i = 0, j = (unsigned int *)buf; i < k; i++, j++) - *j ^= 0x80008000; - } -} - - -static int almp3_get_bytes_at_frame_using_toc_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int data_len) { - int tof[100], i, flags; - int bytesmin, bytesmax, bytesdif, bytes; - int framemin, framemax, framedif; - - /* check for missing data */ - if (mp3->xing_header == NULL) - return -1; - flags = mp3->xing_header->flags; - if (!(flags & XING_FRAMES_FLAG) || !(flags & XING_TOC_FLAG)) - return -1; - if ((frame >= mp3->xing_header->frames) || (frame < 0)) - return -1; - - /* create a table of frames */ - for (i = 0; i < 100; i++) - tof[i] = (mp3->xing_header->toc[i] * mp3->xing_header->frames) / 256; - - /* check in what part of the table of frames is our frame */ - for (i = 0; i < 100; i++) { - if (frame <= tof[i]) - break; - } - - /* our frame is between the i% and (i + 1)% of the file */ - /* let's do more calcules for a "fine" seeking */ - if (i == 100) - return data_len; - bytesmin = (data_len * i) / 100; - framemin = tof[i]; - if (i < 99) { - bytesmax = (data_len * (i + 1)) / 100; - framemax = tof[i + 1]; - } - else { - bytesmax = data_len - 1; - framemax = mp3->xing_header->frames - 1; - } - bytesdif = bytesmax - bytesmin; - framedif = framemax - framemin; - - bytes = bytesmin + (((frame - framemin) * bytesdif) / framedif); - - return bytes; -} - - -static int almp3_get_outbytes_per_sec_mp3stream(ALMP3_MP3STREAM *mp3) { - int bytes_out; - bytes_out = (mp3->stereo ? 2 : 1) * (mp3->bits / 8) * mp3->freq; - return bytes_out; -} - - -static int almp3_decode_frame_mp3stream(ALMP3_MP3STREAM *mp3, char *inbuf, int inlen, char *outbuf, int *size_done, int *inread) { - /* send bytes until it has enough to render a frame */ - int ret; - *inread = 0; - ret = decodeMP3(&(mp3->mpeg), NULL, 0, outbuf, 8192, size_done); - if (ret == MP3_NEED_MORE) { - int chunk_size; - - if (mp3->xing_header) - chunk_size = MAXFRAMESIZE; - else - chunk_size = mp3->framebytes + 4; - - do { - if (inlen <= 0) - break; - - else if (inlen < chunk_size) { - ret = decodeMP3(&(mp3->mpeg), inbuf, inlen, outbuf, 8192, size_done); - inbuf += inlen; - *inread += inlen; - inlen = 0; - } - else { - ret = decodeMP3(&(mp3->mpeg), inbuf, chunk_size, outbuf, 8192, size_done); - inlen -= chunk_size; - inbuf += chunk_size; - *inread += chunk_size; - } - } while (ret == MP3_NEED_MORE); - } - - { - int val = almp3_check_frame_validity((mp3->mpeg).header); - if ((ret == MP3_ERR) || (val == 0) || ((mp3->mpeg).fr.framesize <= 0)) - return 0; - else - return -1; - } - -} - - - -/* API functions */ - -ALMP3_MP3STREAM *almp3_create_mp3stream(void *first_data_buffer, int data_buffer_len, int last_block) { - ALMP3_MP3STREAM *mp3; - struct mpstr test_mpeg; - unsigned char *p = (unsigned char *)first_data_buffer; - int skipbytes; - void *databuf1, *databuf2, *full_databuf; - int ret; - char test_outbuf[8192]; - int test_size, framebytes; - - /* test the first 16 * MAXFRAMESIZE bytes until we find one valid */ - { - int found, max; - if (data_buffer_len >= (16 * MAXFRAMESIZE)) - max = 16 * MAXFRAMESIZE; - else - max = data_buffer_len; - - found = FALSE; - skipbytes = 0; - while (!found && (skipbytes < max)) { - int data_left = max - skipbytes; - char *p = (char *)first_data_buffer + skipbytes; - - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) == -1) { - /* probably found, check */ - InitMP3(&test_mpeg); - ret = decodeMP3(&test_mpeg, p, data_left, test_outbuf, 8192, &test_size); - if ((ret == MP3_OK) && (test_mpeg.fr.framesize > 0)) { - char *p2 = p + test_mpeg.fr.framesize + 4; - if (p2 < ((char *)first_data_buffer + max)) { - /* check the next frame to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p2)) != 0) - found = TRUE; - } - else { - /* guess it is right */ - found = TRUE; - } - } - - if (!found) - ExitMP3(&test_mpeg); - } - - if (!found) - skipbytes++; - } - - if (!found) { - return NULL; - } - } - - /* must be layer III or II */ - if ((test_mpeg.fr.lay != 3) && (test_mpeg.fr.lay != 2)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* the mp3 is ok, get some info */ - framebytes = test_mpeg.fr.framesize + 4; - if ((framebytes <= 4)) { - ExitMP3(&test_mpeg); - return NULL; - } - - /* allocate the buffers */ - databuf1 = malloc(data_buffer_len); - if (databuf1 == NULL) { - ExitMP3(&test_mpeg); - return NULL; - } - databuf2 = malloc(data_buffer_len); - if (databuf2 == NULL) { - ExitMP3(&test_mpeg); - free(databuf1); - return NULL; - } - full_databuf = malloc(data_buffer_len * 2); - if (full_databuf == NULL) { - ExitMP3(&test_mpeg); - free(databuf1); - free(databuf2); - return NULL; - } - - /* copy the first data */ - memcpy(databuf1, first_data_buffer, data_buffer_len); - - /* create a new mp3 struct */ - mp3 = (ALMP3_MP3STREAM *)malloc(sizeof(ALMP3_MP3STREAM)); - if (mp3 == NULL) { - ExitMP3(&test_mpeg); - free(databuf1); - free(databuf2); - free(full_databuf); - return NULL; - } - - /* init the real decoder */ - InitMP3(&(mp3->mpeg)); - - /* fill in the mp3 struct */ - mp3->data_start_skipped = skipbytes; - mp3->databuf1 = databuf1; - mp3->databuf2 = databuf2; - mp3->full_databuf = (char *)full_databuf; - mp3->data_cursor = skipbytes; - mp3->databuf_selector = 1; - mp3->databuf_len = data_buffer_len; - mp3->unsel_databuf_free = TRUE; - if (last_block) - mp3->bytes_used = data_buffer_len; - else - mp3->bytes_used = -1; - - mp3->freq = almp3freqs[test_mpeg.fr.sampling_frequency]; - if (test_mpeg.fr.stereo >= 2) - mp3->stereo = TRUE; - else - mp3->stereo = FALSE; - mp3->bits = 16; - mp3->outbytes_per_frame = test_size; - mp3->audiostream = NULL; - mp3->current_frame = 0; - mp3->current_byte = skipbytes; - mp3->auto_polling = FALSE; - mp3->bitrate = almp3tabsel_123[test_mpeg.fr.lsf][test_mpeg.fr.lay - 1][test_mpeg.fr.bitrate_index] * 1000; - mp3->layer = test_mpeg.fr.lay; - if (mp3->layer <= 0) - mp3->layer = -1; - mp3->dec_reinit = FALSE; - mp3->framebytes = framebytes; - mp3->xing_header = NULL; - - /* if outbytes_per_frame is incorrect, correct it */ - if (mp3->outbytes_per_frame <= 0) { - int samples = 1152; - if (mp3->layer == 2) - samples = 1152; - if (mp3->layer == 3) { - if ((mp3->freq >= 32000) && (mp3->freq < 48000)) - samples = 1152; - else if ((mp3->freq >= 8000) && (mp3->freq < 24000)) - samples = 576; - } - mp3->outbytes_per_frame = samples * (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - } - - /* check for the xing header */ - p = (unsigned char *)((char *)first_data_buffer + skipbytes); - if (!test_mpeg.fr.lsf) { /* mpeg1 */ - if (test_mpeg.fr.mode != 3) - p += 32 + 4; - else - p += 17 + 4; - } - else { /* mpeg2 */ - if (test_mpeg.fr.mode != 3) - p += 17 + 4; - else - p += 9 + 4; - } - - if (memcmp(p, "Xing", 4) == 0) { - - /* found */ - int x; - p += 4; - mp3->xing_header = (XING_HEADER *)malloc(sizeof(XING_HEADER)); - x = mp3->xing_header->flags = almp3_get_big_endian(p); - p += 4; - if (x & XING_FRAMES_FLAG) { - mp3->xing_header->frames = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_BYTES_FLAG) { - mp3->xing_header->bytes = almp3_get_big_endian(p); - p += 4; - } - if (x & XING_TOC_FLAG) { - int j; - for (j = 0; j < 100; j++, p++) - mp3->xing_header->toc[j] = *p; - } - mp3->xing_header->vbr_scale = -1; - if (x & XING_VBR_SCALE_FLAG) { - mp3->xing_header->vbr_scale = almp3_get_big_endian(p); - p += 4; - } - - } - - /* get the number of total frames if we are using a XING header*/ - if ((mp3->xing_header != NULL) && (mp3->xing_header->flags & XING_FRAMES_FLAG)) - mp3->total_frames = mp3->xing_header->frames; - /* else we don't know it */ - else - mp3->total_frames = -1; - - /* deinit the test decoder */ - ExitMP3(&test_mpeg); - - return mp3; -} - - -void almp3_destroy_mp3stream(ALMP3_MP3STREAM *mp3) { - if (mp3 == NULL) - return; - - almp3_stop_mp3stream(mp3); /* note almp3_stop_mp3stream will */ - /* remove autopolling interrupts */ - ExitMP3(&(mp3->mpeg)); - if (mp3->xing_header) - free(mp3->xing_header); - free(mp3->full_databuf); - free(mp3->databuf1); - free(mp3->databuf2); - free(mp3); -} - - -int almp3_play_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan) { - return almp3_play_ex_mp3stream(mp3, buffer_len, vol, pan, 1000); -} - - -int almp3_play_ex_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan, int speed) { - int samples; - - /* continue only if we are not already playing it */ - if (almp3_is_playing_mp3stream(mp3)) - return ALMP3_OK; - - /* calculate the frames we can decode for each poll */ - /* using the given buffer_len */ - mp3->frames_per_poll = buffer_len / mp3->outbytes_per_frame; - if (mp3->frames_per_poll <= 0) - return ALMP3_PLAY_BUFFERTOOSMALL; - - /* create a new audiostream and play it */ - samples = (mp3->outbytes_per_frame * mp3->frames_per_poll) / (mp3->stereo ? 2 : 1) / (mp3->bits / 8); - mp3->audiostream = play_audio_stream(samples, mp3->bits, mp3->stereo, mp3->freq, vol, pan); - if (!mp3->audiostream) { - return ALMP3_POLL_INTERNALERROR; - } - - mp3->wait_for_audio_stop = 0; - - if (speed != 1000) - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); - - /* if the user asked for autopolling, install the interrupt now */ - if (mp3->auto_polling) { - LOCK_FUNCTION(almp3_autopoll_mp3stream); - install_param_int(&almp3_autopoll_mp3stream, (void *)mp3, mp3->auto_poll_speed); - } - - return ALMP3_OK; -} - - -void almp3_stop_mp3stream(ALMP3_MP3STREAM *mp3) { - /* continue if we are playing it */ - if (!almp3_is_playing_mp3stream(mp3)) - return; - - /* remove the interrupt, if we were using autopolling */ - if (mp3->auto_polling) - remove_param_int(&almp3_autopoll_mp3stream, (void *)mp3); - - /* stop the audio stream */ - stop_audio_stream(mp3->audiostream); - mp3->audiostream = NULL; -} - - -int almp3_poll_mp3stream(ALMP3_MP3STREAM *mp3) { - void *audiobuf; - char *audiobuf_p; - char *temp_databuf; - int temp_buf_size, using_full_databuf; - int i, size_done; - int last_block; - - /* continue only if we are playing it */ - if (!almp3_is_playing_mp3stream(mp3)) - return ALMP3_POLL_NOTPLAYING; - - /* get the audio stream buffer and only continue if we need to fill it */ - audiobuf = get_audio_stream_buffer(mp3->audiostream); - if (audiobuf == NULL) - return ALMP3_OK; - - /* clear the buffer */ - memset(audiobuf, 0, mp3->outbytes_per_frame * mp3->frames_per_poll); - - /* if we need to fill it, but we were just waiting for it to finish */ - if (mp3->wait_for_audio_stop > 0) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - if (--mp3->wait_for_audio_stop == 0) { - /* stop it */ - almp3_stop_mp3stream(mp3); - return ALMP3_POLL_PLAYJUSTFINISHED; - } - else - return ALMP3_OK; - } - - /* get if this will be the last block to be processed */ - if (mp3->bytes_used != -1) - last_block = TRUE; - else - last_block = FALSE; - - /* if the 2 buffers are available, use the concatenated one */ - if (!mp3->unsel_databuf_free) { - temp_databuf = mp3->full_databuf; - using_full_databuf = TRUE; - if (!last_block) - temp_buf_size = mp3->databuf_len * 2; - else - temp_buf_size = mp3->databuf_len + mp3->bytes_used; - } - /* else just point to the current buffer */ - else { - using_full_databuf = FALSE; - if (mp3->databuf_selector == 1) - temp_databuf = (char *)mp3->databuf1; - else - temp_databuf = (char *)mp3->databuf2; - if (!last_block) - temp_buf_size = mp3->databuf_len; - else - temp_buf_size = mp3->bytes_used; - } - - /* reinitialize the decoder if needed */ - if (mp3->dec_reinit) { - mp3->wait_for_audio_stop = 0; - if (almp3_reinit_decoder_mp3stream(mp3) < 0) { - /* an error while reinitializing */ - almp3_stop_mp3stream(mp3); - return ALMP3_POLL_INTERNALERROR; - } - } - - audiobuf_p = (char *)audiobuf; - size_done = 0; - for (i = 0; i < (mp3->outbytes_per_frame * mp3->frames_per_poll); i += size_done) { - int ret, temp_buf_left, inread; - - /* check for a ID1 tag - note we do this here cause ID1 tags */ - /* go at the end of file and we have no way to know where is the end */ - if (memcmp(temp_databuf + mp3->data_cursor, "TAG", 3) == 0) { - mp3->data_cursor += 128; - mp3->current_byte += 128; - almp3_reinit_decoder_mp3stream(mp3); - } - - /* check for buffer underrun or end of the mp3 */ - temp_buf_left = temp_buf_size - mp3->data_cursor; - if (temp_buf_left <= 0) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALMP3_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - } - - ret = almp3_decode_frame_mp3stream(mp3, (char *)temp_databuf + mp3->data_cursor, temp_buf_left, audiobuf_p, &size_done, &inread); - - /* check if the decoding was not successful */ - if (ret == 0) { - /* damn, seems like this frame is corrupt */ - /* check the next 16kb just to be sure */ - int j, max, got_error = TRUE, left; - - max = 16 * 1024; - - left = temp_buf_left; - - if (max > left) - max = left; - - - for (j = 0; (j < max) && (got_error); j++) { - char *p; - - /* check for buffer underrun or end of the mp3 */ - if (mp3->data_cursor >= temp_buf_size) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALMP3_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - } - - /* check the header */ - p = (char *)temp_databuf + mp3->data_cursor; - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) == -1) { - /* try to decode it */ - almp3_reinit_decoder_mp3stream(mp3); - ret = almp3_decode_frame_mp3stream(mp3, p, temp_buf_left, audiobuf_p, &size_done, &inread); - if (ret == -1) { - char *p = (char *)temp_databuf + mp3->data_cursor + (mp3->mpeg).fr.framesize + 4; - if (p < ((char *)temp_databuf + temp_buf_size)) { - /* check the next header too just to make sure */ - if (almp3_check_frame_validity((unsigned int)almp3_get_big_endian(p)) != 0) - got_error = FALSE; - } - else { - /* if we don't have enough data to check, assume it is */ - got_error = FALSE; - } - } - } - - if (got_error) { - mp3->data_cursor++; - mp3->current_byte++; - temp_buf_left--; - } - - } - /* if we are still unlucky, this is probably corrupt */ - if (got_error) { - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - free_audio_stream_buffer(mp3->audiostream); - almp3_stop_mp3stream(mp3); - return ALMP3_POLL_FRAMECORRUPT; - } - } - - mp3->data_cursor += inread; - mp3->current_byte += inread; - audiobuf_p += size_done; - mp3->current_frame++; - } - - /* convert to allegro unsigned format */ - almp3_convert_to_unsigned_format_mp3stream(mp3, audiobuf); - - /* lock the buffer */ - free_audio_stream_buffer(mp3->audiostream); - - /* if we were using the full_databuf */ - if (using_full_databuf) { - /* if the cursor passed the first buffer len */ - if (mp3->data_cursor >= mp3->databuf_len) { - /* set the cursor to a good position and mark as free the old buffer */ - mp3->data_cursor -= mp3->databuf_len; - mp3->databuf_selector = -mp3->databuf_selector; - mp3->unsel_databuf_free = TRUE; - } - } - /* using only one buffer */ - else { - if (mp3->data_cursor >= mp3->databuf_len) { - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALMP3_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - mp3->wait_for_audio_stop = 2; - return ALMP3_OK; - } - } - } - - return ALMP3_OK; -} - - -void almp3_start_autopoll_mp3stream(ALMP3_MP3STREAM *mp3, int speed) { - /* return if we are already auto polling */ - if (mp3->auto_polling) - return; - - mp3->auto_polling = TRUE; - mp3->auto_poll_speed = speed; - - /* only install the interrupt if we are already playing */ - /* otherwise, play will do */ - if (almp3_is_playing_mp3stream(mp3)) { - LOCK_FUNCTION(almp3_autopoll_mp3stream); - install_param_int(&almp3_autopoll_mp3stream, (void *)mp3, mp3->auto_poll_speed); - } -} - - -void almp3_stop_autopoll_mp3stream(ALMP3_MP3STREAM *mp3) { - /* return if we are already not auto polling */ - if (!mp3->auto_polling) - return; - - mp3->auto_polling = FALSE; - - /* only remove the interrupt if we were already playing */ - /* otherwise, stop will do*/ - if (almp3_is_playing_mp3stream(mp3)) - remove_param_int(&almp3_autopoll_mp3stream, (void *)mp3); -} - - -void *almp3_get_mp3stream_buffer(ALMP3_MP3STREAM *mp3) { - if (!mp3->unsel_databuf_free) - return NULL; - - /* if the last block was already passed, we don't need more data */ - if (mp3->bytes_used != -1) - return NULL; - - if (mp3->databuf_selector == 1) - return mp3->databuf2; - else - return mp3->databuf1; -} - - -void almp3_free_mp3stream_buffer(ALMP3_MP3STREAM *mp3, int bytes_used) { - if (mp3->unsel_databuf_free) { - mp3->unsel_databuf_free = FALSE; - mp3->bytes_used = bytes_used; - if (mp3->databuf_selector == 1) { - memcpy(mp3->full_databuf, mp3->databuf1, mp3->databuf_len); - memcpy(mp3->full_databuf + mp3->databuf_len, mp3->databuf2, mp3->databuf_len); - } - else { - memcpy(mp3->full_databuf, mp3->databuf2, mp3->databuf_len); - memcpy(mp3->full_databuf + mp3->databuf_len, mp3->databuf1, mp3->databuf_len); - } - } -} - - -int almp3_get_pos_frames_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->current_frame; -} - - -int almp3_get_pos_msecs_mp3stream(ALMP3_MP3STREAM *mp3) { - float second; - second = mp3->current_frame * mp3->outbytes_per_frame; - second /= (mp3->stereo ? 2 : 1) * (mp3->bits / 8); - second /= (float)mp3->freq; - return (int)(1000 * second); -} - - -int almp3_get_pos_secs_mp3stream(ALMP3_MP3STREAM *mp3) { - return (almp3_get_pos_msecs_mp3stream(mp3) / 1000); -} - - -int almp3_get_pos_bytes_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->current_byte; -} - - -int almp3_get_msecs_per_frame_mp3stream(ALMP3_MP3STREAM *mp3) { - int msecs; - msecs = (int)((double)mp3->outbytes_per_frame / (double)almp3_get_outbytes_per_sec_mp3stream(mp3) * (double)1000); - return msecs; -} - - -int almp3_get_bitrate_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->bitrate; -} - - -int almp3_get_layer_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->layer; -} - - -int almp3_get_wave_bits_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->bits; -} - - -int almp3_get_wave_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->stereo; -} - - -int almp3_get_wave_freq_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->freq; -} - - -void almp3_adjust_mp3stream(ALMP3_MP3STREAM *mp3, int vol, int pan, int speed) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3stream(mp3)) - return; - - /* adjust the sample */ - adjust_sample(mp3->audiostream->samp, vol, pan, speed, TRUE); -} - - -void *almp3_get_output_wave_mp3stream(ALMP3_MP3STREAM *mp3, int *buffer_size) { - /* return if we are not playing */ - if (!almp3_is_playing_mp3stream(mp3)) - return NULL; - - /* set the buffer_size */ - *buffer_size = mp3->outbytes_per_frame * mp3->frames_per_poll; - - /* return the current audiostream sample data */ - return (mp3->audiostream->samp->data); -} - - -int almp3_get_length_frames_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - /* if we have the frames from the XING header, use it */ - if (mp3->total_frames != -1) - return mp3->total_frames; - else - return (total_size / mp3->framebytes); -} - - -int almp3_get_length_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - int msecs; - msecs = almp3_get_length_frames_mp3stream(mp3, total_size) * almp3_get_msecs_per_frame_mp3stream(mp3); - return msecs; -} - - -int almp3_get_length_secs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - return (almp3_get_length_msecs_mp3stream(mp3, total_size) / 1000); -} - - -int almp3_get_length_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int total_size) { - return total_size; -} - - -int almp3_is_playing_mp3stream(ALMP3_MP3STREAM *mp3) { - if (mp3->audiostream == NULL) - return FALSE; - else - return TRUE; -} - - -AUDIOSTREAM *almp3_get_audiostream_mp3stream(ALMP3_MP3STREAM *mp3) { - return mp3->audiostream; -} - - -int almp3_seek_abs_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size) { - int bytes; - int total_frames; - - /* get the number of total frames */ - total_frames = almp3_get_length_frames_mp3stream(mp3, total_size); - - /* check if the frame is valid */ - if ((frame < 0) || (frame >= total_frames)) - return -1; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3stream(mp3, frame, total_size); - - /* seems like we are using it */ - if (bytes >= 0) - return bytes; - - /* no, use normal method */ - else - return (frame * mp3->framebytes); -} - - -int almp3_seek_abs_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msecs, int total_size) { - int frame; - frame = msecs / almp3_get_msecs_per_frame_mp3stream(mp3); - return almp3_seek_abs_frames_mp3stream(mp3, frame, total_size); -} - - -int almp3_seek_abs_secs_mp3stream(ALMP3_MP3STREAM *mp3, int secs, int total_size){ - return almp3_seek_abs_msecs_mp3stream(mp3, secs * 1000, total_size); -} - - -int almp3_seek_abs_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size) { - /* check the pos in bytes is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((bytes < -mp3->data_start_skipped) || (bytes >= total_size)) - return -1; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (bytes < 0) - bytes = 0; - - return bytes; -} - - -int almp3_seek_rel_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size) { - int bytes; - int wanted_frame = mp3->current_frame + frame; - int total_frames; - - /* get total frames */ - total_frames = almp3_get_length_frames_mp3stream(mp3, total_size); - - /* check the frame is valid */ - if ((wanted_frame < 0) || (wanted_frame >= total_frames)) - return -1; - - /* first try using the xing header */ - bytes = almp3_get_bytes_at_frame_using_toc_mp3stream(mp3, wanted_frame, total_size); - - /* seems like we are using it */ - if (bytes >= 0) - return bytes; - - /* no, use normal method */ - else - return (frame * mp3->framebytes); -} - - -int almp3_seek_rel_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msec, int total_size) { - int frame; - frame = msec / almp3_get_msecs_per_frame_mp3stream(mp3); - return almp3_seek_rel_frames_mp3stream(mp3, frame, total_size); -} - - -int almp3_seek_rel_secs_mp3stream(ALMP3_MP3STREAM *mp3, int sec, int total_size) { - return almp3_seek_rel_msecs_mp3stream(mp3, sec * 1000, total_size); -} - - -int almp3_seek_rel_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size) { - int current_byte = almp3_get_pos_bytes_mp3stream(mp3); - int wanted_byte = current_byte + bytes; - - /* check the byte is valid */ - /* we check against -mp3->data_start_skipped because our data buffer */ - /* skipped the very first ID3v2 header */ - if ((wanted_byte < -mp3->data_start_skipped) || (wanted_byte >= total_size)) - return -1; - - /* if the poiner wanted was inside the ID3v2 header, skip it and */ - /* point directly to the data */ - if (wanted_byte < 0) - wanted_byte = 0; - - return wanted_byte; -} diff --git a/Engine/libsrc/alogg/ALOGG.txt b/Engine/libsrc/alogg/ALOGG.txt deleted file mode 100644 index ee09d46c93c..00000000000 --- a/Engine/libsrc/alogg/ALOGG.txt +++ /dev/null @@ -1,380 +0,0 @@ - - AllegroOGG v1.0.3 - =================== - - AllegroOGG (c) 2002 Javier Gonzalez - - OGG Decoder part of Ogg Vorbis (Xiph.org Foundation) - - -#include - - - "I do not accept responsibility for any effects, adverse or otherwise, - that this code may have on you, your computer, your sanity, your dog, - and anything else that you can think of. Use it at your own risk." - - - -See README.txt for a general introduction, copyright details, and -information about how to install AllegroOGG. - - - -Using AllegroOGG ----------------- - - To be able to use AllegroOGG with your program, you just need (once - compiled the library) to link the generated lib with your program - (remember that since this lib relies on allegro, you need to add - alogg *before* alleg) and include the header "alogg.h", available in - the lib and include directories respectively. - - -Reference ---------- - - Note parameters are marked between ' ' markers. - - - Differences between ALOGG_OGG and ALOGG_OGGSTREAM: - There are three ways to open ogg data: - 1) Using ALOGG_OGG and alogg_create_ogg_from_file() has the pros - that it won't need to load the whole file in mem and that will - read chunks when needed, and also that you will be able to seek, - get total length, but has the cons that only for work - individual files containing only ogg data, this is, doesn't work - for your own file format. - 2) Using ALOGG_OGG and alogg_create_ogg_from_buffer() has the pros - that you will be able to seek, get the total length and use your - own file format, but has the cons that you will need to load the - whole ogg data into memory. - 3) Using ALOGG_OGGSTREAM has the pros that you won't need to load the - whole file in mem and that will read chunks when needed, and also - that you will be able to use your own file format (even get data - on the fly, like for example from a network), but has the cons - that you won't be able to seek or get the total length. - All of them support getting the current position though. - - - ALOGG_OGG *alogg_create_ogg_from_file(FILE *f); - Creates an ALOGG_OGG which you'll have to pass to all the other - functions, where 'f' is the file pointer that must be already opened. - Note you aren't supposed to close this file until you have destroyed - the ALOGG_OGG. - - return values: - NULL if there ocurred an error (mostly an invalid ogg data was passed). - Other value ( != NULL ) otherwise. - - - ALOGG_OGG *alogg_create_ogg_from_buffer(void *data, int data_len); - Creates an ALOGG_OGG which you'll have to pass to all the other - functions, where 'data' will be a pointer to the buffer containing - the ogg data and 'data_len' the size of this buffer. Note you aren't - supposed to free this buffer until you have destroyed the ALOGG_OGG. - - return values: - NULL if there ocurred an error (mostly an invalid ogg data was passed). - Other value ( != NULL ) otherwise. - - - void alogg_destroy_ogg(ALOGG_OGG *ogg); - Destroys the ALOGG_OGG automatically stopping it. Note this function - check if the 'ogg' pointer is pointing to NULL, so for example this: - ALOGG_OGG *ogg = NULL; - destroy_ogg(ogg); - won't crash the program. - - - int alogg_play_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan); - Plays the 'ogg' ALOGG_OGG with the given volume 'vol' (from 0 to 255) - and panning 'pan' (from 0 to 255, where 0 is full left and 255 is - full right). 'buffer_len' is the desired size in bytes of the - buffer where the decoded data will be stored. The bigger, the less - you'll have to poll the OGG, but the more time you will have to wait - in order to hear the song start playing. Note that due to some - ogg format limitations, the internal (and real) buffer will be - an aproximation to the 'buffer_len' given. A 'buffer_len' size between - 16384 and 32768 bytes (16kb and 32kb) will do in most cases. - - return values: - ALOGG_OK if no problems. - ALOGG_PLAY_BUFFERTOOSMALL if the given 'buffer_len' was not big enough. - - special note: - This function also works like a "resume" function, since it - won't rewind the ALOGG_OGG automatically. Note that once the ALOGG_OGG - has reached the end when playing, it will rewind though, stoping the - ALOGG_OGG if the loop flag was set at FALSE (see alogg_play_ex_ogg()) - or continuing playing it if it was set at TRUE. Also note that this - automatically stops decoding. - - - int alogg_play_ex_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan, int speed, int loop); - See alogg_play_ogg(). The only new is the 'speed' that will play the - ALOGG_OGG at a given speed (being 1000 = normal speed, 2000 = twice - fast, 500 = half speed and so on) and a loop flag that can be set to - not stop the ALOGG_OGG when it has reached the end, but continue it - playing from the start. - - return values: - See alogg_play_ogg(). - - special note: - See alogg_play_ogg(). Note that you can change speed, pan, volume, etc - values to the ALOGG_OGG many times, but you will need to stop it first. - - - void alogg_stop_ogg(ALOGG_OGG *ogg); - Stops the ALOGG_OGG if it was playing. - - special note: - This function also works like a "pause" function, since it won't - rewind it automatically. - - - void alogg_adjust_ogg(ALOGG_OGG *ogg, int vol, int pan, int speed, int loop); - Adjust the ALOGG_OGG parameters when it is already playing. - - - void alogg_rewind_ogg(ALOGG_OGG *ogg); - Rewinds the ALOGG_OGG to its start. - - special note: - This function won't automatically stop the ALOGG_OGG if it was - already playing. - - - void alogg_seek_abs_msecs_ogg(ALOGG_OGG *ogg, int msecs); - void alogg_seek_abs_secs_ogg(ALOGG_OGG *ogg, int secs); - void alogg_seek_abs_bytes_ogg(ALOGG_OGG *ogg, int bytes); - Does an absolute seek (from start of the ogg), given the new - position either in msecs, secs or bytes. - - special note: - This function won't stop the ALOGG_OGG if it was already playing. - - - void alogg_seek_rel_msecs_ogg(ALOGG_OGG *ogg, int msec); - void alogg_seek_rel_secs_ogg(ALOGG_OGG *ogg, int sec); - void alogg_seek_rel_bytes_ogg(ALOGG_OGG *ogg, int bytes); - Does a relative seek (from current position), given the new - position either in msecs, secs or bytes. - - special note: - This function won't stop the ALOGG_OGG if it was already playing. - - - int alogg_poll_ogg(ALOGG_OGG *ogg); - This functions needs to be called in order to keep the ALOGG_OGG - playing properly, since the oggs need to be decoded at real time - (either that, or to a huge memory buffer). - - return values: - ALOGG_OK if there were no error. - ALOGG_POLL_PLAYJUSTFINISHED (only once) when the file has JUST - finished playing. - ALOGG_POLL_NOTPLAYING if the file is not playing. - ALOGG_POLL_FRAMECORRUPT if one of the frames is corrupt. - ALOGG_POLL_INTERNALERROR if an internal error happened. - - special note: - If you don't want (or can't) poll all the time, you can use - automatic polling (see below), but I don't recommend this since - this can be very unstable, specially under DOS (altought I've - never experienced such problems myself, but better warn ;). - - - void alogg_start_autopoll_ogg(ALOGG_OGG *ogg, int speed); - Creates an allegro interrupt that will call poll for this ALOGG_OGG - each 'speed' msecs. This frees you from calling polling yourself, - but I recommend this only in the case you can't call poll (because - of the nature of your program) yourself at regular intervals. - - - void alogg_stop_autopoll_ogg(ALOGG_OGG *ogg); - Destroys the allegro interrupt for that ALOGG_OGG. - - - int alogg_get_pos_msecs_ogg(ALOGG_OGG *ogg); - int alogg_get_pos_secs_ogg(ALOGG_OGG *ogg); - int alogg_get_pos_bytes_ogg(ALOGG_OGG *ogg); - Returns the ALOGG_OGG current position either in msecs, secs - or bytes. - - - int alogg_get_length_secs_ogg(ALOGG_OGG *ogg); - int alogg_get_length_msecs_ogg(ALOGG_OGG *ogg); - int alogg_get_length_bytes_ogg(ALOGG_OGG *ogg); - Returns the ALOGG_OGG length either in msecs, secs or bytes. - - - int alogg_get_bitrate_ogg(ALOGG_OGG *ogg); - Returns the ALOGG_OGG bitrate in bits per second, NOT in kbits. That's - for example 128000, 64000, 96000, etc. - - - int alogg_get_wave_bits_ogg(ALOGG_OGG *ogg); - int alogg_get_wave_is_stereo_ogg(ALOGG_OGG *ogg); - int alogg_get_wave_freq_ogg(ALOGG_OGG *ogg); - Returns info about the wave. - - - SAMPLE *alogg_create_sample_from_ogg(ALOGG_OGG *ogg); - Decodes the given ALOGG_OGG into an Allegro SAMPLE structure. Please - note for big oggs this function could generate a HUGE SAMPLE, so it - is only recommended for very small oggs like sound effects. - - return values: - NULL on error. - otherwise not NULL. - - - void *alogg_get_output_wave_ogg(ALOGG_OGG *ogg, int *buffer_size); - Returns a pointer to the piece of wave decoded after each poll, and - the size of this buffer as well in 'buffer_size' (in bytes). Note this - function will NOT automatically convert from unsinged to signed 16 bit - data using the Allegro format instead of the standard format, so this - data cannot be saved directly into a WAV for example without - modifications. Also note in order for this function to work, the - ALOGG_OGG needs to BE playing. - - return values: - NULL if there is no wave being decoded. - Else the buffer with the wave data. - - - int alogg_is_playing_ogg(ALOGG_OGG *ogg); - Returns TRUE if the ALOGG_OGG is currently being played or FALSE - if it is not. - - - int alogg_is_looping_ogg(ALOGG_OGG *ogg); - void alogg_set_loop_ogg(ALOGG_OGG *ogg, int loop); - Self explanatory. Note these functions only work when the ALOGG_OGG - is playing. - - - AUDIOSTREAM *alogg_get_audiostream_ogg(ALOGG_OGG *ogg); - Returns the allegro AUDIOSTREAM currently being used by the ALOGG_OGG. - - - - ALOGG_OGGSTREAM *alogg_create_oggstream(void *first_data_buffer, int data_buffer_len, int last_block); - See alogg_create_ogg(). The only difference is that 'first_data_buffer' - contains the very first buffer of len 'data_buffer_len' that you will - have to give to the OGGSTREAM periodically. If after this data, there - won't be more (this is, this was the last buffer to be processed), - pass TRUE to 'last_block'. - - - void alogg_destroy_oggstream(ALOGG_OGGSTREAM *ogg); - See alogg_destroy_ogg(). - - - int alogg_play_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan); - See alogg_play_ex_oggstream(). - - - int alogg_play_ex_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan, int speed); - See alogg_play_ex_ogg(). The only difference is that here is no 'loop' - parameter. To loop an ALOGG_OGGSTREAM just destroy the ALOGG_OGGSTREAM - and recreate it (or pass data continuosly). - - - void alogg_stop_oggstream(ALOGG_OGGSTREAM *ogg); - See alogg_stop_ogg(). - - - void alogg_adjust_oggstream(ALOGG_OGGSTREAM *ogg, int vol, int pan, int speed); - Adjust the ALOGG_OGGSTREAM parameters when it is already playing. - Note it doesn't include the parameter loop because ALOGG_OGGSTREAMs are - always looping (or better said, they don't have two points to loop - from/to). - - - int alogg_poll_oggstream(ALOGG_OGGSTREAM *ogg); - See alogg_poll_ogg(). - - return values: - ALOGG_OK if there were no error. - ALOGG_POLL_PLAYJUSTFINISHED (only once) when the file has JUST - finished playing. - ALOGG_POLL_NOTPLAYING if the file is not playing. - ALOGG_POLL_FRAMECORRUPT if one of the frames is corrupt. - ALOGG_POLL_BUFFERUNDERUN if the buffer was exhausted. - ALOGG_POLL_INTERNALERROR if an internal error happened. - - - void alogg_start_autopoll_oggstream(ALOGG_OGGSTREAM *ogg, int speed); - See alogg_start_autopoll_ogg(). Note I discourage the use of this - function with ALOGG_OGGSTREAMs since in anyway you'll have to use - alogg_get_oggstream_buffer() to send data periodically. - - - void alogg_stop_autopoll_oggstream(ALOGG_OGGSTREAM *ogg); - See alogg_stop_autopoll_ogg(). - - - void *alogg_get_oggstream_buffer(ALOGG_OGGSTREAM *ogg); - If the return value is not NULL, it will return a buffer that you'll - have to fill with 'buffer_data_len' (from create_oggstream) bytes MAX - of new data. You will need to use free_oggstream_buffer() when you - are finished with it. - - return values: - NULL if it doesn't need any data yet. - Else the buffer to be filled. - - - void alogg_free_oggstream_buffer(ALOGG_OGGSTREAM *ogg, int bytes_used); - Use whenever you are finished with the buffer returned by - alogg_get_oggstream_buffer(). If 'bytes_used' is -1 it will use - the full buffer and that will mean this is not the last block - of data, else if 'bytes_used' is a number, it will indicate - that this is the last buffer and the number of bytes to use from that - last block. Once this buffer has been played and processed, - alogg_poll_ogg_stream() will return ALOGG_POLL_JUSTFINISHED. - - - int alogg_get_pos_msecs_oggstream(ALOGG_OGGSTREAM *ogg); - int alogg_get_pos_secs_oggstream(ALOGG_OGGSTREAM *ogg); - int alogg_get_pos_bytes_oggstream(ALOGG_OGGSTREAM *ogg); - int alogg_get_bitrate_oggstream(ALOGG_OGGSTREAM *ogg); - See their ALOGG_OGG equals. - - int alogg_get_wave_bits_oggstream(ALOGG_OGGSTREAM *ogg); - int alogg_get_wave_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); - int alogg_get_wave_freq_oggstream(ALOGG_OGGSTREAM *ogg); - Returns info about the wave. - - - void *alogg_get_output_wave_oggstream(ALOGG_OGGSTREAM *ogg, int *buffer_size); - Returns a pointer to the piece of wave decoded after each poll, and - the size of this buffer as well in 'buffer_size' (in bytes). Note this - function will NOT automatically convert from unsinged to signed 16 bit - data using the Allegro format instead of the standard format, so this - data cannot be saved directly into a WAV for example without - modifications. Also note in order for this function to work, the - ALOGG_OGGSTREAM needs to BE playing. - - return values: - NULL if there is no wave being decoded. - Else the buffer with the wave data. - - - int alogg_is_playing_oggstream(ALOGG_OGGSTREAM *ogg); - Returns TRUE if the ALOGG_OGGSTREAM is currently being played or FALSE - if it is not. - - - AUDIOSTREAM *alogg_get_audiostream_oggstream(ALOGG_OGGSTREAM *ogg); - Returns the allegro AUDIOSTREAM currently being used by the - ALOGG_OGGSTREAM. - Note that when the ALOGG_OGGSTREAM isn't being played most probably - it will return NULL. - - - I hope these docs are useful to you. - diff --git a/Engine/libsrc/alogg/AUTHORS.txt b/Engine/libsrc/alogg/AUTHORS.txt deleted file mode 100644 index dce02b82cc3..00000000000 --- a/Engine/libsrc/alogg/AUTHORS.txt +++ /dev/null @@ -1,5 +0,0 @@ -Authors -------- - -Javier Gonzalez - Made the main API and ported the decoder to - make it able to be used in Allegro and DOS programs diff --git a/Engine/libsrc/alogg/CHANGES.txt b/Engine/libsrc/alogg/CHANGES.txt deleted file mode 100644 index 12fa690eed6..00000000000 --- a/Engine/libsrc/alogg/CHANGES.txt +++ /dev/null @@ -1,16 +0,0 @@ -Changes -------- - - v1.0.3 - - Fixed lots of documentation typos pointed by rafalszyja@poczta.onet.pl - - Fixed a semi-serious bug in the ALOGG_OGGSTREAMs - - v1.0.2 - - Looping fixed in ALOGG_OGGs - - v1.0.1 - - Fixed a bug in alogg_create_ogg_from_sample() where it would never - finish if the ogg was corrupt - - v1.0.0 - - First public release diff --git a/Engine/libsrc/alogg/CMakeLists.txt b/Engine/libsrc/alogg/CMakeLists.txt deleted file mode 100644 index 013f1df0c2e..00000000000 --- a/Engine/libsrc/alogg/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_library(alogg) - -set_target_properties(alogg PROPERTIES - C_STANDARD 11 - C_EXTENSIONS NO -) - -target_include_directories(alogg PUBLIC . ) - -target_sources(alogg - PRIVATE - alogg.c -) - -target_link_libraries(alogg PUBLIC Allegro::Allegro AGS::Common Vorbis::Vorbis Vorbis::VorbisFile) - -add_library(AlOgg::AlOgg ALIAS alogg) diff --git a/Engine/libsrc/alogg/COPYING.txt b/Engine/libsrc/alogg/COPYING.txt deleted file mode 100644 index 928afad347e..00000000000 --- a/Engine/libsrc/alogg/COPYING.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2002, Xiph.org Foundation - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -- Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -- Neither the name of the Xiph.org Foundation nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Engine/libsrc/alogg/README.txt b/Engine/libsrc/alogg/README.txt deleted file mode 100644 index 8fccf7ac22b..00000000000 --- a/Engine/libsrc/alogg/README.txt +++ /dev/null @@ -1,71 +0,0 @@ - - AllegroOGG v1.0.3 - =================== - - AllegroOGG (c) 2002 Javier Gonzalez - - OGG Decoder part of Ogg Vorbis (Xiph.org Foundation) - - -AllegroOGG is an Allegro wrapper for the Ogg Vorbis (Xiph.org Foundation) -AllegroOGG is distributed under the Xiph.Org Foundation BDS alike license -(see file COPYING.txt). - -The full source code (very slightly modified to make it compatible -with Allegro and DOS) of this one is available in the decoder directory. - - -AllegroOGG uses code from: - - Ogg Vorbis (Xiph.org Foundation) - - -IMPORTANT NOTE FOR ALL VERSIONS: If you want to use the DLL please link - to the import library (aloggdll.lib in MSVC or libaloggdll.a for the - other systems (except DJGPP of course)) *and* define ALOGG_DLL - *before* including alogg.h, this way for example: - #define ALOGG_DLL - #include - If you wish to use the STATIC library just don't define ALOGG_DLL - - Also please note the examples use the static link library, so to build - them you will need to build the static link library first. - - -How to compile the library and example code: - - If you are running under a un*x system first run fixunix.sh - If you want to use the DOS/Windows the pack is ready to be used - as is right now, no conversion needed. fixdos.bat is only provided - to be used if you used fixunix.sh to change file formats to unix one - and you want them to be DOS format back again. Note that to use fixdos.bat - you will need utod.exe. - - - In case you are using GCC (DJGPP, MINGW32): - - Then edit the makefile and uncomment the target you want to compile to then run in the command - line "make" and that's all. - - It will generate a static link library (libalogg.a) ready to use in your - programs, or a dynamic link library (alogg.dll and libaloggdll.a import - lib in the Mingw32 case). - - After that, if you want to compile the examples, get inside the directory - examples, edit the makefile uncommenting the target you want to compile to - and type "make". - - - In case you are using Microsoft Visual C++: - - Open the project file and build whatever you choose. There are two options: - 1) To build the library as a static link library (alogg_static), that will - generate the alogg.lib file. - 2) To build the library as a dynamic link libray (alogg_dll) that will - generate the aloggdll.lib and alogg.dll files. - - -How to contact me: - - xaviergonz@hotmail.com - - diff --git a/Engine/libsrc/alogg/alogg.c b/Engine/libsrc/alogg/alogg.c deleted file mode 100644 index 2e81dcc3c01..00000000000 --- a/Engine/libsrc/alogg/alogg.c +++ /dev/null @@ -1,1195 +0,0 @@ -/* Allegro OGG */ -/* to play OGG files with Allegro */ - -/* OGG decoder part of Ogg Vorbis (Xiph.org Foundation) */ -/* Allegro OGG is copyright (c) 2002 Javier Gonzalez */ - -/* See COPYING.txt for license */ - - -#include -#include -#include -#include "vorbis/vorbisfile.h" -#include "vorbis/codec.h" - -#include "core/platform.h" /* For bigendian detection */ -#if AGS_PLATFORM_ENDIAN_BIG -#define WANT_BIG_ENDIAN 1 -#else -#define WANT_BIG_ENDIAN 0 -#endif - -#include "util/stdio_compat.h" - -/* standard ALOGG_OGG structure */ - -struct ALOGG_OGG { - /* data info */ - void *data; /* ogg data */ - char *data_cursor; /* pointer to data being read */ - int data_len; /* size of the data */ - /* decoder info */ - OggVorbis_File vf; - int current_section; - /* playing info */ - AUDIOSTREAM *audiostream; /* the audiostream we are using to play */ - /* also used to know when it's playing */ - int audiostream_buffer_len; /* len of the audiostream buffer */ - int stereo, freq, loop; /* audio general info */ - int auto_polling; /* set if the ogg is auto polling */ - int auto_poll_speed; /* auto poll speed in msecs */ - int wait_for_audio_stop; /* set if we are just waiting for the - audiobuffer to stop plaing the last - frame */ -}; - - -/* standard ALOGG_OGGSTREAM structure */ - -struct ALOGG_OGGSTREAM { - /* data info */ - void *databuf1, *databuf2; /* data buffers */ - char *full_databuf; /* to be used when the 2 buffers are filled */ - int data_cursor; /* pointer to data being read */ - int databuf_selector; /* 1 = databuf1, -1 = databuf2 */ - int databuf_len; /* size of the data buffer */ - int unsel_databuf_free; /* TRUE when the unselected databuffer */ - /* is free and needs to be filled */ - int bytes_used; /* number of bytes to use from the buffer */ - /* or -1 if the full buffer */ - /* decoder info */ - OggVorbis_File vf; - int current_section; - /* playing info */ - AUDIOSTREAM *audiostream; /* the audiostream we are using to play */ - /* also used to know when it's playing */ - int audiostream_buffer_len; /* len of the audiostream buffer */ - int freq, stereo; /* audio general info */ - int frames_per_poll; /* number of frames per play poll */ - int auto_polling; /* set if the ogg is auto polling */ - int auto_poll_speed; /* auto poll speed in msecs */ - int wait_for_audio_stop; /* set if we are just waiting for the - audiobuffer to stop plaing the last - frame */ -}; - - - -/* API - OGG */ - -/* callbacks */ - -size_t _alogg_ogg_read(void *ptr, size_t size, size_t nmemb, void *datasource) { - ALOGG_OGG *ogg = (ALOGG_OGG *)datasource; - int data_pos = ogg->data_cursor - (char *)ogg->data; - int data_left = ogg->data_len - data_pos; - int bytes_asked = size * nmemb; - - /* check how much we can copy */ - if (bytes_asked <= data_left) { - /* we can copy it all */ - memcpy(ptr, (const void *)ogg->data_cursor, bytes_asked); - ogg->data_cursor += bytes_asked; - /* all items read */ - return nmemb; - } - else { - int items = data_left / size; - int bytes = items * size; - /* check we are copying at least one item */ - if (items < 1) - return 0; - /* copy whatever we have left */ - memcpy(ptr, (const void *)ogg->data_cursor, bytes); - ogg->data_cursor += bytes; - /* return how many items we read */ - return items; - } -} - -int _alogg_ogg_seek(void *datasource, ogg_int64_t offset, int whence) { - ALOGG_OGG *ogg = (ALOGG_OGG *)datasource; - char *new_data_cursor; - - if (whence == SEEK_CUR) - new_data_cursor = ogg->data_cursor + offset; - else if (whence == SEEK_SET) - new_data_cursor = (char *)ogg->data + offset; - else if (whence == SEEK_END) - new_data_cursor = (char *)ogg->data + ogg->data_len + offset; - else - return -1; - - /* check the new pointer is valid */ - if ((new_data_cursor < (char *)ogg->data) || - (new_data_cursor > ((char *)ogg->data + ogg->data_len))) { - return -1; - } - else { - ogg->data_cursor = new_data_cursor; - return 0; - } -} - -int _alogg_ogg_close(void *datasource) { - ALOGG_OGG *ogg = (ALOGG_OGG *)datasource; - ogg->data_cursor = (char *)ogg->data; - - return 0; -} - -long _alogg_ogg_tell(void *datasource) { - ALOGG_OGG *ogg = (ALOGG_OGG *)datasource; - return (ogg->data_cursor - (char *)ogg->data); -} - -ov_callbacks _alogg_ogg_callbacks = { - &_alogg_ogg_read, - &_alogg_ogg_seek, - &_alogg_ogg_close, - &_alogg_ogg_tell -}; - - -/* function called in an interrupt */ - -static void alogg_autopoll_ogg(void *ogg) { - alogg_poll_ogg((ALOGG_OGG *)ogg); -} -END_OF_FUNCTION(alogg_autopoll_ogg); - - -/* API functions */ - -ALOGG_OGG *alogg_create_ogg_from_buffer(void *data, int data_len) { - ALOGG_OGG *ogg; - vorbis_info *vi; - int ret; - - /* create a new ogg struct */ - ogg = (ALOGG_OGG *)malloc(sizeof(ALOGG_OGG)); - if (ogg == NULL) - return NULL; - - /* fill in the ogg struct */ - ogg->data = data; - ogg->data_cursor = (char *)data; - ogg->data_len = data_len; - memset((void *)&ogg->vf, 0, sizeof(ogg->vf)); - ogg->audiostream = NULL; - ogg->loop = FALSE; - ogg->auto_polling = FALSE; - ogg->current_section = -1; - - /* use vorbisfile to open it */ - ret = ov_open_callbacks((void *)ogg, &(ogg->vf), NULL, 0, _alogg_ogg_callbacks); - - /* if error */ - if (ret < 0) { - free((void *)ogg); - return NULL; - } - - /* get audio info */ - vi = ov_info(&(ogg->vf), -1); - if (vi->channels > 1) - ogg->stereo = TRUE; - else - ogg->stereo = FALSE; - ogg->freq = vi->rate; - - return ogg; -} - - -ALOGG_OGG *alogg_create_ogg_from_file(FILE *f) { - ALOGG_OGG *ogg; - vorbis_info *vi; - int ret; - - /* create a new ogg struct */ - ogg = (ALOGG_OGG *)malloc(sizeof(ALOGG_OGG)); - if (ogg == NULL) - return NULL; - - /* fill in the ogg struct */ - ogg->data = NULL; - ogg->data_cursor = NULL; - { - int pos = ags_ftell(f); - ags_fseek(f, 0, SEEK_END); - ogg->data_len = ags_ftell(f); - ags_fseek(f, pos, SEEK_SET); - } - memset((void *)&ogg->vf, 0, sizeof(ogg->vf)); - ogg->audiostream = NULL; - ogg->loop = FALSE; - ogg->auto_polling = FALSE; - ogg->current_section = -1; - - /* use vorbisfile to open it */ - ret = ov_open(f, &(ogg->vf), NULL, 0); - - /* if error */ - if (ret < 0) { - free((void *)ogg); - return NULL; - } - - /* get audio info */ - vi = ov_info(&(ogg->vf), -1); - if (vi->channels > 1) - ogg->stereo = TRUE; - else - ogg->stereo = FALSE; - ogg->freq = vi->rate; - - return ogg; -} - - -void alogg_destroy_ogg(ALOGG_OGG *ogg) { - if (ogg == NULL) - return; - - alogg_stop_ogg(ogg); /* note alogg_stop_ogg will also remove */ - /* autopolling interrupts */ - ov_clear(&(ogg->vf)); - free(ogg); -} - -int alogg_play_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan) { - return alogg_play_ex_ogg(ogg, buffer_len, vol, pan, 1000, FALSE); -} - - -int alogg_play_ex_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan, int speed, int loop) { - int samples; - - /* continue only if we are not already playing it */ - if (alogg_is_playing_ogg(ogg)) - return ALOGG_OK; - - /* check the buffer is big enough*/ - if (buffer_len < 4096) - return ALOGG_PLAY_BUFFERTOOSMALL; - - /* create a new audiostream and play it */ - samples = buffer_len / (ogg->stereo ? 2 : 1) / 2; /* / 2 = 16 bits samples */ - ogg->audiostream = play_audio_stream(samples, 16, ogg->stereo, ogg->freq, vol, pan); - if (!ogg->audiostream) { - return ALOGG_POLL_INTERNALERROR; - } - ogg->audiostream_buffer_len = samples * (ogg->stereo ? 2 : 1) * 2; /* * 2 = 16 bits samples */ - - if (speed != 1000) - adjust_sample(ogg->audiostream->samp, vol, pan, speed, TRUE); - - ogg->loop = loop; - ogg->wait_for_audio_stop = 0; - - /* if the user asked for autopolling, install the interrupt now */ - if (ogg->auto_polling) { - LOCK_FUNCTION(alogg_autopoll_ogg); - install_param_int(&alogg_autopoll_ogg, (void *)ogg, ogg->auto_poll_speed); - } - - return ALOGG_OK; -} - - -void alogg_stop_ogg(ALOGG_OGG *ogg) { - /* continue if we are playing it */ - if (!alogg_is_playing_ogg(ogg)) - return; - - /* remove the interrupt, if we were using autopolling */ - if (ogg->auto_polling) - remove_param_int(&alogg_autopoll_ogg, (void *)ogg); - - /* stop the audio stream */ - stop_audio_stream(ogg->audiostream); - ogg->audiostream = NULL; -} - - -void alogg_rewind_ogg(ALOGG_OGG *ogg) { - ov_raw_seek(&(ogg->vf), 0); -} - - -void alogg_seek_abs_msecs_ogg(ALOGG_OGG *ogg, int msec) { -#ifdef USE_TREMOR - ov_time_seek(&(ogg->vf), msec); -#else - /* convert msec to pcm sample position */ - double s = msec; - s /= 1000; - - ov_time_seek(&(ogg->vf), s); -#endif -} - - -void alogg_seek_abs_secs_ogg(ALOGG_OGG *ogg, int sec) { -#ifdef USE_TREMOR - ov_time_seek(&(ogg->vf), sec * 1000); -#else - ov_time_seek(&(ogg->vf), sec); -#endif -} - - -void alogg_seek_abs_bytes_ogg(ALOGG_OGG *ogg, int bytes) { - /* check the pos in bytes is valid */ - if ((bytes < 0) || (bytes >= ogg->data_len)) - return; - - ov_raw_seek(&(ogg->vf), bytes); -} - - -void alogg_seek_rel_msecs_ogg(ALOGG_OGG *ogg, int msec) { -#ifdef USE_TREMOR - ogg_int64_t _msec = msec; - _msec += ov_time_tell(&(ogg->vf)); - - ov_time_seek(&(ogg->vf), _msec); -#else - double s = msec; - s /= 1000; - s += ov_time_tell(&(ogg->vf)); - - ov_time_seek(&(ogg->vf), s); -#endif -} - - -void alogg_seek_rel_secs_ogg(ALOGG_OGG *ogg, int sec) { -#ifdef USE_TREMOR - ogg_int64_t _msec = sec * 1000; - _msec += ov_time_tell(&(ogg->vf)); - ov_time_seek(&(ogg->vf), _msec); -#else - double s = sec; - s += ov_time_tell(&(ogg->vf)); - ov_time_seek(&(ogg->vf), s); -#endif -} - - -void alogg_seek_rel_bytes_ogg(ALOGG_OGG *ogg, int bytes) { - int current_byte = ov_raw_tell(&(ogg->vf)); - int wanted_byte = current_byte + bytes; - - /* check the byte is valid */ - if ((wanted_byte < 0) || (wanted_byte >= ogg->data_len)) - return; - - /* get current byte and add to it */ - bytes += ov_raw_tell(&(ogg->vf)); - ov_raw_seek(&(ogg->vf), bytes); -} - - -int alogg_poll_ogg(ALOGG_OGG *ogg) { - void *audiobuf; - char *audiobuf_p; - int i, size_done; - unsigned short* data_array; - int x; - - /* continue only if we are playing it */ - if (!alogg_is_playing_ogg(ogg)) - return ALOGG_POLL_NOTPLAYING; - - /* get the audio stream buffer and only continue if we need to fill it */ - audiobuf = get_audio_stream_buffer(ogg->audiostream); - if (audiobuf == NULL) - return ALOGG_OK; - - /* clear the buffer with 16bit unsigned data */ - { - int i; - unsigned short *j = (unsigned short *)audiobuf; - for (i = 0; i < (ogg->audiostream_buffer_len / 2); i++, j++) - *j = 0x8000; - } - - /* if we need to fill it, but we were just waiting for it to finish */ - if (!ogg->loop) { - if (ogg->wait_for_audio_stop > 0) { - free_audio_stream_buffer(ogg->audiostream); - if (--ogg->wait_for_audio_stop == 0) { - /* stop it */ - //rest(500); - alogg_stop_ogg(ogg); - return ALOGG_POLL_PLAYJUSTFINISHED; - } - else - return ALOGG_OK; - } - } - - audiobuf_p = (char *)audiobuf; - size_done = 0; - for (i = ogg->audiostream_buffer_len; i > 0; i -= size_done) { - /* decode */ - size_done = ov_read(&(ogg->vf), audiobuf_p, i, WANT_BIG_ENDIAN, 2, 0, &(ogg->current_section)); - -#ifdef USE_TREMOR - /* Add offset to data because we are using libtremor */ - data_array = (unsigned short*)audiobuf_p; - - for (x = 0; x < size_done / 2; x++) - { - data_array[x] += 0x8000; - } -#endif - - /* check if the decoding was not successful */ - if (size_done < 0) { - if (size_done == OV_HOLE) - size_done = 0; - else { - free_audio_stream_buffer(ogg->audiostream); - alogg_stop_ogg(ogg); - alogg_rewind_ogg(ogg); - return ALOGG_POLL_FRAMECORRUPT; - } - } - else if (size_done == 0) { - /* we have reached the end */ - alogg_rewind_ogg(ogg); - if (!ogg->loop) { - free_audio_stream_buffer(ogg->audiostream); - ogg->wait_for_audio_stop = 2; - return ALOGG_OK; - } - } - - audiobuf_p += size_done; - } - - /* lock the buffer */ - free_audio_stream_buffer(ogg->audiostream); - - return ALOGG_OK; -} - - -void alogg_start_autopoll_ogg(ALOGG_OGG *ogg, int speed) { - /* return if we are already auto polling */ - if (ogg->auto_polling) - return; - - ogg->auto_polling = TRUE; - ogg->auto_poll_speed = speed; - - /* only install the interrupt if we are already playing */ - /* otherwise, play will do */ - if (alogg_is_playing_ogg(ogg)) { - LOCK_FUNCTION(alogg_autopoll_ogg); - install_param_int(&alogg_autopoll_ogg, (void *)ogg, ogg->auto_poll_speed); - } -} - - -void alogg_stop_autopoll_ogg(ALOGG_OGG *ogg) { - /* return if we are already not auto polling */ - if (!ogg->auto_polling) - return; - - ogg->auto_polling = FALSE; - - /* only remove the interrupt if we were already playing */ - /* otherwise, stop will do*/ - if (alogg_is_playing_ogg(ogg)) - remove_param_int(&alogg_autopoll_ogg, (void *)ogg); -} - - -int alogg_get_pos_msecs_ogg(ALOGG_OGG *ogg) { -#ifdef USE_TREMOR - return (int)(ov_time_tell(&(ogg->vf))); -#else - return (int)(ov_time_tell(&(ogg->vf)) * 1000); -#endif -} - - -int alogg_get_pos_secs_ogg(ALOGG_OGG *ogg) { -#ifdef USE_TREMOR - return (int)ov_time_tell(&(ogg->vf)) / 1000; -#else - return (int)ov_time_tell(&(ogg->vf)); -#endif -} - - -int alogg_get_pos_bytes_ogg(ALOGG_OGG *ogg) { - return ov_raw_tell(&(ogg->vf)); -} - - -int alogg_get_length_msecs_ogg(ALOGG_OGG *ogg) { -#ifdef USE_TREMOR - return (int)ov_time_total(&(ogg->vf), -1); -#else - double s = ov_time_total(&(ogg->vf), -1) * 1000; - return (int)s; -#endif -} - - -int alogg_get_length_secs_ogg(ALOGG_OGG *ogg) { -#ifdef USE_TREMOR - return (int)ov_time_total(&(ogg->vf), -1) * 1000; -#else - return (int)ov_time_total(&(ogg->vf), -1); -#endif -} - - -int alogg_get_length_bytes_ogg(ALOGG_OGG *ogg) { - return ov_raw_total(&(ogg->vf), -1); -} - - -int alogg_get_bitrate_ogg(ALOGG_OGG *ogg) { - return ov_bitrate(&(ogg->vf), -1); -} - - -int alogg_get_wave_bits_ogg(ALOGG_OGG *ogg) { - return 16; -} - - -int alogg_get_wave_is_stereo_ogg(ALOGG_OGG *ogg) { - return ogg->stereo; -} - - -int alogg_get_wave_freq_ogg(ALOGG_OGG *ogg) { - return ogg->freq; -} - - -SAMPLE *alogg_create_sample_from_ogg(ALOGG_OGG *ogg) { - SAMPLE *sample; - char *data; - int i, sample_len_bytes, sample_len, size_done, done; - unsigned short* data_array; - int x; - - /* first we need to calculate the len of the sample in bytes */ - sample_len = ov_pcm_total(&(ogg->vf), -1); - sample_len_bytes = (sample_len * (ogg->stereo ? 2 : 1)) * 2; /* / 2 = 16 bits */ - - /* create the sample */ - sample = create_sample(16, ogg->stereo, ogg->freq, sample_len); - - /* return NULL if we were not able to allocate the memory for it */ - if (sample == NULL) - return NULL; - - /* we need to stop and rewind the ogg */ - alogg_stop_ogg(ogg); - alogg_rewind_ogg(ogg); - - /* set our pointer */ - data = (char *)sample->data; - /* clear the sample buffer in unsigned format */ - { - int i; - unsigned short *j = (unsigned short *)data; - for (i = 0; i < (sample_len_bytes / 2); i++, j++) - *j = 0x8000; - } - - /* decode */ - done = FALSE; - size_done = 0; - for (i = sample_len_bytes; !done && (i > 0); i -= size_done) { - - /* decode */ - size_done = ov_read(&(ogg->vf), data, i, WANT_BIG_ENDIAN, 2, 0, &(ogg->current_section)); - -#ifdef USE_TREMOR - /* Add offset to data because we are using libtremor. */ - data_array = (unsigned short*)data; - - for (x = 0; x < size_done / 2; x++) - { - data_array[x] += 0x8000; - } -#endif - - /* check if the decoding was not successful */ - if (size_done < 0) { - if (size_done == OV_HOLE) - size_done = 0; - else { - alogg_rewind_ogg(ogg); - destroy_sample(sample); - return NULL; - } - } - else if (size_done == 0) - done = TRUE; - - data += size_done; - } - - alogg_rewind_ogg(ogg); - - return sample; -} - - -void alogg_adjust_ogg(ALOGG_OGG *ogg, int vol, int pan, int speed, int loop) { - /* return if we are not playing */ - if (!alogg_is_playing_ogg(ogg)) - return; - - /* adjust the sample */ - adjust_sample(ogg->audiostream->samp, vol, pan, speed, TRUE); - voice_set_volume (ogg->audiostream->voice, vol); - ogg->loop = loop; -} - - -void *alogg_get_output_wave_ogg(ALOGG_OGG *ogg, int *buffer_size) { - /* return if we are not playing */ - if (!alogg_is_playing_ogg(ogg)) - return NULL; - - /* set the buffer_size */ - *buffer_size = ogg->audiostream_buffer_len; - - /* return the current audiostream sample data */ - return (ogg->audiostream->samp->data); -} - - -int alogg_is_playing_ogg(ALOGG_OGG *ogg) { - if (ogg->audiostream == NULL) - return FALSE; - else - return TRUE; -} - - -int alogg_is_looping_ogg(ALOGG_OGG *ogg) { - if (!alogg_is_playing_ogg(ogg)) - return FALSE; - return ogg->loop; -} - - -void alogg_set_loop_ogg(ALOGG_OGG *ogg, int loop) { - /* return if we are not playing */ - if (!alogg_is_playing_ogg(ogg)) - return; - - ogg->loop = loop; -} - - -AUDIOSTREAM *alogg_get_audiostream_ogg(ALOGG_OGG *ogg) { - return ogg->audiostream; -} - - - - -/* API - OGGSTREAM */ - -/* callbacks */ - -size_t _alogg_oggstream_read(void *ptr, size_t size, size_t nmemb, void *datasource) { - ALOGG_OGGSTREAM *ogg = (ALOGG_OGGSTREAM *)datasource; - int bytes_asked = size * nmemb, data_left; - int last_block, temp_buf_size, using_full_databuf, items; - char *temp_databuf; - - /* get if this will be the last block to be processed */ - if (ogg->bytes_used != -1) - last_block = TRUE; - else - last_block = FALSE; - - /* if the 2 buffers are available, use the concatenated one */ - if (!ogg->unsel_databuf_free) { - temp_databuf = ogg->full_databuf; - using_full_databuf = TRUE; - if (!last_block) - temp_buf_size = ogg->databuf_len * 2; - else - temp_buf_size = ogg->databuf_len + ogg->bytes_used; - } - /* else just point to the current buffer */ - else { - using_full_databuf = FALSE; - if (ogg->databuf_selector == 1) - temp_databuf = (char *)ogg->databuf1; - else - temp_databuf = (char *)ogg->databuf2; - if (!last_block) - temp_buf_size = ogg->databuf_len; - else - temp_buf_size = ogg->bytes_used; - } - - /* get the data left */ - data_left = temp_buf_size - ogg->data_cursor; - - /* check how much we can copy */ - if (bytes_asked <= data_left) { - /* we can copy it all */ - memcpy(ptr, (const void *)(temp_databuf + ogg->data_cursor), bytes_asked); - ogg->data_cursor += bytes_asked; - /* all items read */ - items = nmemb; - } - else { - int bytes; - items = data_left / size; - bytes = items * size; - /* check we are copying at least one item */ - if (items < 1) - return 0; - /* copy whatever we have left */ - memcpy(ptr, (const void *)(temp_databuf + ogg->data_cursor), bytes); - ogg->data_cursor += bytes; - /* return how many items we read */ - /* items = items */ - } - - /* adjust the databuf selectors */ - /* if we were using the full_databuf */ - if (using_full_databuf) { - /* if the cursor passed the first buffer len */ - if (ogg->data_cursor >= ogg->databuf_len) { - /* set the cursor to a good position and mark as free the old buffer */ - ogg->data_cursor -= ogg->databuf_len; - ogg->databuf_selector = -ogg->databuf_selector; - ogg->unsel_databuf_free = TRUE; - } - } - - return items; -} - - -int _alogg_oggstream_seek(void *datasource, ogg_int64_t offset, int whence) { - return -1; -} - -int _alogg_oggstream_close(void *datasource) { - return 0; -} - -long _alogg_oggstream_tell(void *datasource) { - return 0; -} - -ov_callbacks _alogg_oggstream_callbacks = { - &_alogg_oggstream_read, - &_alogg_oggstream_seek, - &_alogg_oggstream_close, - &_alogg_oggstream_tell -}; - - -/* function called in an interrupt */ - -static void alogg_autopoll_oggstream(void *ogg) { - alogg_poll_oggstream((ALOGG_OGGSTREAM *)ogg); -} -END_OF_FUNCTION(alogg_autopoll_oggstream); - - -/* API functions */ - -ALOGG_OGGSTREAM *alogg_create_oggstream(void *first_data_buffer, int data_buffer_len, int last_block) { - ALOGG_OGGSTREAM *ogg; - vorbis_info *vi; - int ret; - void *databuf1, *databuf2, *full_databuf; - - /* create a new ogg struct */ - ogg = (ALOGG_OGGSTREAM *)malloc(sizeof(ALOGG_OGGSTREAM)); - if (ogg == NULL) - return NULL; - - /* allocate the buffers */ - databuf1 = malloc(data_buffer_len); - if (databuf1 == NULL) { - free((void *)ogg); - return NULL; - } - databuf2 = malloc(data_buffer_len); - if (databuf2 == NULL) { - free((void *)ogg); - free(databuf1); - return NULL; - } - full_databuf = malloc(data_buffer_len * 2); - if (full_databuf == NULL) { - free((void *)ogg); - free(databuf1); - free(databuf2); - return NULL; - } - - /* copy the first data */ - memcpy(databuf1, first_data_buffer, data_buffer_len); - - /* fill in the ogg struct */ - ogg->databuf1 = databuf1; - ogg->databuf2 = databuf2; - ogg->full_databuf = (char *)full_databuf; - ogg->data_cursor = 0; - ogg->databuf_selector = 1; - ogg->databuf_len = data_buffer_len; - ogg->unsel_databuf_free = TRUE; - if (last_block) - ogg->bytes_used = data_buffer_len; - else - ogg->bytes_used = -1; - ogg->audiostream = NULL; - ogg->auto_polling = FALSE; - - /* use vorbisfile to open it */ - ret = ov_open_callbacks((void *)ogg, &(ogg->vf), NULL, 0, _alogg_oggstream_callbacks); - - /* if error */ - if (ret < 0) { - free((void *)ogg); - free((void *)databuf1); - free((void *)databuf2); - free((void *)full_databuf); - return NULL; - } - - /* get audio info */ - vi = ov_info(&(ogg->vf), -1); - if (vi->channels > 1) - ogg->stereo = TRUE; - else - ogg->stereo = FALSE; - ogg->freq = vi->rate; - - return ogg; -} - - -void alogg_destroy_oggstream(ALOGG_OGGSTREAM *ogg) { - if (ogg == NULL) - return; - - alogg_stop_oggstream(ogg); /* note alogg_stop_oggstream will */ - /* remove autopolling interrupts */ - ov_clear(&(ogg->vf)); - free(ogg->full_databuf); - free(ogg->databuf1); - free(ogg->databuf2); - free(ogg); -} - - -int alogg_play_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan) { - return alogg_play_ex_oggstream(ogg, buffer_len, vol, pan, 1000); -} - - -int alogg_play_ex_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan, int speed) { - int samples; - - /* continue only if we are not already playing it */ - if (alogg_is_playing_oggstream(ogg)) - return ALOGG_OK; - - /* check the buffer is big enough*/ - if (buffer_len < 4096) - return ALOGG_PLAY_BUFFERTOOSMALL; - - /* create a new audiostream and play it */ - samples = buffer_len / (ogg->stereo ? 2 : 1) / 2; /* / 2 = 16 bits samples */ - ogg->audiostream = play_audio_stream(samples, 16, ogg->stereo, ogg->freq, vol, pan); - if (!ogg->audiostream) { - return ALOGG_POLL_INTERNALERROR; - } - ogg->audiostream_buffer_len = samples * (ogg->stereo ? 2 : 1) * 2; /* * 2 = 16 bits samples */ - - ogg->wait_for_audio_stop = 0; - - if (speed != 1000) - adjust_sample(ogg->audiostream->samp, vol, pan, speed, TRUE); - - /* if the user asked for autopolling, install the interrupt now */ - if (ogg->auto_polling) { - LOCK_FUNCTION(alogg_autopoll_oggstream); - install_param_int(&alogg_autopoll_oggstream, (void *)ogg, ogg->auto_poll_speed); - } - - return ALOGG_OK; -} - - -void alogg_stop_oggstream(ALOGG_OGGSTREAM *ogg) { - /* continue if we are playing it */ - if (!alogg_is_playing_oggstream(ogg)) - return; - - /* remove the interrupt, if we were using autopolling */ - if (ogg->auto_polling) - remove_param_int(&alogg_autopoll_oggstream, (void *)ogg); - - /* stop the audio stream */ - stop_audio_stream(ogg->audiostream); - ogg->audiostream = NULL; -} - - -int alogg_poll_oggstream(ALOGG_OGGSTREAM *ogg) { - void *audiobuf; - char *audiobuf_p; - int i, size_done; - int last_block; - unsigned short* data_array; - int x; - - /* continue only if we are playing it */ - if (!alogg_is_playing_oggstream(ogg)) - return ALOGG_POLL_NOTPLAYING; - - /* get the audio stream buffer and only continue if we need to fill it */ - audiobuf = get_audio_stream_buffer(ogg->audiostream); - if (audiobuf == NULL) - return ALOGG_OK; - - /* clear the buffer with unsinged data*/ - { - int i; - unsigned short *j = (unsigned short *)audiobuf; - for (i = 0; i < (ogg->audiostream_buffer_len / 2); i++, j++) - *j = 0x8000; - } - - /* if we need to fill it, but we were just waiting for it to finish */ - if (ogg->wait_for_audio_stop > 0) { - free_audio_stream_buffer(ogg->audiostream); - if (--ogg->wait_for_audio_stop == 0) { - /* stop it */ - alogg_stop_oggstream(ogg); - return ALOGG_POLL_PLAYJUSTFINISHED; - } - else - return ALOGG_OK; - } - - /* get if this will be the last block to be processed */ - if (ogg->bytes_used != -1) - last_block = TRUE; - else - last_block = FALSE; - - audiobuf_p = (char *)audiobuf; - size_done = 0; - for (i = ogg->audiostream_buffer_len; i > 0; i -= size_done) { - size_done = ov_read(&(ogg->vf), audiobuf_p, i, WANT_BIG_ENDIAN, 2, 0, &(ogg->current_section)); - -#ifdef USE_TREMOR - /* Add offset to data because we are using libtremor. */ - data_array = (unsigned short*)audiobuf_p; - - for (x = 0; x < size_done / 2; x++) - { - data_array[x] += 0x8000; - } -#endif - - /* check if the decoding was not successful */ - if (size_done < 0) { - if (size_done == OV_HOLE) - size_done = 0; - else { - free_audio_stream_buffer(ogg->audiostream); - alogg_stop_oggstream(ogg); - return ALOGG_POLL_FRAMECORRUPT; - } - } - else if (size_done == 0) { - free_audio_stream_buffer(ogg->audiostream); - /* if this was not the last block, buffer underrun */ - if (!last_block) { - return ALOGG_POLL_BUFFERUNDERRUN; - } - /* else we just finished playing, we need to wait for audio to stop */ - else { - ogg->wait_for_audio_stop = 2; - return ALOGG_OK; - } - } - - audiobuf_p += size_done; - } - - /* lock the buffer */ - free_audio_stream_buffer(ogg->audiostream); - - return ALOGG_OK; -} - - -void alogg_start_autopoll_oggstream(ALOGG_OGGSTREAM *ogg, int speed) { - /* return if we are already auto polling */ - if (ogg->auto_polling) - return; - - ogg->auto_polling = TRUE; - ogg->auto_poll_speed = speed; - - /* only install the interrupt if we are already playing */ - /* otherwise, play will do */ - if (alogg_is_playing_oggstream(ogg)) { - LOCK_FUNCTION(alogg_autopoll_oggstream); - install_param_int(&alogg_autopoll_oggstream, (void *)ogg, ogg->auto_poll_speed); - } -} - - -void alogg_stop_autopoll_oggstream(ALOGG_OGGSTREAM *ogg) { - /* return if we are already not auto polling */ - if (!ogg->auto_polling) - return; - - ogg->auto_polling = FALSE; - - /* only remove the interrupt if we were already playing */ - /* otherwise, stop will do*/ - if (alogg_is_playing_oggstream(ogg)) - remove_param_int(&alogg_autopoll_oggstream, (void *)ogg); -} - - -void *alogg_get_oggstream_buffer(ALOGG_OGGSTREAM *ogg) { - if (!ogg->unsel_databuf_free) - return NULL; - - /* if the last block was already passed, we don't need more data */ - if (ogg->bytes_used != -1) - return NULL; - - if (ogg->databuf_selector == 1) - return ogg->databuf2; - else - return ogg->databuf1; -} - - -void alogg_free_oggstream_buffer(ALOGG_OGGSTREAM *ogg, int bytes_used) { - if (ogg->unsel_databuf_free) { - ogg->unsel_databuf_free = FALSE; - ogg->bytes_used = bytes_used; - if (ogg->databuf_selector == 1) { - memcpy(ogg->full_databuf, ogg->databuf1, ogg->databuf_len); - memcpy(ogg->full_databuf + ogg->databuf_len, ogg->databuf2, ogg->databuf_len); - } - else { - memcpy(ogg->full_databuf, ogg->databuf2, ogg->databuf_len); - memcpy(ogg->full_databuf + ogg->databuf_len, ogg->databuf1, ogg->databuf_len); - } - } -} - - -int alogg_get_pos_msecs_oggstream(ALOGG_OGGSTREAM *ogg) { -#ifdef USE_TREMOR - return (int)(ov_time_tell(&(ogg->vf))); -#else - return (int)(ov_time_tell(&(ogg->vf)) * 1000); -#endif -} - - -int alogg_get_pos_secs_oggstream(ALOGG_OGGSTREAM *ogg) { -#ifdef USE_TREMOR - return (int)ov_time_tell(&(ogg->vf)) * 1000; -#else - return (int)ov_time_tell(&(ogg->vf)); -#endif -} - - -int alogg_get_pos_bytes_oggstream(ALOGG_OGGSTREAM *ogg) { - return ov_raw_tell(&(ogg->vf)); -} - - -int alogg_get_bitrate_oggstream(ALOGG_OGGSTREAM *ogg) { - return ov_bitrate(&(ogg->vf), -1); -} - - -int alogg_get_wave_bits_oggstream(ALOGG_OGGSTREAM *ogg) { - return 16; -} - - -int alogg_get_wave_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg) { - return ogg->stereo; -} - - -int alogg_get_wave_freq_oggstream(ALOGG_OGGSTREAM *ogg) { - return ogg->freq; -} - - -void alogg_adjust_oggstream(ALOGG_OGGSTREAM *ogg, int vol, int pan, int speed) { - /* return if we are not playing */ - if (!alogg_is_playing_oggstream(ogg)) - return; - - /* adjust the sample */ - adjust_sample(ogg->audiostream->samp, vol, pan, speed, TRUE); -} - - -void *alogg_get_output_wave_oggstream(ALOGG_OGGSTREAM *ogg, int *buffer_size) { - /* return if we are not playing */ - if (!alogg_is_playing_oggstream(ogg)) - return NULL; - - /* set the buffer_size */ - *buffer_size = ogg->audiostream_buffer_len; - - /* return the current audiostream sample data */ - return (ogg->audiostream->samp->data); -} - - -int alogg_is_playing_oggstream(ALOGG_OGGSTREAM *ogg) { - if (ogg->audiostream == NULL) - return FALSE; - else - return TRUE; -} - - -AUDIOSTREAM *alogg_get_audiostream_oggstream(ALOGG_OGGSTREAM *ogg) { - return ogg->audiostream; -} - -int alogg_is_end_of_oggstream(ALOGG_OGGSTREAM *ogg) { - return ogg->wait_for_audio_stop; -} - -int alogg_is_end_of_ogg(ALOGG_OGG *ogg) { - return ogg->wait_for_audio_stop; -} diff --git a/Engine/libsrc/alogg/alogg.h b/Engine/libsrc/alogg/alogg.h deleted file mode 100644 index 7d1e4abc1ed..00000000000 --- a/Engine/libsrc/alogg/alogg.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Allegro OGG */ -/* to play OGG files with Allegro */ - -/* OGG decoder part ofOgg Vorbis (Xiph.org Foundation) */ -/* Allegro OGG is copyright (c) 2002 Javier Gonz lez */ - -/* See COPYING.txt for license */ - - -#ifndef ALOGG_H -#define ALOGG_H - - -#include -#include - -#include "aloggdll.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* common define */ - -#define ALOGG_MAJOR_VERSION 1 -#define ALOGG_MINOR_VERSION 0 -#define ALOGG_SUB_VERSION 0 -#define ALOGG_VERSION_STR "1.0.0" -#define ALOGG_DATE_STR "23/08/2002" -#define ALOGG_DATE 20020823 /* yyyymmdd */ - -/* error codes */ - -#define ALOGG_OK 0 - -#define ALOGG_PLAY_BUFFERTOOSMALL -1 - -#define ALOGG_POLL_PLAYJUSTFINISHED 1 -#define ALOGG_POLL_NOTPLAYING -1 -#define ALOGG_POLL_FRAMECORRUPT -2 -#define ALOGG_POLL_BUFFERUNDERRUN -3 -#define ALOGG_POLL_INTERNALERROR -4 - - -/* API - OGG */ - -typedef struct ALOGG_OGG ALOGG_OGG; - - -ALOGG_DLL_DECLSPEC ALOGG_OGG *alogg_create_ogg_from_buffer(void *data, int data_len); -ALOGG_DLL_DECLSPEC ALOGG_OGG *alogg_create_ogg_from_file(FILE *f); -ALOGG_DLL_DECLSPEC void alogg_destroy_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_play_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan); -ALOGG_DLL_DECLSPEC int alogg_play_ex_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan, int speed, int loop); -ALOGG_DLL_DECLSPEC void alogg_stop_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC void alogg_adjust_ogg(ALOGG_OGG *ogg, int vol, int pan, int speed, int loop); - -ALOGG_DLL_DECLSPEC void alogg_rewind_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC void alogg_seek_abs_msecs_ogg(ALOGG_OGG *ogg, int msecs); -ALOGG_DLL_DECLSPEC void alogg_seek_abs_secs_ogg(ALOGG_OGG *ogg, int secs); -ALOGG_DLL_DECLSPEC void alogg_seek_abs_bytes_ogg(ALOGG_OGG *ogg, int bytes); -ALOGG_DLL_DECLSPEC void alogg_seek_rel_msecs_ogg(ALOGG_OGG *ogg, int msec); -ALOGG_DLL_DECLSPEC void alogg_seek_rel_secs_ogg(ALOGG_OGG *ogg, int sec); -ALOGG_DLL_DECLSPEC void alogg_seek_rel_bytes_ogg(ALOGG_OGG *ogg, int bytes); - -ALOGG_DLL_DECLSPEC int alogg_poll_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC void alogg_start_autopoll_ogg(ALOGG_OGG *ogg, int speed); -ALOGG_DLL_DECLSPEC void alogg_stop_autopoll_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_pos_msecs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_secs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_bytes_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_length_secs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_length_msecs_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_length_bytes_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_bitrate_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_is_stereo_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_bits_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_is_stereo_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_freq_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC SAMPLE *alogg_create_sample_from_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC void *aloggget_output_wave_ogg(ALOGG_OGG *ogg, int *buffer_size); - -ALOGG_DLL_DECLSPEC int alogg_is_playing_ogg(ALOGG_OGG *ogg); -ALOGG_DLL_DECLSPEC int alogg_is_looping_ogg(ALOGG_OGG *ogg); - -ALOGG_DLL_DECLSPEC AUDIOSTREAM *alogg_get_audiostream_ogg(ALOGG_OGG *ogg); - - - -/* API - OGGSTREAM */ - -typedef struct ALOGG_OGGSTREAM ALOGG_OGGSTREAM; - - -ALOGG_DLL_DECLSPEC ALOGG_OGGSTREAM *alogg_create_oggstream(void *first_data_buffer, int data_buffer_len, int last_block); -ALOGG_DLL_DECLSPEC ALOGG_OGGSTREAM *alogg_create_oggstream_ex(void *first_data_buffer, int data_buffer_len, int last_block, int downsample, int downmix); -ALOGG_DLL_DECLSPEC void alogg_destroy_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC int alogg_play_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan); -ALOGG_DLL_DECLSPEC int alogg_play_ex_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan, int speed); -ALOGG_DLL_DECLSPEC void alogg_stop_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC void alogg_adjust_oggstream(ALOGG_OGGSTREAM *ogg, int vol, int pan, int speed); - -ALOGG_DLL_DECLSPEC int alogg_poll_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC void alogg_start_autopoll_oggstream(ALOGG_OGGSTREAM *ogg, int speed); -ALOGG_DLL_DECLSPEC void alogg_stop_autopoll_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC void *alogg_get_oggstream_buffer(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC void alogg_free_oggstream_buffer(ALOGG_OGGSTREAM *ogg, int bytes_used); - -ALOGG_DLL_DECLSPEC int alogg_get_pos_msecs_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_secs_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_pos_bytes_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC int alogg_get_bitrate_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_bits_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); -ALOGG_DLL_DECLSPEC int alogg_get_wave_freq_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC void *alogg_get_output_wave_oggstream(ALOGG_OGGSTREAM *ogg, int *buffer_size); - -ALOGG_DLL_DECLSPEC int alogg_is_playing_oggstream(ALOGG_OGGSTREAM *ogg); - -ALOGG_DLL_DECLSPEC AUDIOSTREAM *alogg_get_audiostream_oggstream(ALOGG_OGGSTREAM *ogg); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/libsrc/alogg/aloggdll.h b/Engine/libsrc/alogg/aloggdll.h deleted file mode 100644 index 2a417de2297..00000000000 --- a/Engine/libsrc/alogg/aloggdll.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Allegro OGG */ -/* to play OGG files with Allegro */ - -/* OGG decoder part of Ogg Vorbis (Xiph.org Foundation) */ -/* Allegro OGG is copyright (c) 2002 Javier Gonz lez */ - -/* See COPYING.txt for license */ - - -#ifndef ALOGG_DLL_DECLSPEC -# ifdef ALOGG_DLL -# ifdef ALOGG_DLL_EXPORTS -# define ALOGG_DLL_DECLSPEC __declspec(dllexport) -# else -# define ALOGG_DLL_DECLSPEC __declspec(dllimport) -# endif -# else -# define ALOGG_DLL_DECLSPEC -# endif -#endif diff --git a/Engine/libsrc/dumb-0.9.2/CMakeLists.txt b/Engine/libsrc/dumb-0.9.2/CMakeLists.txt deleted file mode 100644 index 476908bf89e..00000000000 --- a/Engine/libsrc/dumb-0.9.2/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -add_library(aldumb) - -set_target_properties(aldumb PROPERTIES - C_STANDARD 11 - C_EXTENSIONS NO -) - -target_include_directories(aldumb PUBLIC include ) - -target_sources(aldumb - PRIVATE - allegro/alplay.c - allegro/datduh.c - allegro/datit.c - allegro/datmod.c - allegro/dats3m.c - allegro/datunld.c - allegro/datxm.c - allegro/packfile.c - core/atexit.c - core/duhlen.c - core/dumbfile.c - core/loadduh.c - core/makeduh.c - core/rawsig.c - core/readduh.c - core/register.c - core/rendduh.c - core/rendsig.c - core/unload.c - helpers/clickrem.c - helpers/memfile.c - helpers/resample.c - helpers/sampbuf.c - helpers/silence.c - helpers/stdfile.c - it/itload.c - it/itmisc.c - it/itorder.c - it/itread.c - it/itrender.c - it/itunload.c - it/loadmod.c - it/loads3m.c - it/loadxm.c - it/readmod.c - it/reads3m.c - it/readxm.c - it/xmeffect.c -) - -target_link_libraries(aldumb PUBLIC Allegro::Allegro ) - -add_library(AlDumb::AlDumb ALIAS aldumb) diff --git a/Engine/libsrc/dumb-0.9.2/allegro/alplay.c b/Engine/libsrc/dumb-0.9.2/allegro/alplay.c deleted file mode 100644 index 983bde105b2..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/alplay.c +++ /dev/null @@ -1,270 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * alplay.c - Functions to play a DUH through / / \ \ - * an Allegro audio stream. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include - -#include "aldumb.h" - - - -#define ADP_PLAYING 1 - -struct AL_DUH_PLAYER -{ - int flags; - long bufsize; - int freq; - AUDIOSTREAM *stream; - DUH_SIGRENDERER *sigrenderer; /* If this is NULL, stream is invalid. */ - float volume; - int silentcount; -}; - - - -AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq) -{ - AL_DUH_PLAYER *dp; - - /* This restriction is imposed by Allegro. */ - ASSERT(n_channels > 0); - ASSERT(n_channels <= 2); - - if (!duh) - return NULL; - - dp = malloc(sizeof(*dp)); - if (!dp) - return NULL; - - dp->flags = ADP_PLAYING; - dp->bufsize = bufsize; - dp->freq = freq; - - dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128); - - if (!dp->stream) { - free(dp); - return NULL; - } - - voice_set_priority(dp->stream->voice, 255); - - dp->sigrenderer = duh_start_sigrenderer(duh, 0, n_channels, pos); - - if (!dp->sigrenderer) { - stop_audio_stream(dp->stream); - free(dp); - return NULL; - } - - dp->volume = volume; - dp->silentcount = 0; - - return dp; -} - - - -void al_stop_duh(AL_DUH_PLAYER *dp) -{ - if (dp) { - if (dp->sigrenderer) { - duh_end_sigrenderer(dp->sigrenderer); - stop_audio_stream(dp->stream); - } - free(dp); - } -} - - - -void al_pause_duh(AL_DUH_PLAYER *dp) -{ - if (dp && dp->sigrenderer && (dp->flags & ADP_PLAYING)) { - voice_stop(dp->stream->voice); - dp->flags &= ~ADP_PLAYING; - } -} - - - -void al_resume_duh(AL_DUH_PLAYER *dp) -{ - if (dp && dp->sigrenderer && !(dp->flags & ADP_PLAYING)) { - voice_start(dp->stream->voice); - dp->flags |= ADP_PLAYING; - } -} - - - -void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority) -{ - if (dp && dp->sigrenderer) - voice_set_priority(dp->stream->voice, priority); -} - - - -void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume) -{ - if (dp) - dp->volume = volume; -} - - - -int al_poll_duh(AL_DUH_PLAYER *dp) -{ - unsigned short *sptr; - long n; - long size; - int n_channels; - - if (!dp || !dp->sigrenderer) - return 1; - - if (!(dp->flags & ADP_PLAYING)) - return 0; - - sptr = get_audio_stream_buffer(dp->stream); - - if (!sptr) - return 0; - - n = duh_render(dp->sigrenderer, 16, 1, dp->volume, 65536.0 / dp->freq, dp->bufsize, sptr); - - if (n == 0) { - if (++dp->silentcount >= 2) { - duh_end_sigrenderer(dp->sigrenderer); - free_audio_stream_buffer(dp->stream); - stop_audio_stream(dp->stream); - dp->sigrenderer = NULL; - return 1; - } - } - - n_channels = duh_sigrenderer_get_n_channels(dp->sigrenderer); - n *= n_channels; - size = dp->bufsize * n_channels; - for (; n < size; n++) - sptr[n] = 0x8000; - - free_audio_stream_buffer(dp->stream); - - return 0; -} - - - -long al_duh_get_position(AL_DUH_PLAYER *dp) -{ - return dp ? duh_sigrenderer_get_position(dp->sigrenderer) : -1; -} - - - -AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq) -{ - AL_DUH_PLAYER *dp; - int n_channels; - - if (!sigrenderer) - return NULL; - - dp = malloc(sizeof(*dp)); - if (!dp) - return NULL; - - n_channels = duh_sigrenderer_get_n_channels(sigrenderer); - - /* This restriction is imposed by Allegro. */ - ASSERT(n_channels > 0); - ASSERT(n_channels <= 2); - - dp->flags = ADP_PLAYING; - dp->bufsize = bufsize; - dp->freq = freq; - - dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128); - - if (!dp->stream) { - free(dp); - return NULL; - } - - voice_set_priority(dp->stream->voice, 255); - - dp->sigrenderer = sigrenderer; - - dp->volume = volume; - dp->silentcount = 0; - - return dp; -} - - - -DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp) -{ - return dp ? dp->sigrenderer : NULL; -} - - - -/* IMPORTANT: This function will return NULL if the music has ended. */ -// Should this be changed? User might want to hack the underlying SIGRENDERER -// and resurrect it (e.g. change pattern number), before it gets destroyed... -DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp) -{ - if (dp) { - DUH_SIGRENDERER *sigrenderer = dp->sigrenderer; - if (sigrenderer) stop_audio_stream(dp->stream); - free(dp); - return sigrenderer; - } - return NULL; -} - - - -/* DEPRECATED */ -AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq) -{ - return al_duh_encapsulate_sigrenderer(dr, volume, bufsize, freq); -} - - - -/* DEPRECATED */ -DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp) -{ - return al_duh_get_sigrenderer(dp); -} - - - -/* DEPRECATED */ -DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp) -{ - return al_duh_decompose_to_sigrenderer(dp); -} diff --git a/Engine/libsrc/dumb-0.9.2/allegro/datduh.c b/Engine/libsrc/dumb-0.9.2/allegro/datduh.c deleted file mode 100644 index 672e3c820cf..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/datduh.c +++ /dev/null @@ -1,60 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * datduh.c - Integration with Allegro's / / \ \ - * datafiles. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "aldumb.h" -#include "internal/aldumb.h" - - - -static void *dat_read_duh(PACKFILE *f, long size) -{ - DUMBFILE *df; - DUH *duh; - - (void)size; - - df = dumbfile_open_packfile(f); - - if (!df) - return NULL; - - duh = read_duh(df); - - dumbfile_close(df); - - return duh; -} - - - -/* dumb_register_dat_duh(): tells Allegro about the DUH datafile object. If - * you intend to load a datafile containing a DUH object, you must call this - * function first. It is recommended you pass DAT_DUH, but you may have a - * reason to use a different type (apart from pride, that doesn't count). - */ -void dumb_register_dat_duh(long type) -{ - register_datafile_object( - type, - &dat_read_duh, - &_dat_unload_duh - ); -} diff --git a/Engine/libsrc/dumb-0.9.2/allegro/datit.c b/Engine/libsrc/dumb-0.9.2/allegro/datit.c deleted file mode 100644 index 8f58f14234e..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/datit.c +++ /dev/null @@ -1,62 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * datit.c - Integration of IT files with / / \ \ - * Allegro's datafiles. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "aldumb.h" -#include "internal/aldumb.h" - - - -static void *dat_read_it(PACKFILE *f, long size) -{ - DUMBFILE *df; - DUH *duh; - - (void)size; - - df = dumbfile_open_packfile(f); - - if (!df) - return NULL; - - duh = dumb_read_it(df); - - dumbfile_close(df); - - return duh; -} - - - -/* dumb_register_dat_it(): tells Allegro about the IT datafile object. If you - * intend to load a datafile containing an IT object, you must call this - * function first. It is recommended you pass DUMB_DAT_IT, but you may have a - * reason to use a different type (perhaps you already have a datafile with - * IT files in and they use a different type). - */ -void dumb_register_dat_it(long type) -{ - register_datafile_object( - type, - &dat_read_it, - &_dat_unload_duh - ); -} - diff --git a/Engine/libsrc/dumb-0.9.2/allegro/datmod.c b/Engine/libsrc/dumb-0.9.2/allegro/datmod.c deleted file mode 100644 index 850b17b4446..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/datmod.c +++ /dev/null @@ -1,61 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * datmod.c - Integration of MOD files with / / \ \ - * Allegro's datafiles. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "aldumb.h" -#include "internal/aldumb.h" - - - -static void *dat_read_mod(PACKFILE *f, long size) -{ - DUMBFILE *df; - DUH *duh; - - (void)size; - - df = dumbfile_open_packfile(f); - - if (!df) - return NULL; - - duh = dumb_read_mod(df); - - dumbfile_close(df); - - return duh; -} - - - -/* dumb_register_dat_mod(): tells Allegro about the MOD datafile object. If - * you intend to load a datafile containing a MOD object, you must call this - * function first. It is recommended you pass DUMB_DAT_MOD, but you may have - * a reason to use a different type (perhaps you already have a datafile with - * MOD files in and they use a different type). - */ -void dumb_register_dat_mod(long type) -{ - register_datafile_object( - type, - &dat_read_mod, - &_dat_unload_duh - ); -} diff --git a/Engine/libsrc/dumb-0.9.2/allegro/dats3m.c b/Engine/libsrc/dumb-0.9.2/allegro/dats3m.c deleted file mode 100644 index a0fc74420ea..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/dats3m.c +++ /dev/null @@ -1,61 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * dats3m.c - Integration of S3M files with / / \ \ - * Allegro's datafiles. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "aldumb.h" -#include "internal/aldumb.h" - - - -static void *dat_read_s3m(PACKFILE *f, long size) -{ - DUMBFILE *df; - DUH *duh; - - (void)size; - - df = dumbfile_open_packfile(f); - - if (!df) - return NULL; - - duh = dumb_read_s3m(df); - - dumbfile_close(df); - - return duh; -} - - - -/* dumb_register_dat_s3m(): tells Allegro about the S3M datafile object. If - * you intend to load a datafile containing an S3M object, you must call this - * function first. It is recommended you pass DUMB_DAT_S3M, but you may have - * a reason to use a different type (perhaps you already have a datafile with - * S3M files in and they use a different type). - */ -void dumb_register_dat_s3m(long type) -{ - register_datafile_object( - type, - &dat_read_s3m, - &_dat_unload_duh - ); -} diff --git a/Engine/libsrc/dumb-0.9.2/allegro/datunld.c b/Engine/libsrc/dumb-0.9.2/allegro/datunld.c deleted file mode 100644 index 71906445e05..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/datunld.c +++ /dev/null @@ -1,31 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * datunld.c - Unload function for integration / / \ \ - * with Allegro's datafiles. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "aldumb.h" -#include "internal/aldumb.h" - - - -void _dat_unload_duh(void *duh) -{ - unload_duh(duh); -} - diff --git a/Engine/libsrc/dumb-0.9.2/allegro/datxm.c b/Engine/libsrc/dumb-0.9.2/allegro/datxm.c deleted file mode 100644 index 6cb98d87c1d..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/datxm.c +++ /dev/null @@ -1,62 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * datxm.c - Integration of XM files with / / \ \ - * Allegro's datafiles. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "aldumb.h" -#include "internal/aldumb.h" - - - -static void *dat_read_xm(PACKFILE *f, long size) -{ - DUMBFILE *df; - DUH *duh; - - (void)size; - - df = dumbfile_open_packfile(f); - - if (!df) - return NULL; - - duh = dumb_read_xm(df); - - dumbfile_close(df); - - return duh; -} - - - -/* dumb_register_dat_xm(): tells Allegro about the XM datafile object. If you - * intend to load a datafile containing an XM object, you must call this - * function first. It is recommended you pass DUMB_DAT_XM, but you may have a - * reason to use a different type (perhaps you already have a datafile with - * XM files in and they use a different type). - */ -void dumb_register_dat_xm(long type) -{ - register_datafile_object( - type, - &dat_read_xm, - &_dat_unload_duh - ); -} - diff --git a/Engine/libsrc/dumb-0.9.2/allegro/packfile.c b/Engine/libsrc/dumb-0.9.2/allegro/packfile.c deleted file mode 100644 index 525baebd4ec..00000000000 --- a/Engine/libsrc/dumb-0.9.2/allegro/packfile.c +++ /dev/null @@ -1,98 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * packfile.c - Packfile input module. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * Note that this does not use file compression; | \ / / - * for that you must open the file yourself and | ' / - * then use dumbfile_open_packfile(). \__/ - */ - -#include - -#include "aldumb.h" - - - -static void *dumb_packfile_open(const char *filename) -{ - return pack_fopen(filename, F_READ); -} - - - -static int dumb_packfile_skip(void *f, long n) -{ - return pack_fseek(f, n); -} - - - -static int dumb_packfile_getc(void *f) -{ - return pack_getc(f); -} - - - -static long dumb_packfile_getnc(char *ptr, long n, void *f) -{ - return pack_fread(ptr, n, f); -} - - - -static void dumb_packfile_close(void *f) -{ - pack_fclose(f); -} - - - -static DUMBFILE_SYSTEM packfile_dfs = { - &dumb_packfile_open, - &dumb_packfile_skip, - &dumb_packfile_getc, - &dumb_packfile_getnc, - &dumb_packfile_close -}; - - - -void dumb_register_packfiles(void) -{ - register_dumbfile_system(&packfile_dfs); -} - - - -static DUMBFILE_SYSTEM packfile_dfs_leave_open = { - NULL, - &dumb_packfile_skip, - &dumb_packfile_getc, - &dumb_packfile_getnc, - NULL -}; - - - -DUMBFILE *dumbfile_open_packfile(PACKFILE *p) -{ - return dumbfile_open_ex(p, &packfile_dfs_leave_open); -} - - - -DUMBFILE *dumbfile_from_packfile(PACKFILE *p) -{ - return p ? dumbfile_open_ex(p, &packfile_dfs) : NULL; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/atexit.c b/Engine/libsrc/dumb-0.9.2/core/atexit.c deleted file mode 100644 index 16c6abdb2c1..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/atexit.c +++ /dev/null @@ -1,71 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * atexit.c - Library Clean-up Management. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -typedef struct DUMB_ATEXIT_PROC -{ - struct DUMB_ATEXIT_PROC *next; - void (*proc)(void); -} -DUMB_ATEXIT_PROC; - - - -static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL; - - - -int dumb_atexit(void (*proc)(void)) -{ - DUMB_ATEXIT_PROC *dap = dumb_atexit_proc; - - while (dap) { - if (dap->proc == proc) return 0; - dap = dap->next; - } - - dap = malloc(sizeof(*dap)); - - if (!dap) - return -1; - - dap->next = dumb_atexit_proc; - dap->proc = proc; - dumb_atexit_proc = dap; - - return 0; -} - - - -void dumb_exit(void) -{ - while (dumb_atexit_proc) { - DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next; - (*dumb_atexit_proc->proc)(); - free(dumb_atexit_proc); - dumb_atexit_proc = next; - } -} diff --git a/Engine/libsrc/dumb-0.9.2/core/duhlen.c b/Engine/libsrc/dumb-0.9.2/core/duhlen.c deleted file mode 100644 index 4500d0a50f3..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/duhlen.c +++ /dev/null @@ -1,34 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * duhlen.c - Function to return the length of / / \ \ - * a DUH. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * Note that the length of a DUH is a constant | ' / - * stored in the DUH struct and in the DUH disk \__/ - * format. It will be calculated on loading for - * other formats in which the length is not explicitly stored. Also note that - * it does not necessarily correspond to the length of time for which the DUH - * will generate samples. Rather it represents a suitable point for a player - * such as Winamp to stop, and in any good DUH it will allow for any final - * flourish to fade out and be appreciated. - */ - -#include "dumb.h" -#include "internal/dumb.h" - - - -long duh_get_length(DUH *duh) -{ - return duh ? duh->length : 0; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/dumbfile.c b/Engine/libsrc/dumb-0.9.2/core/dumbfile.c deleted file mode 100644 index 71108c0c3b5..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/dumbfile.c +++ /dev/null @@ -1,401 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * dumbfile.c - Hookable, strictly sequential / / \ \ - * file input functions. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" - - - -static DUMBFILE_SYSTEM *the_dfs = NULL; - - - -void register_dumbfile_system(DUMBFILE_SYSTEM *dfs) -{ - ASSERT(dfs); - ASSERT(dfs->open); - ASSERT(dfs->getc); - ASSERT(dfs->close); - the_dfs = dfs; -} - - - -struct DUMBFILE -{ - DUMBFILE_SYSTEM *dfs; - void *file; - long pos; -}; - - - -DUMBFILE *dumbfile_open(const char *filename) -{ - DUMBFILE *f; - - ASSERT(the_dfs); - - f = malloc(sizeof(*f)); - - if (!f) - return NULL; - - f->dfs = the_dfs; - - f->file = (*the_dfs->open)(filename); - - if (!f->file) { - free(f); - return NULL; - } - - f->pos = 0; - - return f; -} - - - -DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs) -{ - DUMBFILE *f; - - ASSERT(dfs); - ASSERT(dfs->getc); - ASSERT(file); - - f = malloc(sizeof(*f)); - - if (!f) { - if (dfs->close) - (*dfs->close)(file); - return NULL; - } - - f->dfs = dfs; - f->file = file; - - f->pos = 0; - - return f; -} - - - -long dumbfile_pos(DUMBFILE *f) -{ - ASSERT(f); - - return f->pos; -} - - - -int dumbfile_skip(DUMBFILE *f, long n) -{ - int rv; - - ASSERT(f); - ASSERT(n >= 0); - - if (f->pos < 0) - return -1; - - f->pos += n; - - if (f->dfs->skip) { - rv = (*f->dfs->skip)(f->file, n); - if (rv) { - f->pos = -1; - return rv; - } - } else { - while (n) { - rv = (*f->dfs->getc)(f->file); - if (rv < 0) { - f->pos = -1; - return rv; - } - n--; - } - } - - return 0; -} - - - -int dumbfile_getc(DUMBFILE *f) -{ - int rv; - - ASSERT(f); - - if (f->pos < 0) - return -1; - - rv = (*f->dfs->getc)(f->file); - - if (rv < 0) { - f->pos = -1; - return rv; - } - - f->pos++; - - return rv; -} - - - -int dumbfile_igetw(DUMBFILE *f) -{ - int l, h; - - ASSERT(f); - - if (f->pos < 0) - return -1; - - l = (*f->dfs->getc)(f->file); - if (l < 0) { - f->pos = -1; - return l; - } - - h = (*f->dfs->getc)(f->file); - if (h < 0) { - f->pos = -1; - return h; - } - - f->pos += 2; - - return l | (h << 8); -} - - - -int dumbfile_mgetw(DUMBFILE *f) -{ - int l, h; - - ASSERT(f); - - if (f->pos < 0) - return -1; - - h = (*f->dfs->getc)(f->file); - if (h < 0) { - f->pos = -1; - return h; - } - - l = (*f->dfs->getc)(f->file); - if (l < 0) { - f->pos = -1; - return l; - } - - f->pos += 2; - - return l | (h << 8); -} - - - -long dumbfile_igetl(DUMBFILE *f) -{ - unsigned long rv, b; - - ASSERT(f); - - if (f->pos < 0) - return -1; - - rv = (*f->dfs->getc)(f->file); - if ((signed long)rv < 0) { - f->pos = -1; - return rv; - } - - b = (*f->dfs->getc)(f->file); - if ((signed long)b < 0) { - f->pos = -1; - return b; - } - rv |= b << 8; - - b = (*f->dfs->getc)(f->file); - if ((signed long)b < 0) { - f->pos = -1; - return b; - } - rv |= b << 16; - - b = (*f->dfs->getc)(f->file); - if ((signed long)b < 0) { - f->pos = -1; - return b; - } - rv |= b << 24; - - f->pos += 4; - - return rv; -} - - - -long dumbfile_mgetl(DUMBFILE *f) -{ - unsigned long rv, b; - - ASSERT(f); - - if (f->pos < 0) - return -1; - - rv = (*f->dfs->getc)(f->file); - if ((signed long)rv < 0) { - f->pos = -1; - return rv; - } - rv <<= 24; - - b = (*f->dfs->getc)(f->file); - if ((signed long)b < 0) { - f->pos = -1; - return b; - } - rv |= b << 16; - - b = (*f->dfs->getc)(f->file); - if ((signed long)b < 0) { - f->pos = -1; - return b; - } - rv |= b << 8; - - b = (*f->dfs->getc)(f->file); - if ((signed long)b < 0) { - f->pos = -1; - return b; - } - rv |= b; - - f->pos += 4; - - return rv; -} - - - -unsigned long dumbfile_cgetul(DUMBFILE *f) -{ - unsigned long rv = 0; - int v; - - do { - v = dumbfile_getc(f); - - if (v < 0) - return v; - - rv <<= 7; - rv |= v & 0x7F; - } while (v & 0x80); - - return rv; -} - - - -signed long dumbfile_cgetsl(DUMBFILE *f) -{ - unsigned long rv = dumbfile_cgetul(f); - - if (f->pos < 0) - return rv; - - return (rv >> 1) | (rv << 31); -} - - - -long dumbfile_getnc(char *ptr, long n, DUMBFILE *f) -{ - long rv; - - ASSERT(f); - ASSERT(n >= 0); - - if (f->pos < 0) - return -1; - - if (f->dfs->getnc) { - rv = (*f->dfs->getnc)(ptr, n, f->file); - if (rv < n) { - f->pos = -1; - return MAX(rv, 0); - } - } else { - for (rv = 0; rv < n; rv++) { - int c = (*f->dfs->getc)(f->file); - if (c < 0) { - f->pos = -1; - return rv; - } - *ptr++ = c; - } - } - - f->pos += rv; - - return rv; -} - - - -int dumbfile_error(DUMBFILE *f) -{ - ASSERT(f); - - return f->pos < 0; -} - - - -int dumbfile_close(DUMBFILE *f) -{ - int rv; - - ASSERT(f); - - rv = f->pos < 0; - - if (f->dfs->close) - (*f->dfs->close)(f->file); - - free(f); - - return rv; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/loadduh.c b/Engine/libsrc/dumb-0.9.2/core/loadduh.c deleted file mode 100644 index 7dfe5cc100c..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/loadduh.c +++ /dev/null @@ -1,42 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * loadduh.c - Code to read a DUH from a file, / / \ \ - * opening and closing the file for | < / \_ - * you. | \/ /\ / - * \_ / > / - * By entheh. | \ / / - * | ' / - * \__/ - */ - -#include "dumb.h" -#include "internal/dumb.h" - - - -/* load_duh(): loads a .duh file, returning a pointer to a DUH struct. - * When you have finished with it, you must pass the pointer to unload_duh() - * so that the memory can be freed. - */ -DUH *load_duh(const char *filename) -{ - DUH *duh; - DUMBFILE *f = dumbfile_open(filename); - - if (!f) - return NULL; - - duh = read_duh(f); - - dumbfile_close(f); - - return duh; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/makeduh.c b/Engine/libsrc/dumb-0.9.2/core/makeduh.c deleted file mode 100644 index 1e422fb502c..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/makeduh.c +++ /dev/null @@ -1,92 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * makeduh.c - Function to construct a DUH from / / \ \ - * its components. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata) -{ - DUH_SIGNAL *signal; - - ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer)); - ASSERT(desc->sigrenderer_get_samples && desc->sigrenderer_get_current_sample); - - signal = malloc(sizeof(*signal)); - - if (!signal) { - if (desc->unload_sigdata) - if (sigdata) - (*desc->unload_sigdata)(sigdata); - return NULL; - } - - signal->desc = desc; - signal->sigdata = sigdata; - - return signal; -} - - - -DUH *make_duh(long length, int n_signals, DUH_SIGTYPE_DESC *desc[], sigdata_t *sigdata[]) -{ - DUH *duh = malloc(sizeof(*duh)); - int i; - int fail; - - if (duh) { - duh->n_signals = n_signals; - - duh->signal = malloc(n_signals * sizeof(*duh->signal)); - - if (!duh->signal) { - free(duh); - duh = NULL; - } - } - - if (!duh) { - for (i = 0; i < n_signals; i++) - if (desc[i]->unload_sigdata) - if (sigdata[i]) - (*desc[i]->unload_sigdata)(sigdata[i]); - return NULL; - } - - fail = 0; - - for (i = 0; i < n_signals; i++) { - duh->signal[i] = make_signal(desc[i], sigdata[i]); - if (!duh->signal[i]) - fail = 1; - } - - if (fail) { - unload_duh(duh); - return NULL; - } - - duh->length = length; - - return duh; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/rawsig.c b/Engine/libsrc/dumb-0.9.2/core/rawsig.c deleted file mode 100644 index 926c990655d..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/rawsig.c +++ /dev/null @@ -1,44 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * rawsig.c - Function to retrieve raw signal / / \ \ - * data from a DUH provided you know | < / \_ - * what type of signal it is. | \/ /\ / - * \_ / > / - * By entheh. | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -/* You have to specify the type of sigdata, proving you know what to do with - * the pointer. If you get it wrong, you can expect NULL back. - */ -sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type) -{ - DUH_SIGNAL *signal; - - if (!duh) return NULL; - - if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL; - - signal = duh->signal[sig]; - - if (signal && signal->desc->type == type) - return signal->sigdata; - - return NULL; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/readduh.c b/Engine/libsrc/dumb-0.9.2/core/readduh.c deleted file mode 100644 index 514b04a0774..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/readduh.c +++ /dev/null @@ -1,107 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * readduh.c - Code to read a DUH from an open / / \ \ - * file. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f) -{ - DUH_SIGNAL *signal; - long type; - - signal = malloc(sizeof(*signal)); - - if (!signal) - return NULL; - - type = dumbfile_mgetl(f); - if (dumbfile_error(f)) { - free(signal); - return NULL; - } - - signal->desc = _dumb_get_sigtype_desc(type); - if (!signal->desc) { - free(signal); - return NULL; - } - - if (signal->desc->load_sigdata) { - signal->sigdata = (*signal->desc->load_sigdata)(duh, f); - if (!signal->sigdata) { - free(signal); - return NULL; - } - } else - signal->sigdata = NULL; - - return signal; -} - - - -/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its - * pointer, or null on error. The file is not closed. - */ -DUH *read_duh(DUMBFILE *f) -{ - DUH *duh; - int i; - - if (dumbfile_mgetl(f) != DUH_SIGNATURE) - return NULL; - - duh = malloc(sizeof(*duh)); - if (!duh) - return NULL; - - duh->length = dumbfile_igetl(f); - if (dumbfile_error(f) || duh->length <= 0) { - free(duh); - return NULL; - } - - duh->n_signals = dumbfile_igetl(f); - if (dumbfile_error(f) || duh->n_signals <= 0) { - free(duh); - return NULL; - } - - duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals); - if (!duh->signal) { - free(duh); - return NULL; - } - - for (i = 0; i < duh->n_signals; i++) - duh->signal[i] = NULL; - - for (i = 0; i < duh->n_signals; i++) { - if (!(duh->signal[i] = read_signal(duh, f))) { - unload_duh(duh); - return NULL; - } - } - - return duh; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/register.c b/Engine/libsrc/dumb-0.9.2/core/register.c deleted file mode 100644 index 9eed45f796e..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/register.c +++ /dev/null @@ -1,104 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * register.c - Signal type registration. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL; -static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc; - - - -/* destroy_sigtypes(): frees all memory allocated while registering signal - * types. This function is set up to be called by dumb_exit(). - */ -static void destroy_sigtypes(void) -{ - DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next; - sigtype_desc = NULL; - sigtype_desc_tail = &sigtype_desc; - - while (desc_link) { - next = desc_link->next; - free(desc_link); - desc_link = next; - } -} - - - -/* dumb_register_sigtype(): registers a new signal type with DUMB. The signal - * type is identified by a four-character string (e.g. "WAVE"), which you can - * encode using the the DUMB_ID() macro (e.g. DUMB_ID('W','A','V','E')). The - * signal's behaviour is defined by four functions, whose pointers you pass - * here. See the documentation for details. - * - * If a DUH tries to use a signal that has not been registered using this - * function, then the library will fail to load the DUH. - */ -void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc) -{ - DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc; - - ASSERT((desc->load_sigdata && desc->unload_sigdata) || (!desc->load_sigdata && !desc->unload_sigdata)); - ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer)); - ASSERT(desc->sigrenderer_get_samples && desc->sigrenderer_get_current_sample); - - if (desc_link) { - do { - if (desc_link->desc->type == desc->type) { - desc_link->desc = desc; - return; - } - desc_link = desc_link->next; - } while (desc_link); - } else - dumb_atexit(&destroy_sigtypes); - - desc_link = *sigtype_desc_tail = malloc(sizeof(DUH_SIGTYPE_DESC_LINK)); - - if (!desc_link) - return; - - desc_link->next = NULL; - sigtype_desc_tail = &desc_link->next; - - desc_link->desc = desc; -} - - - -/* _dumb_get_sigtype_desc(): searches the registered functions for a signal - * type matching the parameter. If such a sigtype is found, it returns a - * pointer to a sigtype descriptor containing the necessary functions to - * manage the signal. If none is found, it returns NULL. - */ -DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type) -{ - DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc; - - while (desc_link && desc_link->desc->type != type) - desc_link = desc_link->next; - - return desc_link->desc; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/rendduh.c b/Engine/libsrc/dumb-0.9.2/core/rendduh.c deleted file mode 100644 index 39db8ab8a38..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/rendduh.c +++ /dev/null @@ -1,202 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * rendduh.c - Functions for rendering a DUH into / / \ \ - * an end-user sample format. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -/* On the x86, we can use some tricks to speed stuff up */ -#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__) -// Can't we detect Linux and other x86 platforms here? :/ - -#define FAST_MID(var, min, max) { \ - var -= (min); \ - var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \ - var += (min); \ - var -= (max); \ - var &= var >> (sizeof(var) * CHAR_BIT - 1); \ - var += (max); \ -} - -#define CONVERT8(src, pos, signconv) { \ - signed int f = (src + 0x8000) >> 16; \ - FAST_MID(f, -128, 127); \ - ((char*)sptr)[pos] = (char)f ^ signconv; \ -} - -#define CONVERT16(src, pos, signconv) { \ - signed int f = (src + 0x80) >> 8; \ - FAST_MID(f, -32768, 32767); \ - ((short*)sptr)[pos] = (short)(f ^ signconv); \ -} - -#else - -#define CONVERT8(src, pos, signconv) \ -{ \ - signed int f = (src + 0x8000) >> 16; \ - f = MID(-128, f, 127); \ - ((char *)sptr)[pos] = (char)f ^ signconv; \ -} - - - -#define CONVERT16(src, pos, signconv) \ -{ \ - signed int f = (src + 0x80) >> 8; \ - f = MID(-32768, f, 32767); \ - ((short *)sptr)[pos] = (short)(f ^ signconv); \ -} - -#endif - - - -/* DEPRECATED */ -DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) -{ - return duh_start_sigrenderer(duh, 0, n_channels, pos); -} - - - -long duh_render( - DUH_SIGRENDERER *sigrenderer, - int bits, int unsign, - float volume, float delta, - long size, void *sptr -) -{ - long n; - - sample_t **sampptr; - - int n_channels; - - ASSERT(bits == 8 || bits == 16); - ASSERT(sptr); - - if (!sigrenderer) - return 0; - - n_channels = duh_sigrenderer_get_n_channels(sigrenderer); - - ASSERT(n_channels > 0); - /* This restriction will be removed when need be. At the moment, tightly - * optimised loops exist for exactly one or two channels. - */ - ASSERT(n_channels <= 2); - - sampptr = create_sample_buffer(n_channels, size); - - if (!sampptr) - return 0; - - dumb_silence(sampptr[0], n_channels * size); - - size = duh_sigrenderer_get_samples(sigrenderer, volume, delta, size, sampptr); - - if (bits == 16) { - int signconv = unsign ? 0x8000 : 0x0000; - - if (n_channels == 2) { - for (n = 0; n < size; n++) { - CONVERT16(sampptr[0][n], n << 1, signconv); - } - for (n = 0; n < size; n++) { - CONVERT16(sampptr[1][n], (n << 1) + 1, signconv); - } - } else { - for (n = 0; n < size; n++) { - CONVERT16(sampptr[0][n], n, signconv); - } - } - } else { - char signconv = unsign ? 0x80 : 0x00; - - if (n_channels == 2) { - for (n = 0; n < size; n++) { - CONVERT8(sampptr[0][n], n << 1, signconv); - } - for (n = 0; n < size; n++) { - CONVERT8(sampptr[1][n], (n << 1) + 1, signconv); - } - } else { - for (n = 0; n < size; n++) { - CONVERT8(sampptr[0][n], n, signconv); - } - } - } - - destroy_sample_buffer(sampptr); - - return size; -} - - - -/* DEPRECATED */ -int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) -{ - return duh_sigrenderer_get_n_channels(dr); -} - - - -/* DEPRECATED */ -long duh_renderer_get_position(DUH_SIGRENDERER *dr) -{ - return duh_sigrenderer_get_position(dr); -} - - - -/* DEPRECATED */ -void duh_end_renderer(DUH_SIGRENDERER *dr) -{ - duh_end_sigrenderer(dr); -} - - - -/* DEPRECATED */ -DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) -{ - return sigrenderer; -} - - - -/* DEPRECATED */ -DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) -{ - return dr; -} - - - -/* DEPRECATED */ -DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) -{ - return dr; -} diff --git a/Engine/libsrc/dumb-0.9.2/core/rendsig.c b/Engine/libsrc/dumb-0.9.2/core/rendsig.c deleted file mode 100644 index 577a402c286..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/rendsig.c +++ /dev/null @@ -1,298 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * rendsig.c - Wrappers to render samples from / / \ \ - * the signals in a DUH. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ -#define DUMB_DECLARE_DEPRECATED -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -struct DUH_SIGRENDERER -{ - DUH_SIGTYPE_DESC *desc; - - sigrenderer_t *sigrenderer; - - int n_channels; - - long pos; - int subpos; - - DUH_SIGRENDERER_ANALYSER_CALLBACK callback; - void *callback_data; -}; - - - -DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos) -{ - DUH_SIGRENDERER *sigrenderer; - - DUH_SIGNAL *signal; - DUH_START_SIGRENDERER proc; - - if ((unsigned int)sig >= (unsigned int)duh->n_signals) - return NULL; - - signal = duh->signal[sig]; - if (!signal) - return NULL; - - sigrenderer = malloc(sizeof(*sigrenderer)); - if (!sigrenderer) - return NULL; - - sigrenderer->desc = signal->desc; - - proc = sigrenderer->desc->start_sigrenderer; - - if (proc) { - duh->signal[sig] = NULL; - sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos); - duh->signal[sig] = signal; - - if (!sigrenderer->sigrenderer) { - free(sigrenderer); - return NULL; - } - } else - sigrenderer->sigrenderer = NULL; - - sigrenderer->n_channels = n_channels; - - sigrenderer->pos = pos; - sigrenderer->subpos = 0; - - sigrenderer->callback = NULL; - - return sigrenderer; -} - - - -#include -void duh_sigrenderer_set_callback( - DUH_SIGRENDERER *sigrenderer, - DUH_SIGRENDERER_CALLBACK callback, void *data -) -{ - (void)sigrenderer; - (void)callback; - (void)data; - fprintf(stderr, - "Call to deprecated function duh_sigrenderer_set_callback(). The callback\n" - "was not installed. See dumb/docs/deprec.txt for how to fix this.\n"); -} - - - -void duh_sigrenderer_set_analyser_callback( - DUH_SIGRENDERER *sigrenderer, - DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data -) -{ - if (sigrenderer) { - sigrenderer->callback = callback; - sigrenderer->callback_data = data; - } -} - - - -int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer) -{ - return sigrenderer ? sigrenderer->n_channels : 0; -} - - - -long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer) -{ - return sigrenderer ? sigrenderer->pos : -1; -} - - - -void duh_sigrenderer_set_sigparam( - DUH_SIGRENDERER *sigrenderer, - unsigned char id, long value -) -{ - DUH_SIGRENDERER_SET_SIGPARAM proc; - - if (!sigrenderer) return; - - proc = sigrenderer->desc->sigrenderer_set_sigparam; - if (proc) - (*proc)(sigrenderer->sigrenderer, id, value); - else - TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n", - (int)id, - value, - (int)(sigrenderer->desc->type >> 24), - (int)(sigrenderer->desc->type >> 16), - (int)(sigrenderer->desc->type >> 8), - (int)(sigrenderer->desc->type)); -} - - - -long duh_sigrenderer_get_samples( - DUH_SIGRENDERER *sigrenderer, - float volume, float delta, - long size, sample_t **samples -) -{ - long rendered; - LONG_LONG t; - - if (!sigrenderer) return 0; - - rendered = (*sigrenderer->desc->sigrenderer_get_samples) - (sigrenderer->sigrenderer, volume, delta, size, samples); - - if (rendered) { - if (sigrenderer->callback) - (*sigrenderer->callback)(sigrenderer->callback_data, - (const sample_t *const *)samples, sigrenderer->n_channels, rendered); - - t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered; - - sigrenderer->pos += (long)(t >> 16); - sigrenderer->subpos = (int)t & 65535; - } - - return rendered; -} - - - -/* DEPRECATED */ -long duh_render_signal( - DUH_SIGRENDERER *sigrenderer, - float volume, float delta, - long size, sample_t **samples -) -{ - sample_t **s = create_sample_buffer(sigrenderer->n_channels, size); - long rendered; - long i; - int j; - if (!s) return 0; - rendered = duh_sigrenderer_get_samples(sigrenderer, volume, delta, size, s); - for (j = 0; j < sigrenderer->n_channels; j++) - for (i = 0; i < rendered; i++) - samples[j][i] += s[j][i] >> 8; - destroy_sample_buffer(s); - return rendered; -} - - - -void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples) -{ - if (sigrenderer) - (*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples); -} - - - -void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer) -{ - if (sigrenderer) { - if (sigrenderer->desc->end_sigrenderer) - if (sigrenderer->sigrenderer) - (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer); - - free(sigrenderer); - } -} - - - -DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos) -{ - DUH_SIGRENDERER *sigrenderer; - - if (desc->start_sigrenderer && !vsigrenderer) return NULL; - - sigrenderer = malloc(sizeof(*sigrenderer)); - if (!sigrenderer) { - if (desc->end_sigrenderer) - if (vsigrenderer) - (*desc->end_sigrenderer)(vsigrenderer); - return NULL; - } - - sigrenderer->desc = desc; - sigrenderer->sigrenderer = vsigrenderer; - - sigrenderer->n_channels = n_channels; - - sigrenderer->pos = pos; - sigrenderer->subpos = 0; - - sigrenderer->callback = NULL; - - return sigrenderer; -} - - - -sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type) -{ - if (sigrenderer && sigrenderer->desc->type == type) - return sigrenderer->sigrenderer; - - return NULL; -} - - - -#if 0 -// This function is disabled because we don't know whether we want to destroy -// the sigrenderer if the type doesn't match. We don't even know if we need -// the function at all. Who would want to keep an IT_SIGRENDERER (for -// instance) without keeping the DUH_SIGRENDERER? -sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type) -{ - if (sigrenderer && sigrenderer->desc->type == type) { - - - - if (sigrenderer) { - if (sigrenderer->desc->end_sigrenderer) - if (sigrenderer->sigrenderer) - (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer); - - free(sigrenderer); - } - - - - - - - return sigrenderer->sigrenderer; - } - - return NULL; -} -#endif diff --git a/Engine/libsrc/dumb-0.9.2/core/unload.c b/Engine/libsrc/dumb-0.9.2/core/unload.c deleted file mode 100644 index 3bf0285cd1f..00000000000 --- a/Engine/libsrc/dumb-0.9.2/core/unload.c +++ /dev/null @@ -1,58 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * unload.c - Code to free a DUH from memory. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/dumb.h" - - - -static void destroy_signal(DUH_SIGNAL *signal) -{ - if (signal) { - if (signal->desc) - if (signal->desc->unload_sigdata) - if (signal->sigdata) - (*signal->desc->unload_sigdata)(signal->sigdata); - - free(signal); - } -} - - - -/* unload_duh(): destroys a DUH struct. You must call this for every DUH - * struct created, when you've finished with it. - */ -void unload_duh(DUH *duh) -{ - int i; - - if (duh) { - if (duh->signal) { - for (i = 0; i < duh->n_signals; i++) - destroy_signal(duh->signal[i]); - - free(duh->signal); - } - - free(duh); - } -} diff --git a/Engine/libsrc/dumb-0.9.2/helpers/clickrem.c b/Engine/libsrc/dumb-0.9.2/helpers/clickrem.c deleted file mode 100644 index ddc861d9315..00000000000 --- a/Engine/libsrc/dumb-0.9.2/helpers/clickrem.c +++ /dev/null @@ -1,270 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * clickrem.c - Click removal helpers. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include -#include "dumb.h" - - - -typedef struct DUMB_CLICK DUMB_CLICK; - - -struct DUMB_CLICK_REMOVER -{ - DUMB_CLICK *click; - int n_clicks; - - int offset; -}; - - -struct DUMB_CLICK -{ - DUMB_CLICK *next; - long pos; - sample_t step; -}; - - - -DUMB_CLICK_REMOVER *dumb_create_click_remover(void) -{ - DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr)); - if (!cr) return NULL; - - cr->click = NULL; - cr->n_clicks = 0; - - cr->offset = 0; - - return cr; -} - - - -void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step) -{ - DUMB_CLICK *click; - - ASSERT(pos >= 0); - - if (!cr || !step) return; - - if (pos == 0) { - cr->offset -= step; - return; - } - - click = malloc(sizeof(*click)); - if (!click) return; - - click->pos = pos; - click->step = step; - - click->next = cr->click; - cr->click = click; - cr->n_clicks++; -} - - - -static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks) -{ - int i; - DUMB_CLICK *c1, *c2, **cp; - - if (n_clicks <= 1) return click; - - /* Split the list into two */ - c1 = click; - cp = &c1; - for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next; - c2 = *cp; - *cp = NULL; - - /* Sort the sublists */ - c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1); - c2 = dumb_click_mergesort(c2, n_clicks >> 1); - - /* Merge them */ - cp = &click; - while (c1 && c2) { - if (c1->pos > c2->pos) { - *cp = c2; - c2 = c2->next; - } else { - *cp = c1; - c1 = c1->next; - } - cp = &(*cp)->next; - } - if (c2) - *cp = c2; - else - *cp = c1; - - return click; -} - - - -void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, float halflife) -{ - DUMB_CLICK *click; - long pos = 0; - int offset; - int factor; - - if (!cr) return; - - factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31)); - - click = dumb_click_mergesort(cr->click, cr->n_clicks); - cr->click = NULL; - cr->n_clicks = 0; - - while (click) { - DUMB_CLICK *next = click->next; - ASSERT(click->pos <= length); - offset = cr->offset; - if (offset < 0) { - offset = -offset; - while (pos < click->pos) { - samples[pos++] -= offset; - offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); - } - offset = -offset; - } else { - while (pos < click->pos) { - samples[pos++] += offset; - offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); - } - } - cr->offset = offset - click->step; - free(click); - click = next; - } - - offset = cr->offset; - if (offset < 0) { - offset = -offset; - while (pos < length) { - samples[pos++] -= offset; - offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); - } - offset = -offset; - } else { - while (pos < length) { - samples[pos++] += offset; - offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); - } - } - cr->offset = offset; -} - - - -sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr) -{ - return cr ? cr->offset : 0; -} - - - -void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr) -{ - if (cr) { - DUMB_CLICK *click = cr->click; - while (click) { - DUMB_CLICK *next = click->next; - free(click); - click = next; - } - free(cr); - } -} - - - -DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n) -{ - int i; - DUMB_CLICK_REMOVER **cr; - if (n <= 0) return NULL; - cr = malloc(n * sizeof(*cr)); - if (!cr) return NULL; - for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover(); - return cr; -} - - - -void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step) -{ - if (cr) { - int i; - for (i = 0; i < n; i++) - dumb_record_click(cr[i], pos, step[i]); - } -} - - - -void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step) -{ - if (cr) { - int i; - for (i = 0; i < n; i++) - dumb_record_click(cr[i], pos, -step[i]); - } -} - - - -void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife) -{ - if (cr) { - int i; - for (i = 0; i < n; i++) - dumb_remove_clicks(cr[i], samples[i], length, halflife); - } -} - - - -void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset) -{ - if (cr) { - int i; - for (i = 0; i < n; i++) - if (cr[i]) offset[i] += cr[i]->offset; - } -} - - - -void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr) -{ - if (cr) { - int i; - for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]); - free(cr); - } -} diff --git a/Engine/libsrc/dumb-0.9.2/helpers/memfile.c b/Engine/libsrc/dumb-0.9.2/helpers/memfile.c deleted file mode 100644 index b65ab5f78dc..00000000000 --- a/Engine/libsrc/dumb-0.9.2/helpers/memfile.c +++ /dev/null @@ -1,96 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * memfile.c - Module for reading data from / / \ \ - * memory using a DUMBFILE. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include - -#include "dumb.h" - - - -typedef struct MEMFILE MEMFILE; - -struct MEMFILE -{ - const char *ptr; - long left; -}; - - - -static int dumb_memfile_skip(void *f, long n) -{ - MEMFILE *m = f; - if (n > m->left) return -1; - m->ptr += n; - m->left -= n; - return 0; -} - - - -static int dumb_memfile_getc(void *f) -{ - MEMFILE *m = f; - if (m->left <= 0) return -1; - m->left--; - return *(const unsigned char *)m->ptr++; -} - - - -static long dumb_memfile_getnc(char *ptr, long n, void *f) -{ - MEMFILE *m = f; - if (n > m->left) n = m->left; - memcpy(ptr, m->ptr, n); - m->ptr += n; - m->left -= n; - return n; -} - - - -static void dumb_memfile_close(void *f) -{ - free(f); -} - - - -static DUMBFILE_SYSTEM memfile_dfs = { - NULL, - &dumb_memfile_skip, - &dumb_memfile_getc, - &dumb_memfile_getnc, - &dumb_memfile_close -}; - - - -DUMBFILE *dumbfile_open_memory(const char *data, long size) -{ - MEMFILE *m = malloc(sizeof(*m)); - if (!m) return NULL; - - m->ptr = data; - m->left = size; - - return dumbfile_open_ex(m, &memfile_dfs); -} diff --git a/Engine/libsrc/dumb-0.9.2/helpers/resample.c b/Engine/libsrc/dumb-0.9.2/helpers/resample.c deleted file mode 100644 index d8b238fc718..00000000000 --- a/Engine/libsrc/dumb-0.9.2/helpers/resample.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * resample.c - Resampling helper. / / \ \ - * | < / \_ - * By Bob and entheh. | \/ /\ / - * \_ / > / - * In order to find a good trade-off between | \ / / - * speed and accuracy in this code, some tests | ' / - * were carried out regarding the behaviour of \__/ - * long long ints with gcc. The following code - * was tested: - * - * int a, b, c; - * c = ((long long)a * b) >> 16; - * - * DJGPP GCC Version 3.0.3 generated the following assembly language code for - * the multiplication and scaling, leaving the 32-bit result in EAX. - * - * movl -8(%ebp), %eax ; read one int into EAX - * imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX - * shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX - * - * Note that a 32*32->64 multiplication is performed, allowing for high - * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally), - * so it is a minor concern when four multiplications are being performed - * (the cubic resampler). On the Pentium MMX and earlier, it takes four or - * more cycles, so this method is unsuitable for use in the low-quality - * resamplers. - * - * Since "long long" is a gcc-specific extension, we use LONG_LONG instead, - * defined in dumb.h. We may investigate later what code MSVC generates, but - * if it seems too slow then we suggest you use a good compiler. - * - * FIXME: these comments are somewhat out of date now. - */ - -#include -#include "dumb.h" - - - -/* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is - * called when it should be. There will be a considerable performance hit, - * since at least one condition has to be tested for every sample generated. - */ -#ifdef HEAVYDEBUG -#define HEAVYASSERT(cond) ASSERT(cond) -#else -#define HEAVYASSERT(cond) -#endif - - - -//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16)) -//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14) -#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32)) - - - -/* A global variable for controlling resampling quality wherever a local - * specification doesn't override it. The following values are valid: - * - * 0 - DUMB_RQ_ALIASING - fastest - * 1 - DUMB_RQ_LINEAR - * 2 - DUMB_RQ_CUBIC - nicest - * - * Values outside the range 0-2 will behave the same as the nearest - * value within the range. - */ -int dumb_resampling_quality = 2; - - - -void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, long pos, long start, long end) -{ - resampler->src = src; - resampler->pos = pos; - resampler->subpos = 0; - resampler->start = start; - resampler->end = end; - resampler->dir = 1; - resampler->pickup = NULL; - resampler->pickup_data = NULL; - resampler->min_quality = 0; - resampler->max_quality = DUMB_RQ_N_LEVELS - 1; - resampler->x[2] = resampler->x[1] = resampler->x[0] = 0; - resampler->overshot = -1; -} - - - -DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, long pos, long start, long end) -{ - DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler)); - if (!resampler) return NULL; - dumb_reset_resampler(resampler, src, pos, start, end); - return resampler; -} - - - -/* For convenience, returns nonzero on stop. */ -static int process_pickup(DUMB_RESAMPLER *resampler) -{ - if (resampler->overshot < 0) { - resampler->overshot = 0; - dumb_resample(resampler, NULL, 2, 0, 1.0f); - resampler->x[0] = resampler->x[1]; - } - - for (;;) { - if (resampler->dir < 0) { - if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) resampler->x[0] = resampler->src[resampler->pos+3]; - if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) resampler->x[1] = resampler->src[resampler->pos+2]; - if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) resampler->x[2] = resampler->src[resampler->pos+1]; - resampler->overshot = resampler->start - resampler->pos - 1; - } else { - if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) resampler->x[0] = resampler->src[resampler->pos-3]; - if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) resampler->x[1] = resampler->src[resampler->pos-2]; - if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) resampler->x[2] = resampler->src[resampler->pos-1]; - resampler->overshot = resampler->pos - resampler->end; - } - - if (resampler->overshot < 0) { - resampler->overshot = 0; - return 0; - } - - if (!resampler->pickup) { - resampler->dir = 0; - return 1; - } - (*resampler->pickup)(resampler, resampler->pickup_data); - if (resampler->dir == 0) return 1; - ASSERT(resampler->dir == -1 || resampler->dir == 1); - } -} - - - -/* Executes the content 'iterator' times. - * Clobbers the 'iterator' variable. - * The loop is unrolled by four. - */ -#define LOOP4(iterator, CONTENT) \ -{ \ - if ((iterator) & 2) { \ - CONTENT; \ - CONTENT; \ - } \ - if ((iterator) & 1) { \ - CONTENT; \ - } \ - (iterator) >>= 2; \ - while (iterator) { \ - CONTENT; \ - CONTENT; \ - CONTENT; \ - CONTENT; \ - (iterator)--; \ - } \ -} - - - -long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta) -{ - int dt; - int vol; - long done; - long todo; - int quality; - - if (!resampler || resampler->dir == 0) return 0; - ASSERT(resampler->dir == -1 || resampler->dir == 1); - - done = 0; - dt = (int)(delta * 65536.0 + 0.5); - vol = (int)floor(volume * 65536.0 + 0.5); - - if (vol == 0) dst = NULL; - - quality = dumb_resampling_quality; - if (quality > resampler->max_quality) quality = resampler->max_quality; - else if (quality < resampler->min_quality) quality = resampler->min_quality; - - while (done < dst_size) { - if (process_pickup(resampler)) return done; - - if ((resampler->dir ^ dt) < 0) - dt = -dt; - - if (resampler->dir < 0) - todo = (long)((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt); - else - todo = (long)((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt); - - if (todo < 0) - todo = 0; - else if (todo > dst_size - done) - todo = dst_size - done; - - done += todo; - - { - sample_t *src = resampler->src; - long pos = resampler->pos; - int subpos = resampler->subpos; - long diff = pos; - long overshot; - if (resampler->dir < 0) { - if (!dst) { - /* Silence or simulation */ - LONG_LONG new_subpos = subpos + dt * todo; - pos += (long)(new_subpos >> 16); - subpos = (long)new_subpos & 65535; - } else if (quality <= DUMB_RQ_ALIASING) { - /* Aliasing, backwards */ - sample_t xbuf[2]; - sample_t *x = &xbuf[0]; - sample_t *xstart; - xbuf[0] = resampler->x[1]; - xbuf[1] = resampler->x[2]; - while (todo && x < &xbuf[2]) { - HEAVYASSERT(pos >= resampler->start); - *dst++ += MULSC(x[0], vol); - subpos += dt; - pos += subpos >> 16; - x -= subpos >> 16; - subpos &= 65535; - todo--; - } - x = xstart = &src[pos]; - LOOP4(todo, - *dst++ += MULSC(x[2], vol); - subpos += dt; - x += subpos >> 16; - subpos &= 65535; - ); - pos += x - xstart; - } else if (quality <= DUMB_RQ_LINEAR) { - /* Linear interpolation, backwards */ - sample_t xbuf[3]; - sample_t *x = &xbuf[1]; - xbuf[0] = resampler->x[1]; - xbuf[1] = resampler->x[2]; - xbuf[2] = src[pos]; - while (todo && x < &xbuf[3]) { - HEAVYASSERT(pos >= resampler->start); - *dst++ += MULSC(x[0] + MULSC(x[-1] - x[0], subpos), vol); - subpos += dt; - pos += subpos >> 16; - x -= subpos >> 16; - subpos &= 65535; - todo--; - } - x = &src[pos]; - LOOP4(todo, - HEAVYASSERT(pos >= resampler->start); - *dst++ += MULSC(x[1] + MULSC(x[2] - x[1], subpos), vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - ); - } else { - /* Cubic interpolation, backwards */ - sample_t xbuf[6]; - sample_t *x = &xbuf[3]; - sample_t *lastx = NULL; - int a = 0, b = 0, c = 0; - xbuf[0] = resampler->x[0]; - xbuf[1] = resampler->x[1]; - xbuf[2] = resampler->x[2]; - xbuf[3] = src[pos]; - if (pos-1 >= resampler->start) xbuf[4] = src[pos-1]; - if (pos-2 >= resampler->start) xbuf[5] = src[pos-2]; - while (todo && x < &xbuf[6]) { - HEAVYASSERT(pos >= resampler->start); - if (lastx != x) { - lastx = x; - a = (((x[-1] - x[-2]) << 1) + (x[-1] - x[-2]) + (x[-3] - x[0])) >> 1; - b = (x[-2] << 1) + x[0] - ((5 * x[-1] + x[-3]) >> 1); - c = (x[-2] - x[0]) >> 1; - } - *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-1], vol); - subpos += dt; - pos += subpos >> 16; - x -= subpos >> 16; - subpos &= 65535; - todo--; - } - x = &src[pos]; - lastx = NULL; - LOOP4(todo, - HEAVYASSERT(pos >= resampler->start); - if (lastx != x) { - lastx = x; - a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1; - b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1); - c = (x[2] - x[0]) >> 1; - } - *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[1], vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - ); - } - diff = diff - pos; - overshot = resampler->start - pos - 1; - if (diff >= 3) { - resampler->x[0] = overshot >= 3 ? 0 : src[pos+3]; - resampler->x[1] = overshot >= 2 ? 0 : src[pos+2]; - resampler->x[2] = overshot >= 1 ? 0 : src[pos+1]; - } else if (diff >= 2) { - resampler->x[0] = resampler->x[2]; - resampler->x[1] = overshot >= 2 ? 0 : src[pos+2]; - resampler->x[2] = overshot >= 1 ? 0 : src[pos+1]; - } else if (diff >= 1) { - resampler->x[0] = resampler->x[1]; - resampler->x[1] = resampler->x[2]; - resampler->x[2] = overshot >= 1 ? 0 : src[pos+1]; - } - } else { - if (!dst) { - /* Silence or simulation */ - LONG_LONG new_subpos = subpos + dt * todo; - pos += (long)(new_subpos >> 16); - subpos = (long)new_subpos & 65535; - } else if (dumb_resampling_quality <= DUMB_RQ_ALIASING) { - /* Aliasing, forwards */ - sample_t xbuf[2]; - sample_t *x = &xbuf[0]; - sample_t *xstart; - xbuf[0] = resampler->x[1]; - xbuf[1] = resampler->x[2]; - while (todo && x < &xbuf[2]) { - HEAVYASSERT(pos < resampler->end); - *dst++ += MULSC(x[0], vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - todo--; - } - x = xstart = &src[pos]; - LOOP4(todo, - *dst++ += MULSC(x[-2], vol); - subpos += dt; - x += subpos >> 16; - subpos &= 65535; - ); - pos += x - xstart; - } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) { - /* Linear interpolation, forwards */ - sample_t xbuf[3]; - sample_t *x = &xbuf[1]; - xbuf[0] = resampler->x[1]; - xbuf[1] = resampler->x[2]; - xbuf[2] = src[pos]; - while (todo && x < &xbuf[3]) { - HEAVYASSERT(pos < resampler->end); - *dst++ += MULSC(x[-1] + MULSC(x[0] - x[-1], subpos), vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - todo--; - } - x = &src[pos]; - LOOP4(todo, - HEAVYASSERT(pos < resampler->end); - *dst++ += MULSC(x[-2] + MULSC(x[-1] - x[-2], subpos), vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - ); - } else { - /* Cubic interpolation, forwards */ - sample_t xbuf[6]; - sample_t *x = &xbuf[3]; - sample_t *lastx = NULL; - int a = 0, b = 0, c = 0; - xbuf[0] = resampler->x[0]; - xbuf[1] = resampler->x[1]; - xbuf[2] = resampler->x[2]; - xbuf[3] = src[pos]; - if (pos+1 < resampler->end) xbuf[4] = src[pos+1]; - if (pos+2 < resampler->end) xbuf[5] = src[pos+2]; - while (todo && x < &xbuf[6]) { - HEAVYASSERT(pos < resampler->end); - if (lastx != x) { - lastx = x; - a = (((x[-2] - x[-1]) << 1) + (x[-2] - x[-1]) + (x[0] - x[-3])) >> 1; - b = (x[-1] << 1) + x[-3] - ((5 * x[-2] + x[0]) >> 1); - c = (x[-1] - x[-3]) >> 1; - } - *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-2], vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - todo--; - } - x = &src[pos]; - lastx = NULL; - LOOP4(todo, - HEAVYASSERT(pos < resampler->end); - if (lastx != x) { - lastx = x; - a = (((x[-2] - x[-1]) << 1) + (x[-2] - x[-1]) + (x[0] - x[-3])) >> 1; - b = (x[-1] << 1) + x[-3] - ((5 * x[-2] + x[0]) >> 1); - c = (x[-1] - x[-3]) >> 1; - } - *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-2], vol); - subpos += dt; - pos += subpos >> 16; - x += subpos >> 16; - subpos &= 65535; - ); - } - diff = pos - diff; - overshot = pos - resampler->end; - if (diff >= 3) { - resampler->x[0] = overshot >= 3 ? 0 : src[pos-3]; - resampler->x[1] = overshot >= 2 ? 0 : src[pos-2]; - resampler->x[2] = overshot >= 1 ? 0 : src[pos-1]; - } else if (diff >= 2) { - resampler->x[0] = resampler->x[2]; - resampler->x[1] = overshot >= 2 ? 0 : src[pos-2]; - resampler->x[2] = overshot >= 1 ? 0 : src[pos-1]; - } else if (diff >= 1) { - resampler->x[0] = resampler->x[1]; - resampler->x[1] = resampler->x[2]; - resampler->x[2] = overshot >= 1 ? 0 : src[pos-1]; - } - } - resampler->pos = pos; - resampler->subpos = subpos; - } - } - - return done; -} - - - -sample_t dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, float volume) -{ - int vol; - sample_t *src; - long pos; - int subpos; - int quality; - - if (!resampler || resampler->dir == 0) return 0; - ASSERT(resampler->dir == -1 || resampler->dir == 1); - - if (process_pickup(resampler)) return 0; - - vol = (int)floor(volume * 65536.0 + 0.5); - if (vol == 0) return 0; - - quality = dumb_resampling_quality; - if (quality > resampler->max_quality) quality = resampler->max_quality; - else if (quality < resampler->min_quality) quality = resampler->min_quality; - - src = resampler->src; - pos = resampler->pos; - subpos = resampler->subpos; - - if (resampler->dir < 0) { - HEAVYASSERT(pos >= resampler->start); - if (dumb_resampling_quality <= 0) { - /* Aliasing, backwards */ - return MULSC(src[pos], vol); - } else if (quality <= DUMB_RQ_LINEAR) { - /* Linear interpolation, backwards */ - return MULSC(resampler->x[2] + MULSC(resampler->x[1] - resampler->x[2], subpos), vol); - } else { - /* Cubic interpolation, backwards */ - sample_t *x = resampler->x; - int a, b, c; - a = (((x[2] - x[1]) << 1) + (x[2] - x[1]) + (x[0] - src[pos])) >> 1; - b = (x[1] << 1) + src[pos] - ((5 * x[2] + x[0]) >> 1); - c = (x[1] - src[pos]) >> 1; - return MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[2], vol); - } - } else { - HEAVYASSERT(pos < resampler->end); - if (dumb_resampling_quality <= 0) { - /* Aliasing */ - return MULSC(src[pos], vol); - } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) { - /* Linear interpolation, forwards */ - return MULSC(resampler->x[1] + MULSC(resampler->x[2] - resampler->x[1], subpos), vol); - } else { - /* Cubic interpolation, forwards */ - sample_t *x = resampler->x; - int a, b, c; - a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (src[pos] - x[0])) >> 1; - b = (x[2] << 1) + x[0] - ((5 * x[1] + src[pos]) >> 1); - c = (x[2] - x[0]) >> 1; - return MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[1], vol); - } - } -} - - - -void dumb_end_resampler(DUMB_RESAMPLER *resampler) -{ - if (resampler) - free(resampler); -} - - - -#if 0 -/* The following macro is used to overcome the fact that most C - * compilers (including gcc and MSVC) can't correctly multiply signed - * integers outside the range -32768 to 32767. i86 assembler versions - * don't need to use this method, since the processor does in fact - * have instructions to multiply large numbers correctly - which - * means using assembly language could make a significant difference - * to the speed. - * - * The basic method is as follows. We halve the subposition (how far - * we are between samples), so it never exceeds 32767. We also halve - * the delta, which is the amount to be added to the subposition each - * time. Then we unroll the loop twofold, so that we can add the lost - * one every other time if necessary (since the halving may have - * resulted in rounding down). - * - * This method doesn't incur any cumulative inaccuracies. There is a - * very slight loss of quality, which I challenge anyone to notice - - * but the position will advance at *exactly* the same rate as it - * would if we didn't use this method. This also means the pitch is - * exactly the same, which may even make a difference to trained - * musicians when resampling down a lot :) - * - * Each time this macro is invoked, DO_RESAMPLE(inc) must be defined - * to calculate the samples by the appropriate equation (linear, - * cubic, etc.). See the individual cases for examples of how this is - * done. - */ -#define MAKE_RESAMPLER() \ -{ \ - if (dt & 1) { \ - long todo2; \ - \ - dt >>= 1; \ - \ - if (src_subpos & 1) { \ - src_subpos >>= 1; \ - DO_RESAMPLE(1); \ - todo--; \ - } else \ - src_subpos >>= 1; \ - \ - todo2 = todo >> 1; \ - \ - while (todo2) { \ - DO_RESAMPLE(0); \ - DO_RESAMPLE(1); \ - todo2--; \ - } \ - \ - if (todo & 1) { \ - DO_RESAMPLE(0); \ - src_subpos = (src_subpos << 1) | 1; \ - } else \ - src_subpos <<= 1; \ - \ - todo = 0; \ - dt = (dt << 1) | 1; \ - } else { \ - long subposbit = src_subpos & 1; \ - dt >>= 1; \ - src_subpos >>= 1; \ - \ - if (todo & 1) { \ - DO_RESAMPLE(0); \ - } \ - \ - todo >>= 1; \ - \ - while (todo) { \ - DO_RESAMPLE(0); \ - DO_RESAMPLE(0); \ - todo--; \ - } \ - \ - src_subpos = (src_subpos << 1) | subposbit; \ - dt <<= 1; \ - } \ -} - - - -sample_t dumb_resample_get_current_sample( - sample_t *src, long *_src_pos, int *_src_subpos, - long src_start, long src_end, - float volume, int *_dir, - DUMB_RESAMPLE_PICKUP pickup, void *pickup_data -) -{ - long src_pos = *_src_pos; - int src_subpos = *_src_subpos; - int dir = _dir ? *_dir : 1; - - sample_t value = 0; - - if (dir == 0) - return 0; - - ASSERT(dir == 1 || dir == -1); - - if (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)) { - - /* If there's no pick-up function, we stop. */ - if (!pickup) { - dir = 0; - goto end; - } - - /* Process the pick-up. It may need invoking more than once. */ - do { - dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data); - - if (dir == 0) - goto end; - - ASSERT(dir == 1 || dir == -1); - } while (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)); - } - - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); - - if (dumb_resampling_quality == 0) { - /* Aliasing (coarse) */ - int volume_fact = (int)(volume * 16384.0); - value = (src[src_pos] * volume_fact) >> 14; - } else if (dumb_resampling_quality <= 2) { - /* Linear interpolation */ - int volume_fact = (int)(volume * 16384.0); - int subpos = src_subpos >> 1; - value = ((src[src_pos] + ((((src[src_pos + 1] - src[src_pos]) >> 1) * subpos) >> 14)) * volume_fact) >> 14; - } else if (dumb_resampling_quality == 3) { - /* Quadratic interpolation */ - int volume_fact = (int)(volume * 16384.0); - int a, b; - sample_t *x; - int subpos = src_subpos >> 1; - x = &src[src_pos]; - a = ((x[0] + x[2]) >> 1) - x[1]; - b = ((x[2] - x[0]) >> 1) - (a << 1); - value = (((((((a * subpos) >> 15) + b) * subpos) >> 15) + x[0]) * volume_fact) >> 14; - } else { - /* Cubic interpolation */ - int volume_fact = (int)(volume * 16384.0); - int a, b, c; - sample_t *x; - int subpos = src_subpos >> 1; - x = &src[src_pos]; - a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1; - b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1); - c = (x[2] - x[0]) >> 1; - value = (((int)(((LONG_LONG)((int)(((LONG_LONG)((int)(((LONG_LONG)a * subpos) >> 15) + b) * subpos) >> 15) + c) * subpos) >> 15) + x[1]) * volume_fact) >> 14; - } - - end: - - *_src_pos = src_pos; - *_src_subpos = src_subpos; - if (_dir) *_dir = dir; - - return value; -} - - - -long dumb_resample( - sample_t *src, long *_src_pos, int *_src_subpos, - long src_start, long src_end, - sample_t *dst, long dst_size, - float volume, float delta, int *_dir, - DUMB_RESAMPLE_PICKUP pickup, void *pickup_data -) -{ - int dt = (int)(delta * 65536.0 + 0.5); - long s = 0; /* Current position in the destination buffer */ - - long src_pos = *_src_pos; - int src_subpos = *_src_subpos; - int dir = _dir ? *_dir : 1; - - int linear_average; - - if (dir == 0) - return 0; - - ASSERT(dir == 1 || dir == -1); - - linear_average = dst && dumb_resampling_quality >= 2 && dt > 65536; - - if (dir < 0) dt = -dt; - - if (linear_average) - volume /= delta; - - while (s < dst_size) { - - long todo; - - /* Process pick-ups first, just in case. */ - - if (linear_average) { - - /* For linear average, the pick-up point could split a sum into - * two parts. We handle this by putting the pick-up code inside - * the summing loop. Note that this code is only executed when we - * know that a pick-up is necessary somewhere during this sum - * (although it is always executed once for the first sample). - * We use a separate loop further down when we know we won't have - * to do a pick-up, so the condition does not need testing inside - * the loop. - */ - - float sum; - long i; - int advance; - int x[3]; - - advance = src_subpos + dt; - - /* Make these negative. Then they stay within the necessary - * range for integer multiplication, -32768 to 32767 ;) - */ - x[0] = ~(src_subpos >> 1); /* = -1 - (src_subpos >> 1) */ - x[2] = x[0] ^ 0x7FFF; /* = -32768 + (src_subpos >> 1) */ - - sum = (float)(-((src[src_pos] * (x+1)[dir]) >> 15)); - - i = src_pos + (advance >> 16); - src_pos += dir; - src_subpos = (dir >> 1) & 65535; /* changes 1,-1 to 0,65535 */ - - advance &= 65535; - - /* i is the index of the first sample NOT to sum fully, - * regardless of the direction of resampling. - */ - - while (dir < 0 ? (i < src_start) : (i >= src_end)) { - if (dir < 0) { - while (src_pos >= src_start) - sum += src[src_pos--]; - } else { - while (src_pos < src_end) - sum += src[src_pos++]; - } - - i -= src_pos; - /* i is now the number of samples left to sum fully, except - * it's negative if we're going backwards. - */ - - if (!pickup) { - dir = 0; - goto endsum; - } - - dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data); - - if (dir == 0) - goto endsum; - - ASSERT(dir == 1 || dir == -1); - - if ((dir ^ dt) < 0) { - dt = -dt; - advance ^= 65535; - i = -i; - } - - i += src_pos; - /* There, i is back to normal. */ - } - - for (; src_pos != i; src_pos += dir) - sum += src[src_pos]; - - src_subpos = advance; - - x[2] = src_subpos >> 1; - x[0] = x[2] ^ 0x7FFF; /* = 32767 - (src_subpos >> 1) */ - - sum += (src[src_pos] * (x+1)[dir]) >> 15; - - endsum: - - sum *= volume; - dst[s] += (int)sum; - - s++; - - if (dir == 0) - break; - - } else if (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)) { - - /* If there's no pick-up function, we stop. */ - if (!pickup) { - dir = 0; - break; - } - - /* Process the pick-up. It may need invoking more than once. */ - do { - dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data); - - if (dir == 0) - goto end; - - ASSERT(dir == 1 || dir == -1); - } while (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)); - - /* Update sign of dt to match that of dir. */ - if ((dir ^ dt) < 0) - dt = -dt; - } - - /* Work out how many contiguous samples we can now render. */ - if (dir < 0) - todo = (long)((((LONG_LONG)(src_pos - src_start) << 16) + src_subpos) / -dt); - else - todo = (long)((((LONG_LONG)(src_end - src_pos) << 16) - src_subpos - 1) / dt); - - /* The above equations work out how many complete dt-sized - * intervals there are between the current position and the loop - * point (provided there is a little fractional extra). The linear - * average function needs complete intervals - but the other - * resamplers only read a sample from the beginning of each interval, - * so they can process one extra sample in their main loops (so we - * increment todo in a moment). - * - * The linear average function makes up the extra sample using the - * specialised pick-up code above. - * - * Note that our above pick-up process should have absolutely ensured - * that the result of this function will be nonnegative. - */ - - ASSERT(todo >= 0); - - if (!linear_average) - todo++; - - /* Of course we don't want to overrun the output buffer! */ - if (todo > dst_size - s) - todo = dst_size - s; - - if (!dst) { - - LONG_LONG t = src_subpos + (LONG_LONG)dt * todo; - src_pos += (long)(t >> 16); - src_subpos = (int)t & 0xFFFFl; - - s += todo; - - } else if (linear_average) { - - float sum; - long i; - int advance; - int x[3]; - - while (todo) { - - advance = src_subpos + dt; - - /* Make these negative. Then they stay within the necessary - * range for integer multiplication, -32768 to 32767 ;) - */ - x[0] = ~(src_subpos >> 1); /* = -1 - (src_subpos >> 1) */ - x[2] = x[0] ^ 0x7FFF; /* = -32768 + (src_subpos >> 1) */ - - sum = (float)(-((src[src_pos] * (x+1)[dir]) >> 15)); - - i = src_pos + (advance >> 16); - src_pos += dir; - src_subpos = (dir >> 1) & 65535; /* changes 1,-1 to 0,65535 */ - - advance &= 65535; - - /* i is the index of the first sample NOT to sum fully, - * regardless of the direction of resampling. - */ - - HEAVYASSERT(dir < 0 ? (i >= src_start) : (i < src_end)); - - for (; src_pos != i; src_pos += dir) - sum += src[src_pos]; - - src_subpos = advance; - - x[2] = src_subpos >> 1; - x[0] = x[2] ^ 0x7FFF; /* = 32767 - (src_subpos >> 1) */ - - sum += (src[src_pos] * (x+1)[dir]) >> 15; - - sum *= volume; - dst[s] += (int)sum; - - s++; - todo--; - } - - } else if (dumb_resampling_quality == 0 || (dumb_resampling_quality == 1 && delta >= 1.0)) { - - /* Aliasing (coarse) */ - int volume_fact = (int)(volume * 16384.0); - - do { - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); - dst[s] += ((src[src_pos] * volume_fact) >> 14); - src_subpos += dt; - src_pos += src_subpos >> 16; - src_subpos &= 0xFFFFl; - s++; - } while (--todo); - - } else if (dumb_resampling_quality <= 2) { - - /* Linear interpolation */ - int volume_fact = (int)(volume * 16384.0); - - #define DO_RESAMPLE(inc) \ - { \ - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \ - \ - dst[s] += (((src[src_pos] + ((((src[src_pos + 1] - src[src_pos]) >> 1) * src_subpos) >> 14)) * volume_fact) >> 14); \ - \ - src_subpos += dt + inc; \ - src_pos += src_subpos >> 15; \ - src_subpos &= 0x7FFFl; \ - s++; \ - } - - MAKE_RESAMPLER(); - - #undef DO_RESAMPLE - - } else if (dumb_resampling_quality == 3) { - - /* Quadratic interpolation */ - - int volume_fact = (int)(volume * 16384.0); - int a = 0, b = 0; - sample_t *x = NULL; - int last_src_pos = -1; - - /* AIM: no integer multiplicands must transcend the range -32768 to 32767. - * This limitation is imposed by most compilers, including gcc and MSVC. - * - * a = 0.5 * (s0 + s2) - s1 - * b = -1.5 * s0 + 2 * s1 - 0.5 * s2 - * c = s0 - * - * s = (a * t + b) * t + c - * - * In fixed-point: - * - * a = ((s0 + s2) >> 1) - s1 - * b = ((-3 * s0 - s2) >> 1) + (s1 << 1) - * - * s = (((((a * t) >> 16) + b) * t) >> 16) + s0 - * - * With t halved (since t can reach 65535): - * - * s = (((((a * t) >> 15) + b) * t) >> 15) + s0 - * - * a currently reaches 65536 - * b currently reaches 131072 - * - * So we must use aon2 - * - * s = (((((aon2 * t) >> 14) + b) * t) >> 15) + s0 - * - * ((aon2 * t) >> 14) + b is 5 times too big - * so we must divide by 8 - * - * s = (((((aon2 * t) >> 17) + bon8) * t) >> 12) + s0 - * - * aon2 = ((s0 + s2) >> 2) - (s1 >> 1) - * bon8 = ((-3 * s0 - s2) >> 4) + (s1 >> 2) - * or: - * bon8 = ((s2 - s0) >> 4) - (aon2 >> 1) - */ - - /* Unh4x0r3d version: - #define DO_RESAMPLE(inc) \ - { \ - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \ - \ - if (src_pos != last_src_pos) { \ - last_src_pos = src_pos; \ - x = &src[src_pos]; \ - a = ((x[0] + x[2]) >> 2) - (x[1] >> 1); \ - b = ((x[2] - x[0]) >> 4) - (a >> 1); \ - } \ - \ - dst[s] += ((((((((a * src_subpos) >> 17) + b) * src_subpos) >> 12) + x[0]) * volume_fact) >> 14); \ - \ - src_subpos += dt + inc; \ - src_pos += src_subpos >> 15; \ - src_subpos &= 0x7FFFl; \ - s++; \ - } - */ - - /* H4x0r3d version: */ - #define DO_RESAMPLE(inc) \ - { \ - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \ - \ - if (src_pos != last_src_pos) { \ - last_src_pos = src_pos; \ - x = &src[src_pos]; \ - a = ((x[0] + x[2]) >> 1) - x[1]; \ - b = ((x[2] - x[0]) >> 1) - (a << 1); \ - } \ - \ - dst[s] += ((((((((a * src_subpos) >> 15) + b) * src_subpos) >> 15) + x[0]) * volume_fact) >> 14); \ - \ - src_subpos += dt + inc; \ - src_pos += src_subpos >> 15; \ - src_subpos &= 0x7FFFl; \ - s++; \ - } - - MAKE_RESAMPLER(); - - #undef DO_RESAMPLE - - } else { - - /* Cubic interpolation */ - - int volume_fact = (int)(volume * 16384.0); - int a = 0, b = 0, c = 0; - sample_t *x = NULL; - int last_src_pos = -1; - - /* AIM: never multiply integers outside the range -32768 to 32767. - * - * a = 1.5f * (x[1] - x[2]) + (x[3] - x[0]) * 0.5f; - * b = 2.0f * x[2] + x[0] - 2.5f * x[1] - x[3] * 0.5f; - * c = (x[2] - x[0]) * 0.5f; - * - * s = ((a * t + b) * t + c) * t + x[1]; - * - * Fixed-point version: - * - * a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1; - * b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1); - * c = (x[2] - x[0]) >> 1; - * - * s = ((((((((a * t) >> 15) + b) * t) >> 15) + c) * t) >> 15) + x[1]; - * (with t already halved, maximum 32767) - * - * a is in (((1+1)*2)+(1+1)+(1+1))/2 = 8 times the required range - * b is in (1*2)+1+((5*1+1)/2) = 6 times - * c is in the required range - * - * We must use aon8 - * - * s = ((((((((aon8 * t) >> 12) + b) * t) >> 15) + c) * t) >> 15) + x[1]; - * - * But ((aon8 * t) >> 12) is in 2^(15+15-12) = 2^18 = 8 times - * b is in 6 times - * so we divide both ((aon8 * t) >> 12) and b by 16 - * - * s = ((((((((aon8 * t) >> 16) + bon16) * t) >> 11) + c) * t) >> 15) + x[1]; - * - * ((... + bon16) * t) >> 11 is 16 times too big - * c is in the correct range - * we must divide both by 32 - * - * s = ((((((((aon8 * t) >> 16) + bon16) * t) >> 16) + con32) * t) >> 10) + x[1]; - * - * aon8 = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 4; - * bon16 = ((x[2] << 2) + (x[0] << 1) - (5 * x[1] + x[3])) >> 5; - * con32 = (x[2] - x[0]) >> 6; - * - * A lot of accuracy is lost here. It is quite likely that some - * of the above would cancel anyway, so the scaling down wouldn't - * have to be so severe. However, I'm not in the mood to work it - * out now :P - * - * It may also be worth investigating whether doing this stuff - * in floats would be faster. - */ - - /* Unh4x0r3d version: - #define DO_RESAMPLE(inc) \ - { \ - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \ - \ - if (src_pos != last_src_pos) { \ - last_src_pos = src_pos; \ - x = &src[src_pos]; \ - a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 4; \ - b = ((x[2] << 2) + (x[0] << 1) - (5 * x[1] + x[3])) >> 5; \ - c = (x[2] - x[0]) >> 6; \ - } \ - \ - dst[s] += ((((((((((a * src_subpos) >> 16) + b) * src_subpos) >> 16) + c) * src_subpos) >> 10) + x[1]) * volume_fact) >> 14; \ - \ - src_subpos += dt + inc; \ - src_pos += src_subpos >> 15; \ - src_subpos &= 0x7FFFl; \ - s++; \ - } - */ - - /* H4x0r3d version: */ - #define DO_RESAMPLE(inc) \ - { \ - HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \ - \ - if (src_pos != last_src_pos) { \ - last_src_pos = src_pos; \ - x = &src[src_pos]; \ - a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1; \ - b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1); \ - c = (x[2] - x[0]) >> 1; \ - } \ - \ - dst[s] += (((int)(((LONG_LONG)((int)(((LONG_LONG)((int)(((LONG_LONG)a * src_subpos) >> 15) + b) * src_subpos) >> 15) + c) * src_subpos) >> 15) + x[1]) * volume_fact) >> 14; \ - \ - src_subpos += dt + inc; \ - src_pos += src_subpos >> 15; \ - src_subpos &= 0x7FFFl; \ - s++; \ - } - - MAKE_RESAMPLER(); - - #undef DO_RESAMPLE - - } - - } - - end: - - ASSERT(s <= dst_size); - - *_src_pos = src_pos; - *_src_subpos = src_subpos; - if (_dir) *_dir = dir; - - return s; -} -#endif diff --git a/Engine/libsrc/dumb-0.9.2/helpers/sampbuf.c b/Engine/libsrc/dumb-0.9.2/helpers/sampbuf.c deleted file mode 100644 index 75510c729ac..00000000000 --- a/Engine/libsrc/dumb-0.9.2/helpers/sampbuf.c +++ /dev/null @@ -1,47 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * sampbuf.c - Helper for allocating sample / / \ \ - * buffers. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include "dumb.h" - - - -sample_t **create_sample_buffer(int n_channels, long length) -{ - int i; - sample_t **samples = malloc(n_channels * sizeof(*samples)); - if (!samples) return NULL; - samples[0] = malloc(n_channels * length * sizeof(*samples[0])); - if (!samples[0]) { - free(samples); - return NULL; - } - for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length; - return samples; -} - - - -void destroy_sample_buffer(sample_t **samples) -{ - if (samples) { - free(samples[0]); - free(samples); - } -} diff --git a/Engine/libsrc/dumb-0.9.2/helpers/silence.c b/Engine/libsrc/dumb-0.9.2/helpers/silence.c deleted file mode 100644 index 4d5fdcf4daa..00000000000 --- a/Engine/libsrc/dumb-0.9.2/helpers/silence.c +++ /dev/null @@ -1,29 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * silence.c - Silencing helper. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include "dumb.h" - - - -void dumb_silence(sample_t *samples, long length) -{ - memset(samples, 0, length * sizeof(*samples)); -} - diff --git a/Engine/libsrc/dumb-0.9.2/helpers/stdfile.c b/Engine/libsrc/dumb-0.9.2/helpers/stdfile.c deleted file mode 100644 index 2f02539a92a..00000000000 --- a/Engine/libsrc/dumb-0.9.2/helpers/stdfile.c +++ /dev/null @@ -1,93 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * stdfile.c - stdio file input module. / / \ \ - * | < / \_ - * By entheh. | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" - - - -static void *dumb_stdfile_open(const char *filename) -{ - return fopen(filename, "rb"); -} - - - -static int dumb_stdfile_skip(void *f, long n) -{ - return fseek(f, n, SEEK_CUR); -} - - - -static int dumb_stdfile_getc(void *f) -{ - return fgetc(f); -} - - - -static long dumb_stdfile_getnc(char *ptr, long n, void *f) -{ - return fread(ptr, 1, n, f); -} - - - -static void dumb_stdfile_close(void *f) -{ - fclose(f); -} - - - -static DUMBFILE_SYSTEM stdfile_dfs = { - &dumb_stdfile_open, - &dumb_stdfile_skip, - &dumb_stdfile_getc, - &dumb_stdfile_getnc, - &dumb_stdfile_close -}; - - - -void dumb_register_stdfiles(void) -{ - register_dumbfile_system(&stdfile_dfs); -} - - - -static DUMBFILE_SYSTEM stdfile_dfs_leave_open = { - NULL, - &dumb_stdfile_skip, - &dumb_stdfile_getc, - &dumb_stdfile_getnc, - NULL -}; - - - -DUMBFILE *dumbfile_open_stdfile(FILE *p) -{ - DUMBFILE *d = dumbfile_open_ex(p, &stdfile_dfs_leave_open); - - return d; -} diff --git a/Engine/libsrc/dumb-0.9.2/include/aldumb.h b/Engine/libsrc/dumb-0.9.2/include/aldumb.h deleted file mode 100644 index 75262508d9b..00000000000 --- a/Engine/libsrc/dumb-0.9.2/include/aldumb.h +++ /dev/null @@ -1,98 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * aldumb.h - The user header file for DUMB with / / \ \ - * Allegro. | < / \_ - * | \/ /\ / - * Include this file if you wish to use DUMB \_ / > / - * with Allegro. It will include dumb.h for you, | \ / / - * and provide extra functionality such as audio | ' / - * stream and datafile integration. \__/ - */ - -#ifndef ALDUMB_H -#define ALDUMB_H - - -#include - -#include "dumb.h" - - -#ifdef __cplusplus - extern "C" { -#endif - - -/* Packfile Support */ - -void dumb_register_packfiles(void); - -DUMBFILE *dumbfile_open_packfile(PACKFILE *p); -DUMBFILE *dumbfile_from_packfile(PACKFILE *p); - - -/* Datafile Registration Functions */ - -#define DUMB_DAT_DUH DAT_ID('D','U','H',' ') -#define DUMB_DAT_IT DAT_ID('I','T',' ',' ') -#define DUMB_DAT_XM DAT_ID('X','M',' ',' ') -#define DUMB_DAT_S3M DAT_ID('S','3','M',' ') -#define DUMB_DAT_MOD DAT_ID('M','O','D',' ') - -void dumb_register_dat_duh(long type); -void dumb_register_dat_it(long type); -void dumb_register_dat_xm(long type); -void dumb_register_dat_s3m(long type); -void dumb_register_dat_mod(long type); -void dumb_register_dat_it_quick(long type); -void dumb_register_dat_xm_quick(long type); -void dumb_register_dat_s3m_quick(long type); -void dumb_register_dat_mod_quick(long type); - - -/* DUH Playing Functions */ - -typedef struct AL_DUH_PLAYER AL_DUH_PLAYER; - -AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq); -void al_stop_duh(AL_DUH_PLAYER *dp); -void al_pause_duh(AL_DUH_PLAYER *dp); -void al_resume_duh(AL_DUH_PLAYER *dp); -void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority); -void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume); -float al_duh_get_volume(AL_DUH_PLAYER *dp); -int al_poll_duh(AL_DUH_PLAYER *dp); -long al_duh_get_position(AL_DUH_PLAYER *dp); - -AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq); -DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp); - -/* IMPORTANT: This function will return NULL if the music has ended. */ -DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp); - -#ifdef DUMB_DECLARE_DEPRECATED - -AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq) DUMB_DEPRECATED; -DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED; -DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED; -/* Replace 'renderer' with 'sigrenderer' in each case where you called one of - * these functions. - */ - -#endif - - -#ifdef __cplusplus - } -#endif - - -#endif /* ALDUMB_H */ diff --git a/Engine/libsrc/dumb-0.9.2/include/dumb.h b/Engine/libsrc/dumb-0.9.2/include/dumb.h deleted file mode 100644 index 1271c6786e1..00000000000 --- a/Engine/libsrc/dumb-0.9.2/include/dumb.h +++ /dev/null @@ -1,563 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * dumb.h - The user header file for DUMB. / / \ \ - * | < / \_ - * Include this file in any of your files in | \/ /\ / - * which you wish to use the DUMB functions \_ / > / - * and variables. | \ / / - * | ' / - * \__/ - */ - -#ifndef DUMB_H -#define DUMB_H - - -#include -#include - - -#ifdef __cplusplus - extern "C" { -#endif - - -#define DUMB_MAJOR_VERSION 0 -#define DUMB_MINOR_VERSION 9 -#define DUMB_REVISION_VERSION 2 - -#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION) - -#define DUMB_VERSION_STR "0.9.2" - -#define DUMB_NAME "DUMB v" DUMB_VERSION_STR - -#define DUMB_YEAR 2003 -#define DUMB_MONTH 4 -#define DUMB_DAY 2 - -#define DUMB_YEAR_STR2 "03" -#define DUMB_YEAR_STR4 "2003" -#define DUMB_MONTH_STR1 "4" -#define DUMB_DAY_STR1 "2" - -#if DUMB_MONTH < 10 -#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1 -#else -#define DUMB_MONTH_STR2 DUMB_MONTH_STR1 -#endif - -#if DUMB_DAY < 10 -#define DUMB_DAY_STR2 "0" DUMB_DAY_STR1 -#else -#define DUMB_DAY_STR2 DUMB_DAY_STR1 -#endif - - -/* WARNING: The month and day were inadvertently swapped in the v0.8 release. - * Please do not compare this constant against any date in 2002. In - * any case, DUMB_VERSION is probably more useful for this purpose. - */ -#define DUMB_DATE (DUMB_YEAR*10000 + DUMB_MONTH*100 + DUMB_DAY) - -#define DUMB_DATE_STR DUMB_DAY_STR1 "." DUMB_MONTH_STR1 "." DUMB_YEAR_STR4 - - -#undef MIN -#undef MAX -#undef MID - -#define MIN(x,y) (((x) < (y)) ? (x) : (y)) -#define MAX(x,y) (((x) > (y)) ? (x) : (y)) -#define MID(x,y,z) MAX((x), MIN((y), (z))) - -#undef ABS -#define ABS(x) (((x) >= 0) ? (x) : (-(x))) - - -#ifdef DEBUGMODE - -#ifndef ASSERT -#include -#define ASSERT(n) assert(n) -#endif -#ifndef TRACE -// it would be nice if this did actually trace ... -#define TRACE 1 ? (void)0 : (void)printf -#endif - -#else - -#ifndef ASSERT -#define ASSERT(n) -#endif -#ifndef TRACE -#define TRACE 1 ? (void)0 : (void)printf -#endif - -#endif - - -#define DUMB_ID(a,b,c,d) (((unsigned int)(a) << 24) | \ - ((unsigned int)(b) << 16) | \ - ((unsigned int)(c) << 8) | \ - ((unsigned int)(d) )) - - - -#ifndef LONG_LONG -#ifdef __GNUC__ -#define LONG_LONG long long -#elif defined _MSC_VER -#define LONG_LONG __int64 -#else -#error 64-bit integer type unknown -#endif -#endif - -#if __GNUC__ * 100 + __GNUC_MINOR__ >= 301 /* GCC 3.1+ */ -#ifndef DUMB_DECLARE_DEPRECATED -#define DUMB_DECLARE_DEPRECATED -#endif -#define DUMB_DEPRECATED __attribute__((__deprecated__)) -#else -#define DUMB_DEPRECATED -#endif - - -/* Basic Sample Type. Normal range is -0x800000 to 0x7FFFFF. */ - -typedef int sample_t; - - -/* Library Clean-up Management */ - -int dumb_atexit(void (*proc)(void)); - -void dumb_exit(void); - - -/* File Input Functions */ - -typedef struct DUMBFILE_SYSTEM -{ - void *(*open)(const char *filename); - int (*skip)(void *f, long n); - int (*getc)(void *f); - long (*getnc)(char *ptr, long n, void *f); - void (*close)(void *f); -} -DUMBFILE_SYSTEM; - -typedef struct DUMBFILE DUMBFILE; - -void register_dumbfile_system(DUMBFILE_SYSTEM *dfs); - -DUMBFILE *dumbfile_open(const char *filename); -DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs); - -long dumbfile_pos(DUMBFILE *f); -int dumbfile_skip(DUMBFILE *f, long n); - -int dumbfile_getc(DUMBFILE *f); - -int dumbfile_igetw(DUMBFILE *f); -int dumbfile_mgetw(DUMBFILE *f); - -long dumbfile_igetl(DUMBFILE *f); -long dumbfile_mgetl(DUMBFILE *f); - -unsigned long dumbfile_cgetul(DUMBFILE *f); -signed long dumbfile_cgetsl(DUMBFILE *f); - -long dumbfile_getnc(char *ptr, long n, DUMBFILE *f); - -int dumbfile_error(DUMBFILE *f); -int dumbfile_close(DUMBFILE *f); - - -/* stdio File Input Module */ - -void dumb_register_stdfiles(void); - -DUMBFILE *dumbfile_open_stdfile(FILE *p); - - -/* Memory File Input Module */ - -DUMBFILE *dumbfile_open_memory(const char *data, long size); - - -/* DUH Management */ - -typedef struct DUH DUH; - -#define DUH_SIGNATURE DUMB_ID('D','U','H','!') - -void unload_duh(DUH *duh); - -DUH *load_duh(const char *filename); -DUH *read_duh(DUMBFILE *f); - -long duh_get_length(DUH *duh); - - -/* Signal Rendering Functions */ - -typedef struct DUH_SIGRENDERER DUH_SIGRENDERER; - -DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos); - -#ifdef DUMB_DECLARE_DEPRECATED -typedef void (*DUH_SIGRENDERER_CALLBACK)(void *data, sample_t **samples, int n_channels, long length); -/* This is deprecated, but is not marked as such because GCC tends to - * complain spuriously when the typedef is used later. See comments below. - */ - -void duh_sigrenderer_set_callback( - DUH_SIGRENDERER *sigrenderer, - DUH_SIGRENDERER_CALLBACK callback, void *data -) DUMB_DEPRECATED; -/* The 'callback' argument's type has changed for const-correctness. See the - * DUH_SIGRENDERER_CALLBACK definition just above. Also note that the samples - * in the buffer are now 256 times as large; the normal range is -0x800000 to - * 0x7FFFFF. The function has been renamed partly because its functionality - * has changed slightly and partly so that its name is more meaningful. The - * new one is duh_sigrenderer_set_analyser_callback(), and the typedef for - * the function pointer has also changed, from DUH_SIGRENDERER_CALLBACK to - * DUH_SIGRENDERER_ANALYSER_CALLBACK. (If you wanted to use this callback to - * apply a DSP effect, don't worry; there is a better way of doing this. It - * is undocumented, so contact me and I shall try to help. Contact details - * are in readme.txt.) - */ -#endif - -typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length); - -void duh_sigrenderer_set_analyser_callback( - DUH_SIGRENDERER *sigrenderer, - DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data -); - -int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer); -long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer); - -void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer, unsigned char id, long value); - -long duh_sigrenderer_get_samples( - DUH_SIGRENDERER *sigrenderer, - float volume, float delta, - long size, sample_t **samples -); - -void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples); - -void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer); - - -/* DUH Rendering Functions */ - -long duh_render( - DUH_SIGRENDERER *sigrenderer, - int bits, int unsign, - float volume, float delta, - long size, void *sptr -); - -#ifdef DUMB_DECLARE_DEPRECATED - -long duh_render_signal( - DUH_SIGRENDERER *sigrenderer, - float volume, float delta, - long size, sample_t **samples -) DUMB_DEPRECATED; -/* Please use duh_sigrenderer_get_samples(). Arguments and functionality are - * identical. - */ - -typedef DUH_SIGRENDERER DUH_RENDERER DUMB_DEPRECATED; -/* Please use DUH_SIGRENDERER instead of DUH_RENDERER. */ - -DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) DUMB_DEPRECATED; -/* Please use duh_start_sigrenderer() instead. Pass 0 for 'sig'. */ - -int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -long duh_renderer_get_position(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -/* Please use the duh_sigrenderer_*() equivalents of these two functions. */ - -void duh_end_renderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -/* Please use duh_end_sigrenderer() instead. */ - -DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) DUMB_DEPRECATED; -DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; -/* These functions have become no-ops that just return the parameter. - * So, for instance, replace - * duh_renderer_encapsulate_sigrenderer(my_sigrenderer) - * with - * my_sigrenderer - */ - -#endif - - -/* Impulse Tracker Support */ - -extern int dumb_it_max_to_mix; - -typedef struct DUMB_IT_SIGDATA DUMB_IT_SIGDATA; -typedef struct DUMB_IT_SIGRENDERER DUMB_IT_SIGRENDERER; - -DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh); -DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos); -DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer); - -DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder); - -void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); -void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); -void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char byte), void *data); - -int dumb_it_callback_terminate(void *data); -int dumb_it_callback_midi_block(void *data, int channel, unsigned char byte); - -DUH *dumb_load_it(const char *filename); -DUH *dumb_load_xm(const char *filename); -DUH *dumb_load_s3m(const char *filename); -DUH *dumb_load_mod(const char *filename); - -DUH *dumb_read_it(DUMBFILE *f); -DUH *dumb_read_xm(DUMBFILE *f); -DUH *dumb_read_s3m(DUMBFILE *f); -DUH *dumb_read_mod(DUMBFILE *f); - -int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd); - -int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv); - -int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv); - -int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed); - -int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd); -void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo); - -int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel); -void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume); - -int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr); -int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr); - -int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr); -void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv); - -int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr); -void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo); - -int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr); -void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed); - -#define DUMB_IT_N_CHANNELS 64 -#define DUMB_IT_N_NNA_CHANNELS 192 -#define DUMB_IT_TOTAL_CHANNELS (DUMB_IT_N_CHANNELS + DUMB_IT_N_NNA_CHANNELS) - -/* Channels passed to any of these functions are 0-based */ -int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel); -void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume); - -typedef struct DUMB_IT_CHANNEL_STATE DUMB_IT_CHANNEL_STATE; - -struct DUMB_IT_CHANNEL_STATE -{ - int channel; /* 0-based; meaningful for NNA channels */ - int sample; /* 1-based; 0 if nothing playing, then other fields undef */ - int freq; /* in Hz */ - float volume; /* 1.0 maximum; affected by ALL factors, inc. mixing vol */ - unsigned char pan; /* 0-64, 100 for surround */ - signed char subpan; /* use (pan + subpan/256.0f) or ((pan<<8)+subpan) */ - unsigned char filter_cutoff; /* 0-127 cutoff=127 AND resonance=0 */ - unsigned char filter_subcutoff; /* 0-255 -> no filters (subcutoff */ - unsigned char filter_resonance; /* 0-127 always 0 in this case) */ - /* subcutoff only changes from zero if filter envelopes are in use. The - * calculation (filter_cutoff + filter_subcutoff/256.0f) gives a more - * accurate filter cutoff measurement as a float. It would often be more - * useful to use a scaled int such as ((cutoff<<8) + subcutoff). - */ -}; - -/* Values of 64 or more will access NNA channels here. */ -void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state); - - -/* Signal Design Helper Values */ - -/* Use pow(DUMB_SEMITONE_BASE, n) to get the 'delta' value to transpose up by - * n semitones. To transpose down, use negative n. - */ -#define DUMB_SEMITONE_BASE 1.059463094359295309843105314939748495817 - -/* Use pow(DUMB_QUARTERTONE_BASE, n) to get the 'delta' value to transpose up - * by n quartertones. To transpose down, use negative n. - */ -#define DUMB_QUARTERTONE_BASE 1.029302236643492074463779317738953977823 - -/* Use pow(DUMB_PITCH_BASE, n) to get the 'delta' value to transpose up by n - * units. In this case, 256 units represent one semitone; 3072 units - * represent one octave. These units are used by the sequence signal (SEQU). - */ -#define DUMB_PITCH_BASE 1.000225659305069791926712241547647863626 - - -/* Signal Design Function Types */ - -typedef void sigdata_t; -typedef void sigrenderer_t; - -typedef sigdata_t *(*DUH_LOAD_SIGDATA)(DUH *duh, DUMBFILE *file); - -typedef sigrenderer_t *(*DUH_START_SIGRENDERER)( - DUH *duh, - sigdata_t *sigdata, - int n_channels, - long pos -); - -typedef void (*DUH_SIGRENDERER_SET_SIGPARAM)( - sigrenderer_t *sigrenderer, - unsigned char id, long value -); - -typedef long (*DUH_SIGRENDERER_GET_SAMPLES)( - sigrenderer_t *sigrenderer, - float volume, float delta, - long size, sample_t **samples -); - -typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)( - sigrenderer_t *sigrenderer, - float volume, - sample_t *samples -); - -typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer); - -typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata); - - -/* Signal Design Function Registration */ - -typedef struct DUH_SIGTYPE_DESC -{ - long type; - DUH_LOAD_SIGDATA load_sigdata; - DUH_START_SIGRENDERER start_sigrenderer; - DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam; - DUH_SIGRENDERER_GET_SAMPLES sigrenderer_get_samples; - DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample; - DUH_END_SIGRENDERER end_sigrenderer; - DUH_UNLOAD_SIGDATA unload_sigdata; -} -DUH_SIGTYPE_DESC; - -void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc); - - -// Decide where to put these functions; new heading? - -sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type); - -DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos); -sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type); - - -/* Sample Buffer Allocation Helpers */ - -sample_t **create_sample_buffer(int n_channels, long length); -void destroy_sample_buffer(sample_t **samples); - - -/* Silencing Helper */ - -void dumb_silence(sample_t *samples, long length); - - -/* Click Removal Helpers */ - -typedef struct DUMB_CLICK_REMOVER DUMB_CLICK_REMOVER; - -DUMB_CLICK_REMOVER *dumb_create_click_remover(void); -void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step); -void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, float halflife); -sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr); -void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr); - -DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n); -void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); -void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); -void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife); -void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset); -void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr); - - -/* Resampling Helpers */ - -#define DUMB_RQ_ALIASING 0 -#define DUMB_RQ_LINEAR 1 -#define DUMB_RQ_CUBIC 2 -#define DUMB_RQ_N_LEVELS 3 -extern int dumb_resampling_quality; - -typedef struct DUMB_RESAMPLER DUMB_RESAMPLER; - -typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data); - -struct DUMB_RESAMPLER -{ - sample_t *src; - long pos; - int subpos; - long start, end; - int dir; - DUMB_RESAMPLE_PICKUP pickup; - void *pickup_data; - int min_quality; - int max_quality; - /* Everything below this point is internal: do not use. */ - sample_t x[3]; - int overshot; -}; - -void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, long pos, long start, long end); -DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, long pos, long start, long end); -long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta); -sample_t dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, float volume); -void dumb_end_resampler(DUMB_RESAMPLER *resampler); - - -/* DUH Construction */ - -DUH *make_duh( - long length, - int n_signals, - DUH_SIGTYPE_DESC *desc[], - sigdata_t *sigdata[] -); - - -#ifdef __cplusplus - } -#endif - - -#endif /* DUMB_H */ diff --git a/Engine/libsrc/dumb-0.9.2/include/internal/aldumb.h b/Engine/libsrc/dumb-0.9.2/include/internal/aldumb.h deleted file mode 100644 index a0c6d63c075..00000000000 --- a/Engine/libsrc/dumb-0.9.2/include/internal/aldumb.h +++ /dev/null @@ -1,27 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * internal/aldumb.h - The internal header file / / \ \ - * for DUMB with Allegro. | < / \_ - * | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#ifndef INTERNAL_ALDUMB_H -#define INTERNAL_ALDUMB_H - - -void _dat_unload_duh(void *duh); - - -#endif /* INTERNAL_DUMB_H */ diff --git a/Engine/libsrc/dumb-0.9.2/include/internal/dumb.h b/Engine/libsrc/dumb-0.9.2/include/internal/dumb.h deleted file mode 100644 index b4cd0ab1c4d..00000000000 --- a/Engine/libsrc/dumb-0.9.2/include/internal/dumb.h +++ /dev/null @@ -1,58 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * internal/dumb.h - DUMB's internal declarations. / / \ \ - * | < / \_ - * This header file provides access to the | \/ /\ / - * internal structure of DUMB, and is liable \_ / > / - * to change, mutate or cease to exist at any | \ / / - * moment. Include it at your own peril. | ' / - * \__/ - * ... - * - * I mean it, people. You don't need access to anything in this file. If you - * disagree, contact the authors. In the unlikely event that you make a good - * case, we'll add what you need to dumb.h. Thanking you kindly. - */ - -#ifndef INTERNAL_DUMB_H -#define INTERNAL_DUMB_H - - -typedef struct DUH_SIGTYPE_DESC_LINK -{ - struct DUH_SIGTYPE_DESC_LINK *next; - DUH_SIGTYPE_DESC *desc; -} -DUH_SIGTYPE_DESC_LINK; - - -typedef struct DUH_SIGNAL -{ - sigdata_t *sigdata; - DUH_SIGTYPE_DESC *desc; -} -DUH_SIGNAL; - - -struct DUH -{ - long length; - - int n_signals; - DUH_SIGNAL **signal; -}; - - -DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type); - - -#endif /* INTERNAL_DUMB_H */ - diff --git a/Engine/libsrc/dumb-0.9.2/include/internal/it.h b/Engine/libsrc/dumb-0.9.2/include/internal/it.h deleted file mode 100644 index 7fffed6e6ba..00000000000 --- a/Engine/libsrc/dumb-0.9.2/include/internal/it.h +++ /dev/null @@ -1,710 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * internal/it.h - Internal stuff for IT playback / / \ \ - * and MOD/XM/S3M conversion. | < / \_ - * | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#ifndef INTERNAL_IT_H -#define INTERNAL_IT_H - - - -#include - - - -/** TO DO: THINK ABOUT THE FOLLOWING: - -sigdata->flags & IT_COMPATIBLE_GXX - - Bit 5: On = Link Effect G's memory with Effect E/F. Also - Gxx with an instrument present will cause the - envelopes to be retriggered. If you change a - sample on a row with Gxx, it'll adjust the - frequency of the current note according to: - - NewFrequency = OldFrequency * NewC5 / OldC5; -*/ - - - -/* These #defines are TEMPORARY. They are used to write alternative code to - * handle ambiguities in the format specification. The correct code in each - * case will be determined most likely by experimentation. - */ -#define STEREO_SAMPLES_COUNT_AS_TWO -#define INVALID_ORDERS_END_SONG -#define INVALID_NOTES_CAUSE_NOTE_CUT -#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP -#define VOLUME_OUT_OF_RANGE_SETS_MAXIMUM - - - -#define SIGTYPE_IT DUMB_ID('I', 'T', ' ', ' ') - -#define IT_SIGNATURE DUMB_ID('I', 'M', 'P', 'M') -#define IT_INSTRUMENT_SIGNATURE DUMB_ID('I', 'M', 'P', 'I') -#define IT_SAMPLE_SIGNATURE DUMB_ID('I', 'M', 'P', 'S') - - - -/* 1 minute per 4 rows, each row 6 ticks; this is divided by the tempo to get - * the interval between ticks. - */ -#define TICK_TIME_DIVIDEND ((65536 * 60) / (4 * 6)) - - - -/* I'm not going to try to explain this, because I didn't derive it very - * formally ;) - */ -/* #define AMIGA_DIVISOR ((float)(4.0 * 14317056.0)) */ -/* I believe the following one to be more accurate. */ -#define AMIGA_DIVISOR ((float)(8.0 * 7159090.5)) - - - -typedef struct IT_MIDI IT_MIDI; -typedef struct IT_FILTER_STATE IT_FILTER_STATE; -typedef struct IT_ENVELOPE IT_ENVELOPE; -typedef struct IT_INSTRUMENT IT_INSTRUMENT; -typedef struct IT_SAMPLE IT_SAMPLE; -typedef struct IT_ENTRY IT_ENTRY; -typedef struct IT_PATTERN IT_PATTERN; -typedef struct IT_PLAYING_ENVELOPE IT_PLAYING_ENVELOPE; -typedef struct IT_PLAYING IT_PLAYING; -typedef struct IT_CHANNEL IT_CHANNEL; -typedef struct IT_CHECKPOINT IT_CHECKPOINT; -typedef struct IT_CALLBACKS IT_CALLBACKS; - - - -struct IT_MIDI -{ - unsigned char SFmacro[16][16]; // read these from 0x120 - unsigned char SFmacrolen[16]; - unsigned short SFmacroz[16]; /* Bitfield; bit 0 set = z in first position */ - unsigned char Zmacro[128][16]; // read these from 0x320 - unsigned char Zmacrolen[128]; -}; - - - -struct IT_FILTER_STATE -{ - float currsample, prevsample; -}; - - - -#define IT_ENVELOPE_ON 1 -#define IT_ENVELOPE_LOOP_ON 2 -#define IT_ENVELOPE_SUSTAIN_LOOP 4 -#define IT_ENVELOPE_PITCH_IS_FILTER 128 - -struct IT_ENVELOPE -{ - unsigned char flags; - unsigned char n_nodes; - unsigned char loop_start; - unsigned char loop_end; - unsigned char sus_loop_start; - unsigned char sus_loop_end; - signed char node_y[25]; - unsigned short node_t[25]; -}; - - - -#define NNA_NOTE_CUT 0 -#define NNA_NOTE_CONTINUE 1 -#define NNA_NOTE_OFF 2 -#define NNA_NOTE_FADE 3 - -#define DCT_OFF 0 -#define DCT_NOTE 1 -#define DCT_SAMPLE 2 -#define DCT_INSTRUMENT 3 - -#define DCA_NOTE_CUT 0 -#define DCA_NOTE_OFF 1 -#define DCA_NOTE_FADE 2 - -struct IT_INSTRUMENT -{ - int fadeout; - - IT_ENVELOPE volume_envelope; - IT_ENVELOPE pan_envelope; - IT_ENVELOPE pitch_envelope; - - unsigned char new_note_action; - unsigned char dup_check_type; - unsigned char dup_check_action; - unsigned char pp_separation; - unsigned char pp_centre; - unsigned char global_volume; - unsigned char default_pan; - unsigned char random_volume; - unsigned char random_pan; - - unsigned char filter_cutoff; - unsigned char filter_resonance; - - unsigned char map_note[120]; - unsigned short map_sample[120]; -}; - - - -#define IT_SAMPLE_EXISTS 1 -#define IT_SAMPLE_16BIT 2 -#define IT_SAMPLE_STEREO 4 -#define IT_SAMPLE_LOOP 16 -#define IT_SAMPLE_SUS_LOOP 32 -#define IT_SAMPLE_PINGPONG_LOOP 64 -#define IT_SAMPLE_PINGPONG_SUS_LOOP 128 - -#define IT_VIBRATO_SINE 0 -#define IT_VIBRATO_SAWTOOTH 1 /* Ramp down */ -#define IT_VIBRATO_SQUARE 2 -#define IT_VIBRATO_RANDOM 3 - -struct IT_SAMPLE -{ - unsigned char flags; - unsigned char global_volume; - unsigned char default_volume; - unsigned char default_pan; - - long length; - long loop_start; - long loop_end; - long C5_speed; - long sus_loop_start; - long sus_loop_end; - - unsigned char vibrato_speed; - unsigned char vibrato_depth; - unsigned char vibrato_rate; - unsigned char vibrato_waveform; - - sample_t *left; - sample_t *right; -}; - - - -#define IT_ENTRY_NOTE 1 -#define IT_ENTRY_INSTRUMENT 2 -#define IT_ENTRY_VOLPAN 4 -#define IT_ENTRY_EFFECT 8 - -#define IT_SET_END_ROW(entry) ((entry)->channel = 255) -#define IT_IS_END_ROW(entry) ((entry)->channel >= DUMB_IT_N_CHANNELS) - -#define IT_NOTE_OFF 255 -#define IT_NOTE_CUT 254 - -#define IT_ENVELOPE_SHIFT 8 - -#define IT_SURROUND 100 -#define IT_IS_SURROUND(pan) ((pan) > 64) -#define IT_IS_SURROUND_SHIFTED(pan) ((pan) > 64 << IT_ENVELOPE_SHIFT) - -#define IT_SET_SPEED 1 -#define IT_JUMP_TO_ORDER 2 -#define IT_BREAK_TO_ROW 3 -#define IT_VOLUME_SLIDE 4 -#define IT_PORTAMENTO_DOWN 5 -#define IT_PORTAMENTO_UP 6 -#define IT_TONE_PORTAMENTO 7 -#define IT_VIBRATO 8 -#define IT_TREMOR 9 -#define IT_ARPEGGIO 10 -#define IT_VOLSLIDE_VIBRATO 11 -#define IT_VOLSLIDE_TONEPORTA 12 -#define IT_SET_CHANNEL_VOLUME 13 -#define IT_CHANNEL_VOLUME_SLIDE 14 -#define IT_SET_SAMPLE_OFFSET 15 -#define IT_PANNING_SLIDE 16 -#define IT_RETRIGGER_NOTE 17 -#define IT_TREMOLO 18 -#define IT_S 19 -#define IT_SET_SONG_TEMPO 20 -#define IT_FINE_VIBRATO 21 -#define IT_SET_GLOBAL_VOLUME 22 -#define IT_GLOBAL_VOLUME_SLIDE 23 -#define IT_SET_PANNING 24 -#define IT_PANBRELLO 25 -#define IT_MIDI_MACRO 26 //see MIDI.TXT - -/* Some effects needed for XM compatibility */ -#define IT_XM_PORTAMENTO_DOWN 27 -#define IT_XM_PORTAMENTO_UP 28 -#define IT_XM_FINE_VOLSLIDE_DOWN 29 -#define IT_XM_FINE_VOLSLIDE_UP 30 -#define IT_XM_RETRIGGER_NOTE 31 - -#define IT_N_EFFECTS 32 - -/* These represent the top nibble of the command value. */ -#define IT_S_SET_FILTER 0 /* Greyed out in IT... */ -#define IT_S_SET_GLISSANDO_CONTROL 1 /* Greyed out in IT... */ -#define IT_S_FINETUNE 2 /* Greyed out in IT... */ -#define IT_S_SET_VIBRATO_WAVEFORM 3 -#define IT_S_SET_TREMOLO_WAVEFORM 4 -#define IT_S_SET_PANBRELLO_WAVEFORM 5 -#define IT_S_FINE_PATTERN_DELAY 6 -#define IT_S7 7 -#define IT_S_SET_PAN 8 -#define IT_S_SET_SURROUND_SOUND 9 -#define IT_S_SET_HIGH_OFFSET 10 -#define IT_S_PATTERN_LOOP 11 -#define IT_S_DELAYED_NOTE_CUT 12 -#define IT_S_NOTE_DELAY 13 -#define IT_S_PATTERN_DELAY 14 -#define IT_S_SET_MIDI_MACRO 15 - -/* -S0x Set filter -S1x Set glissando control -S2x Set finetune - - -S3x Set vibrato waveform to type x -S4x Set tremelo waveform to type x -S5x Set panbrello waveform to type x - Waveforms for commands S3x, S4x and S5x: - 0: Sine wave - 1: Ramp down - 2: Square wave - 3: Random wave -S6x Pattern delay for x ticks -S70 Past note cut -S71 Past note off -S72 Past note fade -S73 Set NNA to note cut -S74 Set NNA to continue -S75 Set NNA to note off -S76 Set NNA to note fade -S77 Turn off volume envelope -S78 Turn on volume envelope -S79 Turn off panning envelope -S7A Turn on panning envelope -S7B Turn off pitch envelope -S7C Turn on pitch envelope -S8x Set panning position -S91 Set surround sound -SAy Set high value of sample offset yxx00h -SB0 Set loopback point -SBx Loop x times to loopback point -SCx Note cut after x ticks -SDx Note delay for x ticks -SEx Pattern delay for x rows -SFx Set parameterised MIDI Macro -*/ - -struct IT_ENTRY -{ - unsigned char channel; /* End of row if channel >= DUMB_IT_N_CHANNELS */ - unsigned char mask; - unsigned char note; - unsigned char instrument; - unsigned char volpan; - unsigned char effect; - unsigned char effectvalue; -}; - - - -struct IT_PATTERN -{ - int n_rows; - int n_entries; - IT_ENTRY *entry; -}; - - - -#define IT_STEREO 1 -#define IT_USE_INSTRUMENTS 4 -#define IT_LINEAR_SLIDES 8 /* If not set, use Amiga slides */ -#define IT_OLD_EFFECTS 16 -#define IT_COMPATIBLE_GXX 32 - -/* Make sure IT_WAS_AN_XM and IT_WAS_A_MOD aren't set accidentally */ -#define IT_REAL_FLAGS 63 - -#define IT_WAS_AN_XM 64 /* Set for both XMs and MODs */ -#define IT_WAS_A_MOD 128 - -#define IT_ORDER_END 255 -#define IT_ORDER_SKIP 254 - -struct DUMB_IT_SIGDATA -{ - int n_orders; - int n_instruments; - int n_samples; - int n_patterns; - - int flags; - - int global_volume; - int mixing_volume; - int speed; - int tempo; - int pan_separation; - - unsigned char channel_pan[DUMB_IT_N_CHANNELS]; - unsigned char channel_volume[DUMB_IT_N_CHANNELS]; - - unsigned char *order; - unsigned char restart_position; /* for XM compatiblity */ - - IT_INSTRUMENT *instrument; - IT_SAMPLE *sample; - IT_PATTERN *pattern; - - IT_MIDI *midi; - - IT_CHECKPOINT *checkpoint; -}; - - - -struct IT_PLAYING_ENVELOPE -{ - int next_node; - int tick; -}; - - - -#define IT_PLAYING_BACKGROUND 1 -#define IT_PLAYING_SUSTAINOFF 2 -#define IT_PLAYING_FADING 4 -#define IT_PLAYING_DEAD 8 - -struct IT_PLAYING -{ - int flags; - - IT_CHANNEL *channel; - IT_SAMPLE *sample; - IT_INSTRUMENT *instrument; - IT_INSTRUMENT *env_instrument; - - unsigned short sampnum; - unsigned char instnum; - - unsigned char channel_volume; - - unsigned char volume; - unsigned short pan; - - unsigned char note; - - unsigned char filter_cutoff; - unsigned char filter_resonance; - - unsigned short true_filter_cutoff; /* These incorporate the filter envelope, and will not */ - unsigned char true_filter_resonance; /* be changed if they would be set to 127<<8 and 0. */ - - unsigned char vibrato_speed; - unsigned char vibrato_depth; - unsigned char vibrato_n; /* May be specified twice: volpan & effect. */ - unsigned char vibrato_time; - - unsigned char tremolo_speed; - unsigned char tremolo_depth; - unsigned char tremolo_time; - - unsigned char sample_vibrato_time; - int sample_vibrato_depth; /* Starts at rate?0:depth, increases by rate */ - - int slide; - float delta; - - IT_PLAYING_ENVELOPE volume_envelope; - IT_PLAYING_ENVELOPE pan_envelope; - IT_PLAYING_ENVELOPE pitch_envelope; - - int fadeoutcount; - - IT_FILTER_STATE filter_state[2]; /* Left and right */ - - DUMB_RESAMPLER resampler[2]; - - /* time_lost is used to emulate Impulse Tracker's sample looping - * characteristics. When time_lost is added to pos, the result represents - * the position in the theoretical version of the sample where all loops - * have been expanded. If this is stored, the resampling helpers will - * safely convert it for use with new loop boundaries. The situation is - * slightly more complicated if dir == -1 when the change takes place; we - * must reflect pos off the loop end point and set dir to 1 before - * proceeding. - */ - long time_lost; -}; - - - -#define IT_CHANNEL_MUTED 1 - -struct IT_CHANNEL -{ - int flags; - - unsigned char volume; - signed char volslide; - signed char xm_volslide; - - /* xm_volslide is used for volume slides done in the volume column in an - * XM file, since it seems the volume column slide is applied first, - * followed by clamping, followed by the effects column slide. IT does - * not exhibit this behaviour, so xm_volslide is maintained at zero. - */ - - unsigned char pan; - unsigned short truepan; - - unsigned char channelvolume; - signed char channelvolslide; - - unsigned char instrument; - unsigned char note; - - unsigned char SFmacro; - - unsigned char filter_cutoff; - unsigned char filter_resonance; - - unsigned char note_cut_count; - unsigned char note_delay_count; - IT_ENTRY *note_delay_entry; - - int arpeggio; - unsigned char retrig; - unsigned char xm_retrig; - int retrig_tick; - - unsigned char tremor; - unsigned char tremor_time; /* Bit 6 set if note on; bit 7 set if tremor active. */ - - int portamento; - int toneporta; - unsigned char destnote; - - /** WARNING - for neatness, should one or both of these be in the IT_PLAYING struct? */ - unsigned short sample; - unsigned char truenote; - - unsigned char midi_state; - - signed char lastvolslide; - unsigned char lastDKL; - unsigned char lastEF; /* Doubles as last portamento up for XM files */ - unsigned char lastG; - unsigned char lastHspeed; - unsigned char lastHdepth; - unsigned char lastRspeed; - unsigned char lastRdepth; - unsigned char lastI; - unsigned char lastJ; /* Doubles as last portamento down for XM files */ - unsigned char lastN; - unsigned char lastO; - unsigned char high_offset; - unsigned char lastQ; - unsigned char lastS; - unsigned char pat_loop_row; - unsigned char pat_loop_count; - unsigned char lastW; - - unsigned char xm_lastE1; - unsigned char xm_lastE2; - unsigned char xm_lastEA; - unsigned char xm_lastEB; - unsigned char xm_lastX1; - unsigned char xm_lastX2; - - IT_PLAYING *playing; -}; - - - -struct DUMB_IT_SIGRENDERER -{ - DUMB_IT_SIGDATA *sigdata; - - int n_channels; - - unsigned char globalvolume; - signed char globalvolslide; - - unsigned char tempo; - signed char temposlide; - - IT_CHANNEL channel[DUMB_IT_N_CHANNELS]; - - IT_PLAYING *playing[DUMB_IT_N_NNA_CHANNELS]; - - int tick; - int speed; - int rowcount; - - int order; /* Set to -1 if the song is terminated by a callback. */ - int row; - int processorder; - int processrow; - int breakrow; - int pat_loop_row; - - int n_rows; - - IT_ENTRY *entry_start; - IT_ENTRY *entry; - IT_ENTRY *entry_end; - - long time_left; /* Time before the next tick is processed */ - int sub_time_left; - - DUMB_CLICK_REMOVER **click_remover; - - IT_CALLBACKS *callbacks; -}; - - - -struct IT_CHECKPOINT -{ - IT_CHECKPOINT *next; - long time; - DUMB_IT_SIGRENDERER *sigrenderer; -}; - - - -struct IT_CALLBACKS -{ - int (*loop)(void *data); - void *loop_data; - /* Return 1 to prevent looping; the music will terminate abruptly. If you - * want to make the music stop but allow samples to fade (beware, as they - * might not fade at all!), use dumb_it_sr_set_speed() and set the speed - * to 0. Note that xm_speed_zero() will not be called if you set the - * speed manually, and also that this will work for IT and S3M files even - * though the music can't stop in this way by itself. - */ - - int (*xm_speed_zero)(void *data); - void *xm_speed_zero_data; - /* Return 1 to terminate the mod, without letting samples fade. */ - - int (*midi)(void *data, int channel, unsigned char byte); - void *midi_data; - /* Return 1 to prevent DUMB from subsequently interpreting the MIDI bytes - * itself. In other words, return 1 if the Zxx macros in an IT file are - * controlling filters and shouldn't be. - */ -}; - - - -void _dumb_it_end_sigrenderer(sigrenderer_t *sigrenderer); -void _dumb_it_unload_sigdata(sigdata_t *vsigdata); - -extern DUH_SIGTYPE_DESC _dumb_sigtype_it; - - - -long _dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata); - - - -#define XM_APPREGIO 0 -#define XM_PORTAMENTO_UP 1 -#define XM_PORTAMENTO_DOWN 2 -#define XM_TONE_PORTAMENTO 3 -#define XM_VIBRATO 4 -#define XM_VOLSLIDE_TONEPORTA 5 -#define XM_VOLSLIDE_VIBRATO 6 -#define XM_TREMOLO 7 -#define XM_SET_PANNING 8 -#define XM_SAMPLE_OFFSET 9 -#define XM_VOLUME_SLIDE 10 /* A */ -#define XM_POSITION_JUMP 11 /* B */ -#define XM_SET_CHANNEL_VOLUME 12 /* C */ -#define XM_PATTERN_BREAK 13 /* D */ -#define XM_E 14 /* E */ -#define XM_SET_TEMPO_BPM 15 /* F */ -#define XM_SET_GLOBAL_VOLUME 16 /* G */ -#define XM_GLOBAL_VOLUME_SLIDE 17 /* H */ -#define XM_KEY_OFF 20 /* K (undocumented) */ -#define XM_SET_ENVELOPE_POSITION 21 /* L */ -#define XM_PANNING_SLIDE 25 /* P */ -#define XM_MULTI_RETRIG 27 /* R */ -#define XM_TREMOR 29 /* T */ -#define XM_X 33 /* X */ -#define XM_N_EFFECTS (10+26) - -#define XM_E_SET_FILTER 0x0 -#define XM_E_FINE_PORTA_UP 0x1 -#define XM_E_FINE_PORTA_DOWN 0x2 -#define XM_E_SET_GLISSANDO_CONTROL 0x3 -#define XM_E_SET_VIBRATO_CONTROL 0x4 -#define XM_E_SET_FINETUNE 0x5 -#define XM_E_SET_LOOP 0x6 -#define XM_E_SET_TREMOLO_CONTROL 0x7 -#define XM_E_RETRIG_NOTE 0x9 -#define XM_E_FINE_VOLSLIDE_UP 0xA -#define XM_E_FINE_VOLSLIDE_DOWN 0xB -#define XM_E_NOTE_CUT 0xC -#define XM_E_NOTE_DELAY 0xD -#define XM_E_PATTERN_DELAY 0xE - -#define XM_X_EXTRAFINE_PORTA_UP 1 -#define XM_X_EXTRAFINE_PORTA_DOWN 2 - -/* To make my life a bit simpler during conversion, effect E:xy is converted - * to effect number EBASE+x:y. The same applies to effect X, and IT's S. That - * way, these effects can be manipulated like regular effects. - */ -#define EBASE (XM_N_EFFECTS) -#define XBASE (EBASE+16) -#define SBASE (IT_N_EFFECTS) - -#define EFFECT_VALUE(x, y) (((x)<<4)|(y)) -#define HIGH(v) ((v)>>4) -#define LOW(v) ((v)&0x0F) -#define SET_HIGH(v, x) v = (((x)<<4)|((v)&0x0F)) -#define SET_LOW(v, y) v = (((v)&0xF0)|(y)) -#define BCD_TO_NORMAL(v) (HIGH(v)*10+LOW(v)) - - - -#if 0 -unsigned char **_dumb_malloc2(int w, int h); -void _dumb_free2(unsigned char **line); -#endif - -void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry); -int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata); - - - -#endif /* INTERNAL_IT_H */ diff --git a/Engine/libsrc/dumb-0.9.2/it/itload.c b/Engine/libsrc/dumb-0.9.2/it/itload.c deleted file mode 100644 index a377619a88a..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/itload.c +++ /dev/null @@ -1,43 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * itload.c - Code to read an Impulse Tracker / / \ \ - * file, opening and closing it for | < / \_ - * you. | \/ /\ / - * \_ / > / - * By entheh. Don't worry Bob, you're credited | \ / / - * in itread.c! | ' / - * \__/ - */ - -#include "dumb.h" -#include "internal/it.h" - - - -/* dumb_load_it(): loads an IT file into a DUH struct, returning a pointer to - * the DUH struct. When you have finished with it, you must pass the pointer - * to unload_duh() so that the memory can be freed. - */ -DUH *dumb_load_it(const char *filename) -{ - DUH *duh; - DUMBFILE *f = dumbfile_open(filename); - - if (!f) - return NULL; - - duh = dumb_read_it(f); - - dumbfile_close(f); - - return duh; -} - diff --git a/Engine/libsrc/dumb-0.9.2/it/itmisc.c b/Engine/libsrc/dumb-0.9.2/it/itmisc.c deleted file mode 100644 index b69a64df109..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/itmisc.c +++ /dev/null @@ -1,175 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * itmisc.c - Miscellaneous functions relating / / \ \ - * to module files. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include "dumb.h" -#include "internal/it.h" - - - -DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh) -{ - return duh_get_raw_sigdata(duh, 0, SIGTYPE_IT); -} - - - -int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd) -{ - return sd ? sd->n_orders : 0; -} - - - -int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd) -{ - return sd ? sd->global_volume : 0; -} - - - -void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv) -{ - if (sd) sd->global_volume = gv; -} - - - -int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd) -{ - return sd ? sd->mixing_volume : 0; -} - - - -void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv) -{ - if (sd) sd->mixing_volume = mv; -} - - - -int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd) -{ - return sd ? sd->speed : 0; -} - - - -void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed) -{ - if (sd) sd->speed = speed; -} - - - -int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd) -{ - return sd ? sd->tempo : 0; -} - - - -void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo) -{ - if (sd) sd->tempo = tempo; -} - - - -int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel) -{ - ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS); - return sd ? sd->channel_volume[channel] : 0; -} - -void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume) -{ - ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS); - if (sd) sd->channel_volume[channel] = volume; -} - - - -int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr) -{ - return sr ? sr->order : -1; -} - - - -int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr) -{ - return sr ? sr->row : -1; -} - - - -int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr) -{ - return sr ? sr->globalvolume : 0; -} - - - -void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv) -{ - if (sr) sr->globalvolume = gv; -} - - - -int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr) -{ - return sr ? sr->tempo : 0; -} - - - -void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo) -{ - if (sr) sr->tempo = tempo; -} - - - -int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr) -{ - return sr ? sr->speed : 0; -} - - - -void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed) -{ - if (sr) sr->speed = speed; -} - - - -int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel) -{ - return sr ? sr->channel[channel].channelvolume : 0; -} - - - -void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume) -{ - if (sr) sr->channel[channel].channelvolume = volume; -} diff --git a/Engine/libsrc/dumb-0.9.2/it/itorder.c b/Engine/libsrc/dumb-0.9.2/it/itorder.c deleted file mode 100644 index 6959f054433..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/itorder.c +++ /dev/null @@ -1,63 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * itorder.c - Code to fix invalid patterns in / / \ \ - * the pattern table. | < / \_ - * | \/ /\ / - * By Julien Cugniere. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - - - -#include - -#include "dumb.h" -#include "internal/it.h" - - - -/* This function ensures that any pattern mentioned in the order table but - * not present in the pattern table is treated as an empty 64 rows pattern. - * This is done by adding such a dummy pattern at the end of the pattern - * table, and redirect invalid orders to it. - * Patterns 254 and 255 are left untouched, unless the signal is an XM. - */ -int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata) -{ - int i; - int found_some = 0; - - int first_invalid = sigdata->n_patterns; - int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253; - - for (i = 0; i < sigdata->n_orders; i++) { - if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) { - sigdata->order[i] = sigdata->n_patterns; - found_some = 1; - } - } - - if (found_some) { - IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1)); - if (!new_pattern) - return -1; - - new_pattern[sigdata->n_patterns].n_rows = 64; - new_pattern[sigdata->n_patterns].n_entries = 0; - new_pattern[sigdata->n_patterns].entry = NULL; - sigdata->pattern = new_pattern; - sigdata->n_patterns++; - } - - return 0; -} diff --git a/Engine/libsrc/dumb-0.9.2/it/itread.c b/Engine/libsrc/dumb-0.9.2/it/itread.c deleted file mode 100644 index 472b361872c..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/itread.c +++ /dev/null @@ -1,1179 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * itread.c - Code to read an Impulse Tracker / / \ \ - * module from an open file. | < / \_ - * | \/ /\ / - * Based on the loader from an IT player by Bob. \_ / > / - * Adapted for DUMB by entheh. | \ / / - * | ' / - * \__/ - */ - -#include -#include //might not be necessary later; required for memset - -#include "dumb.h" -#include "internal/it.h" - - - -#define INVESTIGATE_OLD_INSTRUMENTS - - - -static int it_seek(DUMBFILE *f, long offset) -{ - long pos = dumbfile_pos(f); - - if (pos > offset) - return -1; - - if (pos < offset) - if (dumbfile_skip(f, offset - pos)) - return -1; - - return 0; -} - - - -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long dword; - - - -static unsigned char *sourcebuf = NULL; -static unsigned char *sourcepos = NULL; -static unsigned char *sourceend; -static int rembits = 0; - - - -static int readblock(DUMBFILE *f) -{ - long size; - int c; - - size = dumbfile_igetw(f); - if (size < 0) - return size; - - sourcebuf = malloc(size); - if (!sourcebuf) - return -1; - - c = dumbfile_getnc((char *)sourcebuf, size, f); - if (c < size) { - free(sourcebuf); - sourcebuf = NULL; - return -1; - } - - sourcepos = sourcebuf; - sourceend = sourcebuf + size; - rembits = 8; - return 0; -} - - - -static void freeblock(void) -{ - free(sourcebuf); - sourcebuf = NULL; -} - - - -static int readbits(int bitwidth) -{ - int val = 0; - int b = 0; - - if (sourcepos >= sourceend) return val; - - while (bitwidth > rembits) { - val |= *sourcepos++ << b; - if (sourcepos >= sourceend) return val; - b += rembits; - bitwidth -= rembits; - rembits = 8; - } - - val |= (*sourcepos & ((1 << bitwidth) - 1)) << b; - *sourcepos >>= bitwidth; - rembits -= bitwidth; - - return val; -} - - - -/** WARNING - do we even need to pass `right`? */ -/** WARNING - why bother memsetting at all? The whole array is written... */ -// if we do memset, dumb_silence() would be neater... -static int decompress8(DUMBFILE *f, sample_t *left, sample_t *right, int len, int cmwt) -{ - int blocklen, blockpos; - byte bitwidth; - word val; - char d1, d2; - - memset(left, 0, len * sizeof(*left)); - if (right) { - memset(right, 0, len * sizeof(*right)); - len <<= 1; - } - - while (len > 0) { - //Read a block of compressed data: - if (readblock(f)) - return -1; - //Set up a few variables - blocklen = (len < 0x8000) ? len : 0x8000; //Max block length is 0x8000 bytes - blockpos = 0; - bitwidth = 9; - d1 = d2 = 0; - //Start the decompression: - while (blockpos < blocklen) { - //Read a value: - val = (word)readbits(bitwidth); - //Check for bit width change: - - if (bitwidth < 7) { //Method 1: - if (val == (1 << (bitwidth - 1))) { - val = (word)readbits(3) + 1; - bitwidth = (val < bitwidth) ? val : val + 1; - continue; - } - } - else if (bitwidth < 9) { //Method 2 - byte border = (0xFF >> (9 - bitwidth)) - 4; - - if (val > border && val <= (border + 8)) { - val -= border; - bitwidth = (val < bitwidth) ? val : val + 1; - continue; - } - } - else if (bitwidth == 9) { //Method 3 - if (val & 0x100) { - bitwidth = (val + 1) & 0xFF; - continue; - } - } - else { //Illegal width, abort ? - freeblock(); - return -1; - } - - //Expand the value to signed byte: - { - char v; //The sample value: - if (bitwidth < 8) { - byte shift = 8 - bitwidth; - v = (val << shift); - v >>= shift; - } - else - v = (char)val; - - //And integrate the sample value - //(It always has to end with integration doesn't it ? ;-) - d1 += v; - d2 += d1; - } - - //Store ! - /* Version 2.15 was an unofficial version with hacked compression - * code. Yay, better compression :D - */ - if (right && (len & 1)) - *right++ = (int)(signed char)(cmwt == 0x215 ? d2 : d1) << 16; - else - *left++ = (int)(signed char)(cmwt == 0x215 ? d2 : d1) << 16; - len--; - blockpos++; - } - freeblock(); - } - return 0; -} - - - -static int decompress16(DUMBFILE *f, sample_t *left, sample_t *right, int len, int cmwt) -{ - int blocklen, blockpos; - byte bitwidth; - long val; - short d1, d2; - - memset(left, 0, len * sizeof(*left)); - if (right) { - memset(right, 0, len * sizeof(*right)); - len <<= 1; - } - - while (len > 0) { - //Read a block of compressed data: - if (readblock(f)) - return -1; - //Set up a few variables - blocklen = (len < 0x4000) ? len : 0x4000; // Max block length is 0x4000 bytes - blockpos = 0; - bitwidth = 17; - d1 = d2 = 0; - //Start the decompression: - while (blockpos < blocklen) { - val = readbits(bitwidth); - //Check for bit width change: - - if (bitwidth < 7) { //Method 1: - if (val == (1 << (bitwidth - 1))) { - val = readbits(4) + 1; - bitwidth = (val < bitwidth) ? val : val + 1; - continue; - } - } - else if (bitwidth < 17) { //Method 2 - word border = (0xFFFF >> (17 - bitwidth)) - 8; - - if (val > border && val <= (border + 16)) { - val -= border; - bitwidth = val < bitwidth ? val : val + 1; - continue; - } - } - else if (bitwidth == 17) { //Method 3 - if (val & 0x10000) { - bitwidth = (val + 1) & 0xFF; - continue; - } - } - else { //Illegal width, abort ? - freeblock(); - return -1; - } - - //Expand the value to signed byte: - { - short v; //The sample value: - if (bitwidth < 16) { - byte shift = 16 - bitwidth; - v = (short)(val << shift); - v >>= shift; - } - else - v = (short)val; - - //And integrate the sample value - //(It always has to end with integration doesn't it ? ;-) - d1 += v; - d2 += d1; - } - - //Store ! - /* Version 2.15 was an unofficial version with hacked compression - * code. Yay, better compression :D - */ - if (right && (len & 1)) - *right++ = (int)(signed short)(cmwt == 0x215 ? d2 : d1) << 8; - else - *left++ = (int)(signed short)(cmwt == 0x215 ? d2 : d1) << 8; - len--; - blockpos++; - } - freeblock(); - } - return 0; -} - - - -static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f) -{ - int n; - - envelope->flags = dumbfile_getc(f); - envelope->n_nodes = dumbfile_getc(f); - envelope->loop_start = dumbfile_getc(f); - envelope->loop_end = dumbfile_getc(f); - envelope->sus_loop_start = dumbfile_getc(f); - envelope->sus_loop_end = dumbfile_getc(f); - for (n = 0; n < envelope->n_nodes; n++) { - envelope->node_y[n] = dumbfile_getc(f); - envelope->node_t[n] = dumbfile_igetw(f); - } - dumbfile_skip(f, 75 - envelope->n_nodes * 3 + 1); - - return dumbfile_error(f); -} - - - -static int it_read_old_instrument(IT_INSTRUMENT *instrument, DUMBFILE *f) -{ - int n; - - if (dumbfile_mgetl(f) != IT_INSTRUMENT_SIGNATURE) - return -1; - - /* Skip DOS Filename. */ - dumbfile_skip(f, 13); - - instrument->volume_envelope.flags = dumbfile_getc(f); - instrument->volume_envelope.loop_start = dumbfile_getc(f); - instrument->volume_envelope.loop_end = dumbfile_getc(f); - instrument->volume_envelope.sus_loop_start = dumbfile_getc(f); - instrument->volume_envelope.sus_loop_end = dumbfile_getc(f); - - /* Skip two unused bytes. */ - dumbfile_skip(f, 2); - - /* In the old instrument format, fadeout ranges from 0 to 64, and is - * subtracted at intervals from a value starting at 512. In the new - * format, all these values are doubled. Therefore we double when loading - * from the old instrument format - that way we don't have to think about - * it later. - */ - instrument->fadeout = dumbfile_igetw(f) << 1; - instrument->new_note_action = dumbfile_getc(f); - instrument->dup_check_type = dumbfile_getc(f); - instrument->dup_check_action = DCA_NOTE_CUT; // This might be wrong! - /** WARNING - what is the duplicate check action for old-style instruments? */ - - /* Skip Tracker Version and Number of Samples. These are only used in - * separate instrument files. Also skip unused bytes and Instrument Name. - */ - dumbfile_skip(f, 36); - - instrument->pp_separation = 0; - instrument->pp_centre = 60; - instrument->global_volume = 128; - /** WARNING - should global_volume be 64 or something? */ - instrument->default_pan = 32; - /** WARNING - should default_pan be 128, meaning don`t use? */ - instrument->random_volume = 0; - instrument->random_pan = 0; - - for (n = 0; n < 120; n++) { - instrument->map_note[n] = dumbfile_getc(f); - instrument->map_sample[n] = dumbfile_getc(f); - } - - /* Skip "Volume envelope (200 bytes)". */ - // - need to know better what this is for though. - dumbfile_skip(f, 200); - -#ifdef INVESTIGATE_OLD_INSTRUMENTS - fprintf(stderr, "Inst %02d Env:", n); -#endif - - for (n = 0; n < 25; n++) - { - instrument->volume_envelope.node_t[n] = dumbfile_getc(f); - instrument->volume_envelope.node_y[n] = dumbfile_getc(f); - -#ifdef INVESTIGATE_OLD_INSTRUMENTS - fprintf(stderr, " %d,%d", - instrument->volume_envelope.node_t[n], - instrument->volume_envelope.node_y[n]); -#endif - - // This loop is unfinished, as we can probably escape from it before - // the end if we want to. Hence the otherwise useless dumbfile_skip() - // call below. - } - dumbfile_skip(f, 50 - (n << 1)); - instrument->volume_envelope.n_nodes = n; - -#ifdef INVESTIGATE_OLD_INSTRUMENTS - fprintf(stderr, "\n"); -#endif - - if (dumbfile_error(f)) - return -1; - - instrument->filter_cutoff = 127; - instrument->filter_resonance = 0; - - instrument->pan_envelope.flags = 0; - instrument->pitch_envelope.flags = 0; - - return 0; -} - - - -static int it_read_instrument(IT_INSTRUMENT *instrument, DUMBFILE *f) -{ - int n; - - if (dumbfile_mgetl(f) != IT_INSTRUMENT_SIGNATURE) - return -1; - - /* Skip DOS Filename. */ - dumbfile_skip(f, 13); - - instrument->new_note_action = dumbfile_getc(f); - instrument->dup_check_type = dumbfile_getc(f); - instrument->dup_check_action = dumbfile_getc(f); - instrument->fadeout = dumbfile_igetw(f); - instrument->pp_separation = dumbfile_getc(f); - instrument->pp_centre = dumbfile_getc(f); - instrument->global_volume = dumbfile_getc(f); - instrument->default_pan = dumbfile_getc(f); - instrument->random_volume = dumbfile_getc(f); - instrument->random_pan = dumbfile_getc(f); - - /* Skip Tracker Version and Number of Samples. These are only used in - * separate instrument files. Also skip unused byte and Instrument Name. - */ - dumbfile_skip(f, 30); - - instrument->filter_cutoff = dumbfile_getc(f); - instrument->filter_resonance = dumbfile_getc(f); - - /* Skip MIDI Channel, Program and Bank. */ - dumbfile_skip(f, 4); - - for (n = 0; n < 120; n++) { - instrument->map_note[n] = dumbfile_getc(f); - instrument->map_sample[n] = dumbfile_getc(f); - } - - if (dumbfile_error(f)) - return -1; - - if (it_read_envelope(&instrument->volume_envelope, f)) return -1; - if (it_read_envelope(&instrument->pan_envelope, f)) return -1; - if (it_read_envelope(&instrument->pitch_envelope, f)) return -1; - - return 0; -} - - - -static int it_read_sample_header(IT_SAMPLE *sample, unsigned char *convert, long *offset, DUMBFILE *f) -{ - if (dumbfile_mgetl(f) != IT_SAMPLE_SIGNATURE) - return -1; - - /* Skip DOS Filename. */ - dumbfile_skip(f, 13); - - sample->global_volume = dumbfile_getc(f); - sample->flags = dumbfile_getc(f); - sample->default_volume = dumbfile_getc(f); - - /* Skip Sample Name. */ - dumbfile_skip(f, 26); - - *convert = dumbfile_getc(f); - sample->default_pan = dumbfile_getc(f); - sample->length = dumbfile_igetl(f); - sample->loop_start = dumbfile_igetl(f); - sample->loop_end = dumbfile_igetl(f); - sample->C5_speed = dumbfile_igetl(f); - sample->sus_loop_start = dumbfile_igetl(f); - sample->sus_loop_end = dumbfile_igetl(f); - -#ifdef STEREO_SAMPLES_COUNT_AS_TWO - if (sample->flags & IT_SAMPLE_STEREO) { - sample->length >>= 1; - sample->loop_start >>= 1; - sample->loop_end >>= 1; - sample->C5_speed >>= 1; - sample->sus_loop_start >>= 1; - sample->sus_loop_end >>= 1; - } -#endif - - if (sample->flags & IT_SAMPLE_EXISTS) { - if (sample->length <= 0) - sample->flags &= ~IT_SAMPLE_EXISTS; - else { - if ((unsigned int)sample->loop_end > (unsigned int)sample->length) - sample->flags &= ~IT_SAMPLE_LOOP; - else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end) - sample->flags &= ~IT_SAMPLE_LOOP; - - if ((unsigned int)sample->sus_loop_end > (unsigned int)sample->length) - sample->flags &= ~IT_SAMPLE_SUS_LOOP; - else if ((unsigned int)sample->sus_loop_start >= (unsigned int)sample->sus_loop_end) - sample->flags &= ~IT_SAMPLE_SUS_LOOP; - - /* We may be able to truncate the sample to save memory. */ - if (sample->flags & IT_SAMPLE_LOOP) { - if ((sample->flags & IT_SAMPLE_SUS_LOOP) && sample->sus_loop_end >= sample->loop_end) - sample->length = sample->sus_loop_end; - else - sample->length = sample->loop_end; - } - } - } - - *offset = dumbfile_igetl(f); - - sample->vibrato_speed = dumbfile_getc(f); - sample->vibrato_depth = dumbfile_getc(f); - sample->vibrato_rate = dumbfile_getc(f); - sample->vibrato_waveform = dumbfile_getc(f); - - return dumbfile_error(f); -} - - - -static long it_read_sample_data(int cmwt, IT_SAMPLE *sample, unsigned char convert, DUMBFILE *f) -{ - long n; - - sample->left = malloc(sample->length * sizeof(*sample->left)); - if (!sample->left) - return -1; - - if (sample->flags & IT_SAMPLE_STEREO) { - sample->right = malloc(sample->length * sizeof(*sample->right)); - if (!sample->right) - return -1; - } - - if (sample->flags & 8) { - /* If the sample is packed, then we must unpack it. */ - - /** WARNING - unresolved business here... test with ModPlug? */ - - if (sample->flags & IT_SAMPLE_STEREO) - exit(37); - -/* -//#ifndef STEREO_SAMPLES_COUNT_AS_TWO - ASSERT(!(sample->flags & IT_SAMPLE_STEREO)); -//#endif -*/ - if (sample->flags & IT_SAMPLE_16BIT) - decompress16(f, sample->left, sample->right, sample->length, cmwt); - else - decompress8(f, sample->left, sample->right, sample->length, cmwt); - } else if (sample->flags & IT_SAMPLE_STEREO) { - if (sample->flags & IT_SAMPLE_16BIT) { - if (convert & 2) { - for (n = 0; n < sample->length; n++) { - sample->left[n] = (int)(signed short)dumbfile_mgetw(f) << 8; - sample->right[n] = (int)(signed short)dumbfile_mgetw(f) << 8; - } - } else { - for (n = 0; n < sample->length; n++) { - sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8; - sample->right[n] = (int)(signed short)dumbfile_igetw(f) << 8; - } - } - } else { - for (n = 0; n < sample->length; n++) { - sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16; - sample->right[n] = (int)(signed char)dumbfile_getc(f) << 16; - } - } - } else if (sample->flags & IT_SAMPLE_16BIT) { - if (convert & 2) - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed short)dumbfile_mgetw(f) << 8; - else - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8; - } else - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16; - - if (dumbfile_error(f)) - return -1; - - if (!(convert & 1)) { - /* Convert to signed. */ - for (n = 0; n < sample->length; n++) - sample->left[n] ^= 0xFF800000; - - if (sample->right) - for (n = 0; n < sample->length; n++) - sample->right[n] ^= 0xFF800000; - } - - /* NOT SUPPORTED: - * - * convert & 4 - Samples stored as delta values - * convert & 16 - Samples stored as TX-Wave 12-bit values - * convert & 32 - Left/Right/All Stereo prompt - */ - - return 0; -} - - - -#define DETECT_DUPLICATE_CHANNELS -#ifdef DETECT_DUPLICATE_CHANNELS -#include -#endif -static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer) -{ - unsigned char cmask[DUMB_IT_N_CHANNELS]; - unsigned char cnote[DUMB_IT_N_CHANNELS]; - unsigned char cinstrument[DUMB_IT_N_CHANNELS]; - unsigned char cvolpan[DUMB_IT_N_CHANNELS]; - unsigned char ceffect[DUMB_IT_N_CHANNELS]; - unsigned char ceffectvalue[DUMB_IT_N_CHANNELS]; -#ifdef DETECT_DUPLICATE_CHANNELS - IT_ENTRY *dupentry[DUMB_IT_N_CHANNELS]; -#endif - - int n_entries = 0; - int buflen; - int bufpos = 0; - - IT_ENTRY *entry; - - unsigned char channel; - unsigned char mask; - - memset(cmask, 0, sizeof(cmask)); - memset(cnote, 0, sizeof(cnote)); - memset(cinstrument, 0, sizeof(cinstrument)); - memset(cvolpan, 0, sizeof(cvolpan)); - memset(ceffect, 0, sizeof(ceffect)); - memset(ceffectvalue, 0, sizeof(ceffectvalue)); -#ifdef DETECT_DUPLICATE_CHANNELS - { - int i; - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) dupentry[i] = NULL; - } -#endif - - buflen = dumbfile_igetw(f); - pattern->n_rows = dumbfile_igetw(f); - - /* Skip four unused bytes. */ - dumbfile_skip(f, 4); - - if (dumbfile_error(f)) - return -1; - - /* Read in the pattern data. */ - dumbfile_getnc(buffer, buflen, f); - - if (dumbfile_error(f)) - return -1; - - /* Scan the pattern data, and work out how many entries we need room for. */ - while (bufpos < buflen) { - unsigned char b = buffer[bufpos++]; - - if (b == 0) { - /* End of row */ - n_entries++; - continue; - } - - channel = (b - 1) & 63; - - if (b & 128) - cmask[channel] = mask = buffer[bufpos++]; - else - mask = cmask[channel]; - - { - static const unsigned char used[16] = {0, 1, 1, 2, 1, 2, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5}; - n_entries += (mask != 0); - bufpos += used[mask & 15]; - } - } - - pattern->n_entries = n_entries; - - pattern->entry = malloc(n_entries * sizeof(*pattern->entry)); - - if (!pattern->entry) - return -1; - - bufpos = 0; - memset(cmask, 0, sizeof(cmask)); - - entry = pattern->entry; - - while (bufpos < buflen) { - unsigned char b = buffer[bufpos++]; - - if (b == 0) { - /* End of row */ - IT_SET_END_ROW(entry); - entry++; -#ifdef DETECT_DUPLICATE_CHANNELS - { - int i; - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) dupentry[i] = NULL; - } -#endif - continue; - } - - channel = (b - 1) & 63; - - if (b & 128) - cmask[channel] = mask = buffer[bufpos++]; - else - mask = cmask[channel]; - - if (mask) { - entry->mask = (mask & 15) | (mask >> 4); - entry->channel = channel; - - if (mask & IT_ENTRY_NOTE) - cnote[channel] = entry->note = buffer[bufpos++]; - else if (mask & (IT_ENTRY_NOTE << 4)) - entry->note = cnote[channel]; - - if (mask & IT_ENTRY_INSTRUMENT) - cinstrument[channel] = entry->instrument = buffer[bufpos++]; - else if (mask & (IT_ENTRY_INSTRUMENT << 4)) - entry->instrument = cinstrument[channel]; - - if (mask & IT_ENTRY_VOLPAN) - cvolpan[channel] = entry->volpan = buffer[bufpos++]; - else if (mask & (IT_ENTRY_VOLPAN << 4)) - entry->volpan = cvolpan[channel]; - - if (mask & IT_ENTRY_EFFECT) { - ceffect[channel] = entry->effect = buffer[bufpos++]; - ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++]; - } else { - entry->effect = ceffect[channel]; - entry->effectvalue = ceffectvalue[channel]; - } - -#ifdef DETECT_DUPLICATE_CHANNELS - if (dupentry[channel]) { - FILE *f = fopen("dupentry.txt", "a"); - if (!f) abort(); - fprintf(f, "Two events on channel %d:", channel); - fprintf(f, " Event #1:"); - if (dupentry[channel]->mask & IT_ENTRY_NOTE ) fprintf(f, " %03d", dupentry[channel]->note ); else fprintf(f, " ..."); - if (dupentry[channel]->mask & IT_ENTRY_INSTRUMENT) fprintf(f, " %03d", dupentry[channel]->instrument); else fprintf(f, " ..."); - if (dupentry[channel]->mask & IT_ENTRY_VOLPAN ) fprintf(f, " %03d", dupentry[channel]->volpan ); else fprintf(f, " ..."); - if (dupentry[channel]->mask & IT_ENTRY_EFFECT) fprintf(f, " %c%02X\n", 'A' - 1 + dupentry[channel]->effect, dupentry[channel]->effectvalue); else fprintf(f, " ...\n"); - fprintf(f, " Event #2:"); - if (entry->mask & IT_ENTRY_NOTE ) fprintf(f, " %03d", entry->note ); else fprintf(f, " ..."); - if (entry->mask & IT_ENTRY_INSTRUMENT) fprintf(f, " %03d", entry->instrument); else fprintf(f, " ..."); - if (entry->mask & IT_ENTRY_VOLPAN ) fprintf(f, " %03d", entry->volpan ); else fprintf(f, " ..."); - if (entry->mask & IT_ENTRY_EFFECT) fprintf(f, " %c%02X\n", 'A' - 1 + entry->effect, entry->effectvalue); else fprintf(f, " ...\n"); - fclose(f); - } - dupentry[channel] = entry; -#endif - - entry++; - } - } - - ASSERT(entry == pattern->entry + n_entries); - - return 0; -} - - - -/* Currently we assume the sample data are stored after the sample headers in - * module files. This assumption may be unjustified; let me know if you have - * trouble. - */ - -#define IT_COMPONENT_INSTRUMENT 1 -#define IT_COMPONENT_PATTERN 2 -#define IT_COMPONENT_SAMPLE 3 - -typedef struct IT_COMPONENT -{ - unsigned char type; - unsigned char n; - long offset; - short sampfirst; /* component[sampfirst] = first sample data after this */ - short sampnext; /* sampnext is used to create linked lists of sample data */ -} -IT_COMPONENT; - - - -static int it_component_compare(const void *e1, const void *e2) -{ - return ((const IT_COMPONENT *)e1)->offset - - ((const IT_COMPONENT *)e2)->offset; -} - - - -static sigdata_t *it_load_sigdata(DUMBFILE *f) -{ - DUMB_IT_SIGDATA *sigdata; - - int cwt, cmwt; - int special; - - IT_COMPONENT *component; - int n_components = 0; - - unsigned char sample_convert[256]; - - int n; - - unsigned char *buffer; - - if (dumbfile_mgetl(f) != IT_SIGNATURE) - return NULL; - - sigdata = malloc(sizeof(*sigdata)); - - if (!sigdata) - return NULL; - - sigdata->order = NULL; - sigdata->instrument = NULL; - sigdata->sample = NULL; - sigdata->pattern = NULL; - sigdata->midi = NULL; - sigdata->checkpoint = NULL; - - /* Skip song name and pattern row highlight info. */ - dumbfile_skip(f, 28); - - sigdata->n_orders = dumbfile_igetw(f); - sigdata->n_instruments = dumbfile_igetw(f); - sigdata->n_samples = dumbfile_igetw(f); - sigdata->n_patterns = dumbfile_igetw(f); - - cwt = dumbfile_igetw(f); - cmwt = dumbfile_igetw(f); - - sigdata->flags = dumbfile_igetw(f); - special = dumbfile_igetw(f); - - sigdata->global_volume = dumbfile_getc(f); - sigdata->mixing_volume = dumbfile_getc(f); - sigdata->speed = dumbfile_getc(f); - if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo? - sigdata->tempo = dumbfile_getc(f); - sigdata->pan_separation = dumbfile_getc(f); /** WARNING: use this */ - - /* Skip Pitch Wheel Depth, Message Length, Message Offset and Reserved. */ - dumbfile_skip(f, 11); - - dumbfile_getnc(sigdata->channel_pan, DUMB_IT_N_CHANNELS, f); - dumbfile_getnc(sigdata->channel_volume, DUMB_IT_N_CHANNELS, f); - - if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_instruments > 256 || sigdata->n_samples > 256 || sigdata->n_patterns > 256) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - sigdata->order = malloc(sigdata->n_orders); - if (!sigdata->order) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (sigdata->n_instruments) { - sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument)); - if (!sigdata->instrument) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - } - - if (sigdata->n_samples) { - sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); - if (!sigdata->sample) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (n = 0; n < sigdata->n_samples; n++) - sigdata->sample[n].right = sigdata->sample[n].left = NULL; - } - - if (sigdata->n_patterns) { - sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); - if (!sigdata->pattern) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (n = 0; n < sigdata->n_patterns; n++) - sigdata->pattern[n].entry = NULL; - } - - dumbfile_getnc(sigdata->order, sigdata->n_orders, f); - sigdata->restart_position = 0; - - component = malloc(768 * sizeof(*component)); - if (!component) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - for (n = 0; n < sigdata->n_instruments; n++) { - component[n_components].type = IT_COMPONENT_INSTRUMENT; - component[n_components].n = n; - component[n_components].offset = dumbfile_igetl(f); - component[n_components].sampfirst = -1; - n_components++; - } - - for (n = 0; n < sigdata->n_samples; n++) { - component[n_components].type = IT_COMPONENT_SAMPLE; - component[n_components].n = n; - component[n_components].offset = dumbfile_igetl(f); - component[n_components].sampfirst = -1; - n_components++; - } - - for (n = 0; n < sigdata->n_patterns; n++) { - long offset = dumbfile_igetl(f); - if (offset) { - component[n_components].type = IT_COMPONENT_PATTERN; - component[n_components].n = n; - component[n_components].offset = offset; - component[n_components].sampfirst = -1; - n_components++; - } else { - /* Empty 64-row pattern */ - sigdata->pattern[n].n_rows = 64; - sigdata->pattern[n].n_entries = 0; - } - } - - if (dumbfile_error(f)) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (!(sigdata->flags & 128) != !(special & 8)) { - fprintf(stderr, "Flags Bit 7 (\"Request embedded MIDI configuration\"): %s\n", sigdata->flags & 128 ? "=SET=" : "clear"); - fprintf(stderr, "Special Bit 3 (\"MIDI configuration embedded\") : %s\n", special & 8 ? "=SET=" : "clear"); - fprintf(stderr, "entheh would like to investigate this IT file.\n"); - fprintf(stderr, "Please contact him! entheh@users.sf.net\n"); - } - - if (special & 8) { - /* MIDI configuration is embedded. */ - unsigned char mididata[32]; - int i; - sigdata->midi = malloc(sizeof(*sigdata->midi)); - if (!sigdata->midi) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - // Should we be happy with this outcome in some situations? - } - // What are we skipping? - i = dumbfile_igetw(f); - if (dumbfile_error(f) || dumbfile_skip(f, 8*i)) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - /* Read embedded MIDI configuration */ - // What are the first 9 commands for? - if (dumbfile_skip(f, 32*9)) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (i = 0; i < 16; i++) { - unsigned char len = 0; - int j, leftdigit = -1; - if (dumbfile_getnc(mididata, 32, f) < 32) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - sigdata->midi->SFmacroz[i] = 0; - for (j = 0; j < 32; j++) { - if (leftdigit >= 0) { - if (mididata[j] == 0) { - sigdata->midi->SFmacro[i][len++] = leftdigit; - break; - } else if (mididata[j] == ' ') - sigdata->midi->SFmacro[i][len++] = leftdigit; - else if (mididata[j] >= '0' && mididata[j] <= '9') - sigdata->midi->SFmacro[i][len++] = (leftdigit << 4) | (mididata[j] - '0'); - else if (mididata[j] >= 'A' && mididata[j] <= 'F') - sigdata->midi->SFmacro[i][len++] = (leftdigit << 4) | (mididata[j] - 'A' + 0xA); - leftdigit = -1; - } else if (mididata[j] == 0) - break; - else if (mididata[j] == 'z') - sigdata->midi->SFmacroz[i] |= 1 << len++; - else if (mididata[j] >= '0' && mididata[j] <= '9') - leftdigit = mididata[j] - '0'; - else if (mididata[j] >= 'A' && mididata[j] <= 'F') - leftdigit = mididata[j] - 'A' + 0xA; - } - sigdata->midi->SFmacrolen[i] = len; - } - for (i = 0; i < 128; i++) { - unsigned char len = 0; - int j, leftdigit = -1; - dumbfile_getnc(mididata, 32, f); - for (j = 0; j < 32; j++) { - if (leftdigit >= 0) { - if (mididata[j] == 0) { - sigdata->midi->Zmacro[i][len++] = leftdigit; - break; - } else if (mididata[j] == ' ') - sigdata->midi->Zmacro[i][len++] = leftdigit; - else if (mididata[j] >= '0' && mididata[j] <= '9') - sigdata->midi->Zmacro[i][len++] = (leftdigit << 4) | (mididata[j] - '0'); - else if (mididata[j] >= 'A' && mididata[j] <= 'F') - sigdata->midi->Zmacro[i][len++] = (leftdigit << 4) | (mididata[j] - 'A' + 0xA); - leftdigit = -1; - } else if (mididata[j] == 0) - break; - else if (mididata[j] >= '0' && mididata[j] <= '9') - leftdigit = mididata[j] - '0'; - else if (mididata[j] >= 'A' && mididata[j] <= 'F') - leftdigit = mididata[j] - 'A' + 0xA; - } - sigdata->midi->Zmacrolen[i] = len; - } - } - - sigdata->flags &= IT_REAL_FLAGS; - - qsort(component, n_components, sizeof(IT_COMPONENT), &it_component_compare); - - buffer = malloc(65536); - if (!buffer) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - for (n = 0; n < n_components; n++) { - long offset; - int m; - - if (it_seek(f, component[n].offset)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - switch (component[n].type) { - - case IT_COMPONENT_INSTRUMENT: - if (cmwt < 0x200) - m = it_read_old_instrument(&sigdata->instrument[component[n].n], f); - else - m = it_read_instrument(&sigdata->instrument[component[n].n], f); - - if (m) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - break; - - case IT_COMPONENT_PATTERN: - if (it_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - break; - - case IT_COMPONENT_SAMPLE: - if (it_read_sample_header(&sigdata->sample[component[n].n], &sample_convert[component[n].n], &offset, f)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (sigdata->sample[component[n].n].flags & IT_SAMPLE_EXISTS) { - short *sample; - - for (m = n + 1; m < n_components; m++) - if (component[m].offset > offset) - break; - m--; - - sample = &component[m].sampfirst; - - while (*sample >= 0 && component[*sample].offset <= offset) - sample = &component[*sample].sampnext; - - component[n].sampnext = *sample; - *sample = n; - - component[n].offset = offset; - } - } - - m = component[n].sampfirst; - - while (m >= 0) { - if (it_seek(f, component[m].offset)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (it_read_sample_data(cmwt, &sigdata->sample[component[m].n], sample_convert[component[m].n], f)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - m = component[m].sampnext; - } - } - - free(buffer); - free(component); - - _dumb_it_fix_invalid_orders(sigdata); - - return sigdata; -} - - - -DUH *dumb_read_it(DUMBFILE *f) -{ - sigdata_t *sigdata; - long length; - - DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; - - sigdata = it_load_sigdata(f); - - if (!sigdata) - return NULL; - - length = _dumb_it_build_checkpoints(sigdata); - - return make_duh(length, 1, &descptr, &sigdata); -} - diff --git a/Engine/libsrc/dumb-0.9.2/it/itrender.c b/Engine/libsrc/dumb-0.9.2/it/itrender.c deleted file mode 100644 index 103654fd778..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/itrender.c +++ /dev/null @@ -1,3512 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * itrender.c - Code to render an Impulse Tracker / / \ \ - * module. | < / \_ - * | \/ /\ / - * Written - painstakingly - by entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include - -#include "dumb.h" -#include "internal/it.h" - - - -static IT_PLAYING *dup_playing(IT_PLAYING *src, IT_CHANNEL *dstchannel, IT_CHANNEL *srcchannel) -{ - IT_PLAYING *dst; - - if (!src) return NULL; - - dst = malloc(sizeof(*dst)); - if (!dst) return NULL; - - dst->flags = src->flags; - - ASSERT(src->channel); - dst->channel = &dstchannel[src->channel - srcchannel]; - dst->sample = src->sample; - dst->instrument = src->instrument; - dst->env_instrument = src->env_instrument; - - dst->sampnum = src->sampnum; - dst->instnum = src->instnum; - - dst->channel_volume = src->channel_volume; - - dst->volume = src->volume; - dst->pan = src->pan; - - dst->note = src->note; - - dst->filter_cutoff = src->filter_cutoff; - dst->filter_resonance = src->filter_resonance; - - dst->true_filter_cutoff = src->true_filter_cutoff; - dst->true_filter_resonance = src->true_filter_resonance; - - dst->vibrato_speed = src->vibrato_speed; - dst->vibrato_depth = src->vibrato_depth; - dst->vibrato_n = src->vibrato_n; - dst->vibrato_time = src->vibrato_time; - - dst->tremolo_speed = src->tremolo_speed; - dst->tremolo_depth = src->tremolo_depth; - dst->tremolo_time = src->tremolo_time; - - dst->sample_vibrato_time = src->sample_vibrato_time; - dst->sample_vibrato_depth = src->sample_vibrato_depth; - - dst->slide = src->slide; - dst->delta = src->delta; - - dst->volume_envelope = src->volume_envelope; - dst->pan_envelope = src->pan_envelope; - dst->pitch_envelope = src->pitch_envelope; - - dst->fadeoutcount = src->fadeoutcount; - - dst->filter_state[0] = src->filter_state[0]; - dst->filter_state[1] = src->filter_state[1]; - - dst->resampler[0] = src->resampler[0]; - dst->resampler[1] = src->resampler[1]; - dst->resampler[1].pickup_data = dst->resampler[0].pickup_data = dst; - dst->time_lost = src->time_lost; - - return dst; -} - - - -static void dup_channel(IT_CHANNEL *dst, IT_CHANNEL *src) -{ - dst->flags = src->flags; - - dst->volume = src->volume; - dst->volslide = src->volslide; - dst->xm_volslide = src->xm_volslide; - - dst->pan = src->pan; - dst->truepan = src->truepan; - - dst->channelvolume = src->channelvolume; - dst->channelvolslide = src->channelvolslide; - - dst->instrument = src->instrument; - dst->note = src->note; - - dst->SFmacro = src->SFmacro; - - dst->filter_cutoff = src->filter_cutoff; - dst->filter_resonance = src->filter_resonance; - - dst->note_cut_count = src->note_cut_count; - dst->note_delay_count = src->note_delay_count; - dst->note_delay_entry = src->note_delay_entry; - - dst->arpeggio = src->arpeggio; - dst->retrig = src->retrig; - dst->xm_retrig = src->xm_retrig; - dst->retrig_tick = src->retrig_tick; - - dst->tremor_time = src->tremor_time; - - dst->portamento = src->portamento; - dst->toneporta = src->toneporta; - dst->destnote = src->destnote; - - dst->sample = src->sample; - dst->truenote = src->truenote; - - dst->midi_state = src->midi_state; - - dst->lastvolslide = src->lastvolslide; - dst->lastDKL = src->lastDKL; - dst->lastEF = src->lastEF; - dst->lastG = src->lastG; - dst->lastHspeed = src->lastHspeed; - dst->lastHdepth = src->lastHdepth; - dst->lastRspeed = src->lastRspeed; - dst->lastRdepth = src->lastRdepth; - dst->lastI = src->lastI; - dst->lastJ = src->lastJ; - dst->lastN = src->lastN; - dst->lastO = src->lastO; - dst->high_offset = src->high_offset; - dst->lastQ = src->lastQ; - dst->lastS = src->lastS; - dst->pat_loop_row = src->pat_loop_row; - dst->pat_loop_count = src->pat_loop_count; - dst->lastW = src->lastW; - - dst->xm_lastE1 = src->xm_lastE1; - dst->xm_lastE2 = src->xm_lastE2; - dst->xm_lastEA = src->xm_lastEA; - dst->xm_lastEB = src->xm_lastEB; - dst->xm_lastX1 = src->xm_lastX1; - dst->xm_lastX2 = src->xm_lastX2; - - dst->playing = dup_playing(src->playing, dst, src); -} - - - -/* Allocate the new callbacks first, then pass them to this function! - * It will free them on failure. - */ -static DUMB_IT_SIGRENDERER *dup_sigrenderer(DUMB_IT_SIGRENDERER *src, int n_channels, IT_CALLBACKS *callbacks) -{ - DUMB_IT_SIGRENDERER *dst; - int i; - - if (!src) { - if (callbacks) free(callbacks); - return NULL; - } - - dst = malloc(sizeof(*dst)); - if (!dst) { - if (callbacks) free(callbacks); - return NULL; - } - - dst->sigdata = src->sigdata; - - dst->n_channels = n_channels; - - dst->globalvolume = src->globalvolume; - dst->globalvolslide = src->globalvolslide; - - dst->tempo = src->tempo; - dst->temposlide = src->temposlide; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) - dup_channel(&dst->channel[i], &src->channel[i]); - - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) - dst->playing[i] = dup_playing(src->playing[i], dst->channel, src->channel); - - dst->tick = src->tick; - dst->speed = src->speed; - dst->rowcount = src->rowcount; - - dst->order = src->order; - dst->row = src->row; - dst->processorder = src->processorder; - dst->processrow = src->processrow; - dst->breakrow = src->breakrow; - dst->pat_loop_row = src->pat_loop_row; - - dst->n_rows = src->n_rows; - - dst->entry_start = src->entry_start; - dst->entry = src->entry; - dst->entry_end = src->entry_end; - - dst->time_left = src->time_left; - dst->sub_time_left = src->sub_time_left; - - dst->click_remover = NULL; - - dst->callbacks = callbacks; - - return dst; -} - - - -static IT_MIDI default_midi = { - /* unsigned char SFmacro[16][16]; */ - { - {0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - }, - /* unsigned char SFmacrolen[16]; */ - {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* unsigned short SFmacroz[16]; */ - /* Bitfield; bit 0 set = z in first position */ - { - 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - }, - /* unsigned char Zmacro[128][16]; */ - { - {0xF0, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xF0, 0xF0, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - }, - /* unsigned char Zmacrolen[128]; */ - { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - } -}; - - - -static void it_reset_filter_state(IT_FILTER_STATE *state) -{ - state->currsample = 0; - state->prevsample = 0; -} - - - -#define LOG10 2.30258509299 - -/* IMPORTANT: This function expects one extra sample in 'src' so it can apply - * click removal. It reads size samples, starting from src[0], and writes its - * output starting at dst[pos]. The pos parameter is required for getting - * click removal right. - */ -static void it_filter(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int sampfreq, int cutoff, int resonance) -{ - float currsample = state->currsample; - float prevsample = state->prevsample; - - float a, b, c; - - { - float inv_angle = (float)(sampfreq * pow(0.5, 0.25 + cutoff*(1.0/(24< 2.0f) d = 2.0f; - d = (loss - d) * inv_angle; - e = inv_angle * inv_angle; - a = 1.0f / (1.0f + d + e); - c = -e * a; - b = 1.0f - a - c; -#else - a = 1.0f / (inv_angle*inv_angle + inv_angle*loss + loss); - c = -(inv_angle*inv_angle) * a; - b = 1.0f - a - c; -#endif - } - - dst += pos; - - if (cr) { - float startstep = src[0]*a + currsample*b + prevsample*c; - dumb_record_click(cr, pos, (sample_t)startstep); - } - -#define INT_FILTERS -#ifdef INT_FILTERS -#define MULSCA(a, b) ((int)((LONG_LONG)((a) << 4) * (b) >> 32)) -#define SCALEB 12 - { - int ai = (int)(a * (1 << (16+SCALEB))); - int bi = (int)(b * (1 << (16+SCALEB))); - int ci = (int)(c * (1 << (16+SCALEB))); - sample_t csi = (sample_t)currsample; - sample_t psi = (sample_t)prevsample; - sample_t *dst_end = dst + size; - while (dst < dst_end) { - { - sample_t nsi = MULSCA(*src++, ai) + MULSCA(csi, bi) + MULSCA(psi, ci); - psi = csi; - csi = nsi; - } - *dst++ += csi; - } - currsample = csi; - prevsample = psi; - } -#else - { - int i = size % 3; - while (i > 0) { - { - float newsample = *src++*a + currsample*b + prevsample*c; - prevsample = currsample; - currsample = newsample; - } - *dst++ += (sample_t)currsample; - i--; - } - i = size / 3; - while (i > 0) { - float newsample; - /* Gotta love unrolled loops! */ - *dst++ += (sample_t)(newsample = *src++*a + currsample*b + prevsample*c); - *dst++ += (sample_t)(prevsample = *src++*a + newsample*b + currsample*c); - *dst++ += (sample_t)(currsample = *src++*a + prevsample*b + newsample*c); - i--; - } - } -#endif - - if (cr) { - float endstep = *src*a + currsample*b + prevsample*c; - dumb_record_click(cr, pos + size, -(sample_t)endstep); - } - - state->currsample = currsample; - state->prevsample = prevsample; -} - -#undef LOG10 - - - -static signed char it_sine[256] = { - 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, - 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, - 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, - 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, - 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26, - 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2, - 0, -2, -3, -5, -6, -8, -9,-11,-12,-14,-16,-17,-19,-20,-22,-23, - -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44, - -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59, - -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64, - -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60, - -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46, - -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26, - -24,-23,-22,-20,-19,-17,-16,-14,-12,-11, -9, -8, -6, -5, -3, -2 -}; - - - -#if 0 -/** WARNING: use these! */ -/** JULIEN: Plus for XM compatibility it could be interesting to rename - * it_sawtooth[] to it_rampdown[], and add an it_rampup[]. - * Also, still for XM compat', twood be good if it was possible to tell the - * the player not to retrig' the waveform on a new instrument. - * Both of these are only for completness though, as I don't think it would - * be very noticeable ;) - */ -/** ENTHEH: IT also has the 'don't retrig' thingy :) */ - -static signed char it_sawtooth[256] = { - 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56, - 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, - 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, - 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, - 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, - 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, - 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, - 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, - 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8, - -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16, - -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24, - -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32, - -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40, - -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48, - -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56, - -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64 -}; - - - -static signed char it_squarewave[256] = { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#endif - - - -static void reset_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer) -{ - int i; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; - channel->note_cut_count = 0; - channel->note_delay_count = 0; - } -} - - - -static void reset_effects(DUMB_IT_SIGRENDERER *sigrenderer) -{ - int i; - - sigrenderer->globalvolslide = 0; - sigrenderer->temposlide = 0; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; - channel->volslide = 0; - channel->xm_volslide = 0; - channel->channelvolslide = 0; - channel->arpeggio = 0; - channel->retrig = 0; - if (channel->xm_retrig) { - channel->xm_retrig = 0; - channel->retrig_tick = 0; - } - channel->tremor_time &= 127; - channel->portamento = 0; - channel->toneporta = 0; - if (channel->playing) { - channel->playing->vibrato_n = 0; - channel->playing->tremolo_speed = 0; - channel->playing->tremolo_depth = 0; - } - } -} - - - -static void update_tremor(IT_CHANNEL *channel) -{ - if ((channel->tremor_time & 128) && channel->playing) { - if (channel->tremor_time == 128) - channel->tremor_time = (channel->lastI >> 4) | 192; - else if (channel->tremor_time == 192) - channel->tremor_time = (channel->lastI & 15) | 128; - else - channel->tremor_time--; - } -} - - - -static void it_pickup_loop(DUMB_RESAMPLER *resampler, void *data) -{ - resampler->pos -= resampler->end - resampler->start; - ((IT_PLAYING *)data)->time_lost += resampler->end - resampler->start; -} - - - -static void it_pickup_pingpong_loop(DUMB_RESAMPLER *resampler, void *data) -{ - if (resampler->dir < 0) { - resampler->pos = (resampler->start << 1) - 1 - resampler->pos; - resampler->subpos ^= 65535; - resampler->dir = 1; - ((IT_PLAYING *)data)->time_lost += (resampler->end - resampler->start) << 1; - } else { - resampler->pos = (resampler->end << 1) - 1 - resampler->pos; - resampler->subpos ^= 65535; - resampler->dir = -1; - } -} - - - -static void it_pickup_stop_at_end(DUMB_RESAMPLER *resampler, void *data) -{ - (void)data; - - if (resampler->dir < 0) { - resampler->pos = (resampler->start << 1) - 1 - resampler->pos; - resampler->subpos ^= 65535; - /* By rights, time_lost would be updated here. However, there is no - * need at this point; it will not be used. - * - * ((IT_PLAYING *)data)->time_lost += (resampler->src_end - resampler->src_start) << 1; - */ - resampler->dir = 1; - } else - resampler->dir = 0; -} - - - -static void it_playing_update_resamplers(IT_PLAYING *playing) -{ - if ((playing->sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) { - playing->resampler[0].start = playing->sample->sus_loop_start; - playing->resampler[0].end = playing->sample->sus_loop_end; - if (playing->sample->flags & IT_SAMPLE_PINGPONG_SUS_LOOP) - playing->resampler[0].pickup = &it_pickup_pingpong_loop; - else - playing->resampler[0].pickup = &it_pickup_loop; - } else if (playing->sample->flags & IT_SAMPLE_LOOP) { - playing->resampler[0].start = playing->sample->loop_start; - playing->resampler[0].end = playing->sample->loop_end; - if (playing->sample->flags & IT_SAMPLE_PINGPONG_LOOP) - playing->resampler[0].pickup = &it_pickup_pingpong_loop; - else - playing->resampler[0].pickup = &it_pickup_loop; - } else { - if (playing->sample->flags & IT_SAMPLE_SUS_LOOP) - playing->resampler[0].start = playing->sample->sus_loop_start; - else - playing->resampler[0].start = 0; - playing->resampler[0].end = playing->sample->length; - playing->resampler[0].pickup = &it_pickup_stop_at_end; - } - playing->resampler[1].start = playing->resampler[0].start; - playing->resampler[1].end = playing->resampler[0].end; - playing->resampler[1].pickup = playing->resampler[0].pickup; - ASSERT(playing->resampler[0].pickup_data == playing); - ASSERT(playing->resampler[1].pickup_data == playing); -} - - - -/* This should be called whenever the sample or sample position changes. */ -static void it_playing_reset_resamplers(IT_PLAYING *playing, long pos) -{ - dumb_reset_resampler(&playing->resampler[0], playing->sample->left, pos, 0, 0); - dumb_reset_resampler(&playing->resampler[1], playing->sample->right, pos, 0, 0); - playing->resampler[1].pickup_data = playing->resampler[0].pickup_data = playing; - playing->time_lost = 0; - playing->flags &= ~IT_PLAYING_DEAD; - it_playing_update_resamplers(playing); -} - - - -static void update_retrig(IT_CHANNEL *channel) -{ - if (channel->xm_retrig) { - channel->retrig_tick--; - if (channel->retrig_tick <= 0) { - if (channel->playing) it_playing_reset_resamplers(channel->playing, 0); - channel->retrig_tick = channel->xm_retrig; - } - } else if (channel->retrig & 0x0F) { - channel->retrig_tick--; - if (channel->retrig_tick <= 0) { - if (channel->retrig < 0x10) { - } else if (channel->retrig < 0x20) { - channel->volume--; - if (channel->volume > 64) channel->volume = 0; - } else if (channel->retrig < 0x30) { - channel->volume -= 2; - if (channel->volume > 64) channel->volume = 0; - } else if (channel->retrig < 0x40) { - channel->volume -= 4; - if (channel->volume > 64) channel->volume = 0; - } else if (channel->retrig < 0x50) { - channel->volume -= 8; - if (channel->volume > 64) channel->volume = 0; - } else if (channel->retrig < 0x60) { - channel->volume -= 16; - if (channel->volume > 64) channel->volume = 0; - } else if (channel->retrig < 0x70) { - channel->volume <<= 1; - channel->volume /= 3; - } else if (channel->retrig < 0x80) { - channel->volume >>= 1; - } else if (channel->retrig < 0x90) { - } else if (channel->retrig < 0xA0) { - channel->volume++; - if (channel->volume > 64) channel->volume = 64; - } else if (channel->retrig < 0xB0) { - channel->volume += 2; - if (channel->volume > 64) channel->volume = 64; - } else if (channel->retrig < 0xC0) { - channel->volume += 4; - if (channel->volume > 64) channel->volume = 64; - } else if (channel->retrig < 0xD0) { - channel->volume += 8; - if (channel->volume > 64) channel->volume = 64; - } else if (channel->retrig < 0xE0) { - channel->volume += 16; - if (channel->volume > 64) channel->volume = 64; - } else if (channel->retrig < 0xF0) { - channel->volume *= 3; - channel->volume >>= 1; - if (channel->volume > 64) channel->volume = 64; - } else { - channel->volume <<= 1; - if (channel->volume > 64) channel->volume = 64; - } - if (channel->playing) it_playing_reset_resamplers(channel->playing, 0); - channel->retrig_tick = channel->retrig & 0x0F; - } - } -} - - - -static void update_smooth_effects(DUMB_IT_SIGRENDERER *sigrenderer) -{ - int i; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; - IT_PLAYING *playing = channel->playing; - - if (playing) { - playing->vibrato_time += playing->vibrato_n * - (playing->vibrato_speed << 2); - playing->tremolo_time += playing->tremolo_speed << 2; - } - } -} - - - -static void update_effects(DUMB_IT_SIGRENDERER *sigrenderer) -{ - int i; - - if (sigrenderer->globalvolslide) { - sigrenderer->globalvolume += sigrenderer->globalvolslide; - if (sigrenderer->globalvolume > 128) { - if (sigrenderer->globalvolslide >= 0) - sigrenderer->globalvolume = 128; - else - sigrenderer->globalvolume = 0; - } - } - - if (sigrenderer->temposlide) { - sigrenderer->tempo += sigrenderer->temposlide; - if (sigrenderer->tempo < 32) { - if (sigrenderer->temposlide >= 0) - sigrenderer->tempo = 255; - else - sigrenderer->tempo = 32; - } - } - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; - IT_PLAYING *playing = channel->playing; - - if (channel->xm_volslide) { - channel->volume += channel->xm_volslide; - if (channel->volume > 64) { - if (channel->xm_volslide >= 0) - channel->volume = 64; - else - channel->volume = 0; - } - } - - if (channel->volslide) { - channel->volume += channel->volslide; - if (channel->volume > 64) { - if (channel->volslide >= 0) - channel->volume = 64; - else - channel->volume = 0; - } - } - - if (channel->channelvolslide) { - channel->channelvolume += channel->channelvolslide; - if (channel->channelvolume > 64) { - if (channel->channelvolslide >= 0) - channel->channelvolume = 64; - else - channel->channelvolume = 0; - } - if (channel->playing) - channel->playing->channel_volume = channel->channelvolume; - } - - update_tremor(channel); - - channel->arpeggio = (channel->arpeggio << 4) | (channel->arpeggio >> 8); - channel->arpeggio &= 0xFFF; - - update_retrig(channel); - - if (playing) { - playing->slide += channel->portamento; - - if (sigrenderer->sigdata->flags & IT_LINEAR_SLIDES) { - if (channel->toneporta && channel->destnote < 120) { - int currpitch = ((playing->note - 60) << 8) + playing->slide; - int destpitch = (channel->destnote - 60) << 8; - if (currpitch > destpitch) { - currpitch -= channel->toneporta; - if (currpitch < destpitch) { - currpitch = destpitch; - channel->destnote = IT_NOTE_OFF; - } - } else if (currpitch < destpitch) { - currpitch += channel->toneporta; - if (currpitch > destpitch) { - currpitch = destpitch; - channel->destnote = IT_NOTE_OFF; - } - } - playing->slide = currpitch - ((playing->note - 60) << 8); - } - } else { - if (channel->toneporta && channel->destnote < 120) { - float amiga_multiplier = playing->sample->C5_speed * (1.0f / AMIGA_DIVISOR); - - float deltanote = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note); - /* deltanote is 1.0 for C-5, 0.5 for C-6, etc. */ - - float deltaslid = deltanote - playing->slide * amiga_multiplier; - - float destdelta = (float)pow(DUMB_SEMITONE_BASE, 60 - channel->destnote); - if (deltaslid < destdelta) { - playing->slide -= channel->toneporta; - deltaslid = deltanote - playing->slide * amiga_multiplier; - if (deltaslid > destdelta) { - playing->note = channel->destnote; - playing->slide = 0; - channel->destnote = IT_NOTE_OFF; - } - } else { - playing->slide += channel->toneporta; - deltaslid = deltanote - playing->slide * amiga_multiplier; - if (deltaslid < destdelta) { - playing->note = channel->destnote; - playing->slide = 0; - channel->destnote = IT_NOTE_OFF; - } - } - } - } - } - } - - update_smooth_effects(sigrenderer); -} - - - -static void update_pattern_variables(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel]; - - if (entry->mask & IT_ENTRY_EFFECT) { - if (entry->effect == IT_S) { - unsigned char effectvalue = entry->effectvalue; - if (effectvalue == 0) - effectvalue = channel->lastS; - channel->lastS = effectvalue; - switch (effectvalue >> 4) { - //case IT_S7: - case IT_S_PATTERN_LOOP: - { - unsigned char v = effectvalue & 15; - if (v == 0) - channel->pat_loop_row = sigrenderer->processrow; - else { - if (channel->pat_loop_count == 0) { - channel->pat_loop_count = v; - sigrenderer->pat_loop_row = channel->pat_loop_row; - } else { - if (--channel->pat_loop_count) - sigrenderer->pat_loop_row = channel->pat_loop_row; - else if (!(sigrenderer->sigdata->flags & IT_WAS_AN_XM)) - channel->pat_loop_row = sigrenderer->processrow + 1; - } - } - } - break; - case IT_S_PATTERN_DELAY: - sigrenderer->rowcount = 1 + (effectvalue & 15); - break; - } - } - } -} - - - -/* This function guarantees that channel->sample will always be valid if it - * is nonzero. In other words, to check if it is valid, simply check if it is - * nonzero. - */ -static void instrument_to_sample(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel) -{ - if (sigdata->flags & IT_USE_INSTRUMENTS) { - if (channel->instrument >= 1 && channel->instrument <= sigdata->n_instruments) { - if (channel->note < 120) { - channel->sample = sigdata->instrument[channel->instrument-1].map_sample[channel->note]; - channel->truenote = sigdata->instrument[channel->instrument-1].map_note[channel->note]; - } else - channel->sample = 0; - } else - channel->sample = 0; - } else { - channel->sample = channel->instrument; - channel->truenote = channel->note; - } - if (!(channel->sample >= 1 && channel->sample <= sigdata->n_samples && (sigdata->sample[channel->sample-1].flags & IT_SAMPLE_EXISTS))) - channel->sample = 0; -} - - - -static void fix_sample_looping(IT_PLAYING *playing) -{ - if ((playing->sample->flags & (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP)) == - (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP)) { - if (playing->resampler[0].dir < 0) { - playing->resampler[1].pos = playing->resampler[0].pos = (playing->sample->sus_loop_end << 1) - 1 - playing->resampler[0].pos; - playing->resampler[1].subpos = playing->resampler[0].subpos ^= 65535; - playing->resampler[1].dir = playing->resampler[0].dir = 1; - } - - playing->resampler[1].pos = playing->resampler[0].pos += playing->time_lost; - } -} - - - -static void retrigger_it_envelopes(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel) -{ - channel->playing->volume_envelope.next_node = 0; - channel->playing->volume_envelope.tick = -1; - channel->playing->pan_envelope.next_node = 0; - channel->playing->pan_envelope.tick = -1; - channel->playing->pitch_envelope.next_node = 0; - channel->playing->pitch_envelope.tick = -1; - channel->playing->fadeoutcount = 1024; - // Should we remove IT_PLAYING_BACKGROUND? Test with sample with sustain loop... - channel->playing->flags &= ~(IT_PLAYING_BACKGROUND | IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING | IT_PLAYING_DEAD); - it_playing_update_resamplers(channel->playing); - - if (channel->sample) - if (sigdata->flags & IT_USE_INSTRUMENTS) - channel->playing->env_instrument = &sigdata->instrument[channel->instrument-1]; -} - - - -static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - unsigned char nna; - int i; - - if (channel->playing) { -#ifdef INVALID_NOTES_CAUSE_NOTE_CUT - if (channel->note == IT_NOTE_OFF) - nna = NNA_NOTE_OFF; - else if (channel->note >= 120 || !channel->playing->instrument || (channel->playing->flags & IT_PLAYING_DEAD)) - nna = NNA_NOTE_CUT; - else - nna = channel->playing->instrument->new_note_action; -#else - if (channel->note == IT_NOTE_CUT) - nna = NNA_NOTE_CUT; - if (channel->note >= 120) - nna = NNA_NOTE_OFF; - else if (!channel->playing->instrument || (channel->playing->flags & IT_PLAYING_DEAD)) - nna = NNA_NOTE_CUT; - else - nna = channel->playing->instrument->new_note_action; -#endif - - switch (nna) { - case NNA_NOTE_CUT: - free(channel->playing); - channel->playing = NULL; - break; - case NNA_NOTE_OFF: - channel->playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_SUSTAINOFF; - fix_sample_looping(channel->playing); - it_playing_update_resamplers(channel->playing); - if (channel->playing->instrument) - if ((channel->playing->instrument->volume_envelope.flags & (IT_ENVELOPE_ON | IT_ENVELOPE_LOOP_ON)) != IT_ENVELOPE_ON) - channel->playing->flags |= IT_PLAYING_FADING; - break; - case NNA_NOTE_FADE: - channel->playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_FADING; - break; - } - } - - if (channel->sample == 0 || channel->note >= 120) - return; - - channel->destnote = IT_NOTE_OFF; - - if (channel->playing) { - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { - if (!sigrenderer->playing[i]) { - sigrenderer->playing[i] = channel->playing; - channel->playing = NULL; - break; - } - } -/** WARNING - come up with some more heuristics for replacing old notes */ -#if 0 - if (channel->playing) { - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { - if (sigrenderer->playing[i]->flags & IT_PLAYING_BACKGROUND) { - write_seqtime(); - sequence_c(SEQUENCE_STOP_SIGNAL); - sequence_c(i); - channel->VChannel = &module->VChannel[i]; - break; - } - } - } -#endif - } - - if (channel->playing) - free(channel->playing); - - channel->playing = malloc(sizeof(*channel->playing)); - - if (!channel->playing) - return; - - channel->playing->flags = 0; - channel->playing->channel = channel; - channel->playing->sample = &sigdata->sample[channel->sample-1]; - if (sigdata->flags & IT_USE_INSTRUMENTS) - channel->playing->instrument = &sigdata->instrument[channel->instrument-1]; - else - channel->playing->instrument = NULL; - channel->playing->env_instrument = channel->playing->instrument; - channel->playing->sampnum = channel->sample; - channel->playing->instnum = channel->instrument; - channel->playing->channel_volume = channel->channelvolume; - channel->playing->note = channel->truenote; - channel->playing->filter_cutoff = 127; - channel->playing->filter_resonance = 0; - channel->playing->true_filter_cutoff = 127 << 8; - channel->playing->true_filter_resonance = 0; - channel->playing->vibrato_speed = 0; - channel->playing->vibrato_depth = 0; - channel->playing->vibrato_n = 0; - channel->playing->vibrato_time = 0; - channel->playing->tremolo_speed = 0; - channel->playing->tremolo_depth = 0; - channel->playing->tremolo_time = 0; - channel->playing->sample_vibrato_time = 0; - channel->playing->sample_vibrato_depth = 0; - channel->playing->slide = 0; - channel->playing->volume_envelope.next_node = 0; - channel->playing->volume_envelope.tick = -1; - channel->playing->pan_envelope.next_node = 0; - channel->playing->pan_envelope.tick = -1; - channel->playing->pitch_envelope.next_node = 0; - channel->playing->pitch_envelope.tick = -1; - channel->playing->fadeoutcount = 1024; - it_reset_filter_state(&channel->playing->filter_state[0]); - it_reset_filter_state(&channel->playing->filter_state[1]); - it_playing_reset_resamplers(channel->playing, 0); - - /** WARNING - is everything initialised? */ -} - - - -static void get_default_volpan(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel) -{ - if (channel->sample == 0) - return; - - channel->volume = sigdata->sample[channel->sample-1].default_volume; - - { - int pan = sigdata->sample[channel->sample-1].default_pan; - if (pan >= 128 && pan <= 192) { - channel->pan = pan - 128; - return; - } - } - - if (sigdata->flags & IT_USE_INSTRUMENTS) { - IT_INSTRUMENT *instrument = &sigdata->instrument[channel->instrument-1]; - if (instrument->default_pan <= 64) - channel->pan = instrument->default_pan; - if (instrument->filter_cutoff >= 128) - channel->filter_cutoff = instrument->filter_cutoff - 128; - if (instrument->filter_resonance >= 128) - channel->filter_resonance = instrument->filter_resonance - 128; - } -} - - - -static void get_true_pan(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel) -{ - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - - if (!IT_IS_SURROUND_SHIFTED(channel->truepan) && (sigdata->flags & IT_USE_INSTRUMENTS)) { - IT_INSTRUMENT *instrument = &sigdata->instrument[channel->instrument-1]; - int truepan = channel->truepan; - truepan += (channel->note - instrument->pp_centre) * instrument->pp_separation << (IT_ENVELOPE_SHIFT - 3); - channel->truepan = MID(0, truepan, 64 << IT_ENVELOPE_SHIFT); - } -} - - - -static void post_process_it_volpan(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel]; - - if (entry->mask & IT_ENTRY_VOLPAN) { - if (entry->volpan <= 84) { - /* Volume */ - /* Fine volume slide up */ - /* Fine volume slide down */ - } else if (entry->volpan <= 94) { - /* Volume slide up */ - unsigned char v = entry->volpan - 85; - if (v == 0) - v = channel->lastvolslide; - channel->lastvolslide = v; - /* = effect Dx0 where x == entry->volpan - 85 */ - channel->volslide = v; - } else if (entry->volpan <= 104) { - /* Volume slide down */ - unsigned char v = entry->volpan - 95; - if (v == 0) - v = channel->lastvolslide; - channel->lastvolslide = v; - /* = effect D0x where x == entry->volpan - 95 */ - channel->volslide = -v; - } else if (entry->volpan <= 114) { - /* Portamento down */ - unsigned char v = (entry->volpan - 105) << 2; - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - channel->portamento -= v << 4; - } else if (entry->volpan <= 124) { - /* Portamento up */ - unsigned char v = (entry->volpan - 115) << 2; - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - channel->portamento += v << 4; - } else if (entry->volpan <= 202) { - /* Pan */ - /* Tone Portamento */ - } else if (entry->volpan <= 212) { - /* Vibrato */ - unsigned char v = entry->volpan - 203; - if (v == 0) - v = channel->lastHdepth; - else { - v <<= 2; - channel->lastHdepth = v; - } - if (channel->playing) { - channel->playing->vibrato_speed = channel->lastHspeed; - channel->playing->vibrato_depth = v; - channel->playing->vibrato_n++; - } - } - } -} - - - -static void it_send_midi(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel, unsigned char byte) -{ - if (sigrenderer->callbacks->midi) - if ((*sigrenderer->callbacks->midi)(sigrenderer->callbacks->midi_data, channel - sigrenderer->channel, byte)) - return; - - switch (channel->midi_state) { - case 4: /* Ready to receive resonance parameter */ - if (byte < 0x80) channel->filter_resonance = byte; - channel->midi_state = 0; - break; - case 3: /* Ready to receive cutoff parameter */ - if (byte < 0x80) channel->filter_cutoff = byte; - channel->midi_state = 0; - break; - case 2: /* Ready for byte specifying which parameter will follow */ - if (byte == 0) /* Cutoff */ - channel->midi_state = 3; - else if (byte == 1) /* Resonance */ - channel->midi_state = 4; - else - channel->midi_state = 0; - break; - default: /* Counting initial F0 bytes */ - switch (byte) { - case 0xF0: - channel->midi_state++; - break; - case 0xFA: - case 0xFC: - case 0xFF: - /* Reset filter parameters for all channels */ - { - int i; - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - sigrenderer->channel[i].filter_cutoff = 127; - sigrenderer->channel[i].filter_resonance = 0; - //// should we be resetting channel[i].playing->filter_* here? - } - } - /* Fall through */ - default: - channel->midi_state = 0; - break; - } - } -} - - - -/* Returns 1 if a callback caused termination of playback. */ -static int process_effects(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - - IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel]; - - if (entry->mask & IT_ENTRY_EFFECT) { - switch (entry->effect) { -/* -Notes about effects (as compared to other module formats) - -C This is now in *HEX*. (Used to be in decimal in ST3) -E/F/G/H/U You need to check whether the song uses Amiga/Linear slides. -H/U Vibrato in Impulse Tracker is two times finer than in - any other tracker and is updated EVERY tick. - If "Old Effects" is *ON*, then the vibrato is played in the - normal manner (every non-row tick and normal depth) -E/F/G These commands ALL share the same memory. -Oxx Offsets to samples are to the 'xx00th' SAMPLE. (ie. for - 16 bit samples, the offset is xx00h*2) - Oxx past the sample end will be ignored, unless "Old Effects" - is ON, in which case the Oxx will play from the end of the - sample. -Yxy This uses a table 4 times larger (hence 4 times slower) than - vibrato or tremelo. If the waveform is set to random, then - the 'speed' part of the command is interpreted as a delay. -*/ - case IT_SET_SPEED: - if (entry->effectvalue) - sigrenderer->tick = sigrenderer->speed = entry->effectvalue; - else if (sigdata->flags & IT_WAS_AN_XM) { - sigrenderer->speed = 0; - if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data)) - return 1; - } - break; - - case IT_JUMP_TO_ORDER: sigrenderer->processorder = entry->effectvalue - 1; sigrenderer->processrow = 0xFFFE; break; - case IT_BREAK_TO_ROW: sigrenderer->breakrow = entry->effectvalue; sigrenderer->processrow = 0xFFFE; break; - - case IT_VOLSLIDE_VIBRATO: - if (channel->playing) { - channel->playing->vibrato_speed = channel->lastHspeed; - channel->playing->vibrato_depth = channel->lastHdepth; - channel->playing->vibrato_n++; - } - /* Fall through and process volume slide. */ - case IT_VOLUME_SLIDE: - case IT_VOLSLIDE_TONEPORTA: - /* The tone portamento component is handled elsewhere. */ - { - unsigned char v = entry->effectvalue; - if (!(sigdata->flags & IT_WAS_A_MOD)) { - if (v == 0) - v = channel->lastDKL; - channel->lastDKL = v; - } - if ((v & 0x0F) == 0) { /* Dx0 */ - channel->volslide = v >> 4; - if (channel->volslide == 15 && !(sigdata->flags & IT_WAS_AN_XM)) { - channel->volume += 15; - if (channel->volume > 64) channel->volume = 64; - } - } else if ((v & 0xF0) == 0) { /* D0x */ - channel->volslide = -v; - if (channel->volslide == -15 && !(sigdata->flags & IT_WAS_AN_XM)) { - channel->volume -= 15; - if (channel->volume > 64) channel->volume = 0; - } - } else if ((v & 0x0F) == 0x0F) { /* DxF */ - channel->volume += v >> 4; - if (channel->volume > 64) channel->volume = 64; - } else if ((v & 0xF0) == 0xF0) { /* DFx */ - channel->volume -= v & 15; - if (channel->volume > 64) channel->volume = 0; - } - } - break; - case IT_XM_FINE_VOLSLIDE_DOWN: - { - unsigned char v = entry->effectvalue; - if (v == 0) - v = channel->xm_lastEB; - channel->xm_lastEB = v; - channel->volume -= v; - if (channel->volume > 64) channel->volume = 0; - } - break; - case IT_XM_FINE_VOLSLIDE_UP: - { - unsigned char v = entry->effectvalue; - if (v == 0) - v = channel->xm_lastEA; - channel->xm_lastEA = v; - channel->volume += v; - if (channel->volume > 64) channel->volume = 64; - } - break; - case IT_PORTAMENTO_DOWN: - { - unsigned char v = entry->effectvalue; - if (sigdata->flags & IT_WAS_AN_XM) { - if (!(sigdata->flags & IT_WAS_A_MOD)) { - if (v == 0xF0) - v |= channel->xm_lastE2; - else if (v >= 0xF0) - channel->xm_lastE2 = v & 15; - else if (v == 0xE0) - v |= channel->xm_lastX2; - else - channel->xm_lastX2 = v & 15; - } - } else { - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - } - if (channel->playing) { - if ((v & 0xF0) == 0xF0) - channel->playing->slide -= (v & 15) << 4; - else if ((v & 0xF0) == 0xE0) - channel->playing->slide -= (v & 15) << 2; - else - channel->portamento -= v << 4; - } - } - break; - case IT_PORTAMENTO_UP: - { - unsigned char v = entry->effectvalue; - if (sigdata->flags & IT_WAS_AN_XM) { - if (!(sigdata->flags & IT_WAS_A_MOD)) { - if (v == 0xF0) - v |= channel->xm_lastE1; - else if (v >= 0xF0) - channel->xm_lastE1 = v & 15; - else if (v == 0xE0) - v |= channel->xm_lastX1; - else - channel->xm_lastX1 = v & 15; - } - } else { - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - } - if (channel->playing) { - if ((v & 0xF0) == 0xF0) - channel->playing->slide += (v & 15) << 4; - else if ((v & 0xF0) == 0xE0) - channel->playing->slide += (v & 15) << 2; - else - channel->portamento += v << 4; - } - } - break; - case IT_XM_PORTAMENTO_DOWN: - { - unsigned char v = entry->effectvalue; - if (!(sigdata->flags & IT_WAS_A_MOD)) { - if (v == 0) - v = channel->lastJ; - channel->lastJ = v; - } - if (channel->playing) - channel->portamento -= v << 4; - } - break; - case IT_XM_PORTAMENTO_UP: - { - unsigned char v = entry->effectvalue; - if (!(sigdata->flags & IT_WAS_A_MOD)) { - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - } - if (channel->playing) - channel->portamento += v << 4; - } - break; - case IT_VIBRATO: - { - unsigned char speed = entry->effectvalue >> 4; - unsigned char depth = entry->effectvalue & 15; - if (speed == 0) - speed = channel->lastHspeed; - channel->lastHspeed = speed; - if (depth == 0) - depth = channel->lastHdepth; - else { - if (sigdata->flags & IT_OLD_EFFECTS) - depth <<= 3; - else - depth <<= 2; - channel->lastHdepth = depth; - } - if (channel->playing) { - channel->playing->vibrato_speed = speed; - channel->playing->vibrato_depth = depth; - channel->playing->vibrato_n++; - } - } - break; - case IT_TREMOR: - { - unsigned char v = entry->effectvalue; - if (v == 0) - v = channel->lastI; - else if (!(sigdata->flags & IT_OLD_EFFECTS)) { - if (v & 0xF0) v -= 0x10; - if (v & 0x0F) v -= 0x01; - } - channel->lastI = v; - channel->tremor_time |= 128; - } - update_tremor(channel); - break; - case IT_ARPEGGIO: - { - unsigned char v = entry->effectvalue; - /* XM files have no memory for arpeggio (000 = no effect) - * and we use lastJ for portamento down instead. - */ - if (!(sigdata->flags & IT_WAS_AN_XM)) { - if (v == 0) - v = channel->lastJ; - channel->lastJ = v; - } - channel->arpeggio = v; - } - break; - case IT_SET_CHANNEL_VOLUME: - if (sigdata->flags & IT_WAS_AN_XM) - channel->volume = MIN(entry->effectvalue, 64); - else if (entry->effectvalue <= 64) - channel->channelvolume = entry->effectvalue; -#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM - else - channel->channelvolume = 64; -#endif - if (channel->playing) - channel->playing->channel_volume = channel->channelvolume; - break; - case IT_CHANNEL_VOLUME_SLIDE: - { - unsigned char v = entry->effectvalue; - if (v == 0) - v = channel->lastN; - channel->lastN = v; - if ((v & 0x0F) == 0) { /* Nx0 */ - channel->channelvolslide = v >> 4; - } else if ((v & 0xF0) == 0) { /* N0x */ - channel->channelvolslide = -v; - } else { - if ((v & 0x0F) == 0x0F) { /* NxF */ - channel->channelvolume += v >> 4; - if (channel->channelvolume > 64) channel->channelvolume = 64; - } else if ((v & 0xF0) == 0xF0) { /* NFx */ - channel->channelvolume -= v & 15; - if (channel->channelvolume > 64) channel->channelvolume = 0; - } else - break; - if (channel->playing) - channel->playing->channel_volume = channel->channelvolume; - } - } - break; - case IT_SET_SAMPLE_OFFSET: - { - unsigned char v = entry->effectvalue; - if (sigdata->flags & IT_WAS_A_MOD) { - if (v == 0) break; - } else { - if (v == 0) - v = channel->lastO; - channel->lastO = v; - } - /* Note: we set the offset even if tone portamento is - * specified. Impulse Tracker does the same. - */ - if (entry->mask & IT_ENTRY_NOTE) { - if (channel->playing) { - int offset = ((int)channel->high_offset << 16) | ((int)v << 8); - IT_PLAYING *playing = channel->playing; - IT_SAMPLE *sample = playing->sample; - int end; - if ((sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) - end = sample->sus_loop_end; - else if (sample->flags & IT_SAMPLE_LOOP) - end = sample->loop_end; - else - end = sample->length; - if (offset < end) - it_playing_reset_resamplers(playing, offset); - else if (sigdata->flags & IT_OLD_EFFECTS) - it_playing_reset_resamplers(playing, end); - } - } - } - break; - //case IT_PANNING_SLIDE: - /** JULIEN: guess what? the docs are wrong! (how unusual ;) - * Pxy seems to memorize its previous value... and there - * might be other mistakes like that... (sigh!) - */ - /** ENTHEH: umm... but... the docs say that Pxy memorises its - * value... don't they? :o - */ - case IT_RETRIGGER_NOTE: - { - unsigned char v = entry->effectvalue; - if (sigdata->flags & IT_WAS_AN_XM) { - if ((v & 0x0F) == 0) v |= channel->lastQ & 0x0F; - if ((v & 0xF0) == 0) v |= channel->lastQ & 0xF0; - } else { - if (v == 0) - v = channel->lastQ; - } - channel->lastQ = v; - if ((v & 0x0F) == 0) v |= 0x01; - channel->retrig = v; - if (entry->mask & IT_ENTRY_NOTE) { - channel->retrig_tick = v & 0x0F; - /* Emulate a bug */ - if (sigdata->flags & IT_WAS_AN_XM) - update_retrig(channel); - } else - update_retrig(channel); - } - break; - case IT_XM_RETRIGGER_NOTE: - channel->retrig_tick = channel->xm_retrig = entry->effectvalue; - if (entry->effectvalue == 0) - if (channel->playing) it_playing_reset_resamplers(channel->playing, 0); - break; - case IT_TREMOLO: - { - unsigned char speed = entry->effectvalue >> 4; - unsigned char depth = entry->effectvalue & 15; - if (speed == 0) - speed = channel->lastRspeed; - channel->lastRspeed = speed; - if (depth == 0) - depth = channel->lastRdepth; - channel->lastRdepth = depth; - if (channel->playing) { - channel->playing->tremolo_speed = speed; - channel->playing->tremolo_depth = depth; - } - } - break; - case IT_S: - { - /* channel->lastS was set in update_pattern_variables(). */ - unsigned char effectvalue = channel->lastS; - switch (effectvalue >> 4) { - //case IT_S_SET_FILTER: - //case IT_S_SET_GLISSANDO_CONTROL: - //case IT_S_FINETUNE: - //case IT_S_SET_VIBRATO_WAVEFORM: - //case IT_S_SET_TREMOLO_WAVEFORM: - //case IT_S_SET_PANBRELLO_WAVEFORM: - /* Waveforms for commands S3x, S4x and S5x: - * 0: Sine wave - * 1: Ramp down - * 2: Square wave - * 3: Random wave - */ - case IT_S_FINE_PATTERN_DELAY: - sigrenderer->tick += effectvalue & 15; - break; - //case IT_S7: - case IT_S_SET_PAN: - channel->pan = - ((effectvalue & 15) << 2) | - ((effectvalue & 15) >> 2); - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - break; - case IT_S_SET_SURROUND_SOUND: - if ((effectvalue & 15) == 1) - channel->pan = IT_SURROUND; - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - break; - case IT_S_SET_HIGH_OFFSET: - channel->high_offset = effectvalue & 15; - break; - //case IT_S_PATTERN_LOOP: - case IT_S_DELAYED_NOTE_CUT: - channel->note_cut_count = effectvalue & 15; - if (!channel->note_cut_count) { - if (sigdata->flags & IT_WAS_AN_XM) - channel->volume = 0; - else - channel->note_cut_count = 1; - } - break; - case IT_S_SET_MIDI_MACRO: - channel->SFmacro = effectvalue & 15; - break; - } - } - break; - case IT_SET_SONG_TEMPO: - { - unsigned char v = entry->effectvalue; - if (v == 0) - v = channel->lastW; - channel->lastW = v; - if (v < 0x10) - sigrenderer->temposlide = -v; - else if (v < 0x20) - sigrenderer->temposlide = v & 15; - else - sigrenderer->tempo = v; - } - break; - case IT_FINE_VIBRATO: - { - unsigned char speed = entry->effectvalue >> 4; - unsigned char depth = entry->effectvalue & 15; - if (speed == 0) - speed = channel->lastHspeed; - channel->lastHspeed = speed; - if (depth == 0) - depth = channel->lastHdepth; - else { - if (sigdata->flags & IT_OLD_EFFECTS) - depth <<= 1; - channel->lastHdepth = depth; - } - if (channel->playing) { - channel->playing->vibrato_speed = speed; - channel->playing->vibrato_depth = depth; - channel->playing->vibrato_n++; - } - } - break; - case IT_SET_GLOBAL_VOLUME: - if (entry->effectvalue <= 128) - sigrenderer->globalvolume = entry->effectvalue; -#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM - else - sigrenderer->globalvolume = 128; -#endif - break; - case IT_GLOBAL_VOLUME_SLIDE: - { - unsigned char v = entry->effectvalue; - if (v == 0) - v = channel->lastW; - channel->lastW = v; - if ((v & 0x0F) == 0) { /* Wx0 */ - sigrenderer->globalvolslide = - (sigdata->flags & IT_WAS_AN_XM) ? (v >> 4)*2 : (v >> 4); - } else if ((v & 0xF0) == 0) { /* W0x */ - sigrenderer->globalvolslide = - (sigdata->flags & IT_WAS_AN_XM) ? (-v)*2 : (-v); - } else if ((v & 0x0F) == 0x0F) { /* WxF */ - sigrenderer->globalvolume += v >> 4; - if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 128; - } else if ((v & 0xF0) == 0xF0) { /* WFx */ - sigrenderer->globalvolume -= v & 15; - if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 0; - } - } - break; - case IT_SET_PANNING: - channel->pan = (entry->effectvalue + 2) >> 2; - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - break; - //case IT_PANBRELLO: - case IT_MIDI_MACRO: - { - IT_MIDI *midi = sigdata->midi ? sigdata->midi : &default_midi; - if (entry->effectvalue >= 0x80) { - int n = midi->Zmacrolen[entry->effectvalue-0x80]; - int i; - for (i = 0; i < n; i++) - it_send_midi(sigrenderer, channel, midi->Zmacro[entry->effectvalue-0x80][i]); - } else { - int n = midi->SFmacrolen[channel->SFmacro]; - int i, j; - for (i = 0, j = 1; i < n; i++, j <<= 1) - it_send_midi(sigrenderer, channel, - midi->SFmacroz[channel->SFmacro] & j ? - entry->effectvalue : midi->SFmacro[channel->SFmacro][i]); - } - } - break; - } - } - - if (!(sigdata->flags & IT_WAS_AN_XM)) - post_process_it_volpan(sigrenderer, entry); - - return 0; -} - - - -static int process_it_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel]; - - // When tone portamento and instrument are specified: - // If Gxx is off: - // - same sample, do nothing but portamento - // - diff sample, retrigger all but keep current note+slide + do porta - // - if instrument is invalid, nothing; if sample is invalid, cut - // If Gxx is on: - // - same sample or new sample invalid, retrigger envelopes - // - diff sample/inst, start using new envelopes - // When tone portamento is specified alone, sample won't change. - // TODO: consider what happens with instrument alone after all this... - - if (entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) { - if (entry->mask & IT_ENTRY_INSTRUMENT) - channel->instrument = entry->instrument; - instrument_to_sample(sigdata, channel); - if (channel->note < 120) { - if ((sigdata->flags & IT_USE_INSTRUMENTS) && channel->sample == 0) - return 1; - if (entry->mask & IT_ENTRY_INSTRUMENT) - get_default_volpan(sigdata, channel); - } else - it_retrigger_note(sigrenderer, channel); - } - - /** WARNING: This is not ideal, since channel->playing might not get allocated owing to lack of memory... */ - if (channel->playing && - (((entry->mask & IT_ENTRY_VOLPAN) && entry->volpan >= 193 && entry->volpan <= 202) || - ((entry->mask & IT_ENTRY_EFFECT) && (entry->effect == IT_TONE_PORTAMENTO || entry->effect == IT_VOLSLIDE_TONEPORTA)))) - { - if (entry->mask & IT_ENTRY_INSTRUMENT) { - if (sigdata->flags & IT_COMPATIBLE_GXX) - retrigger_it_envelopes(sigdata, channel); - else if ((!(sigdata->flags & IT_USE_INSTRUMENTS) || - (channel->instrument >= 1 && channel->instrument <= sigdata->n_instruments)) && - channel->sample != channel->playing->sampnum) - { - unsigned char note = channel->playing->note; - int slide = channel->playing->slide; - it_retrigger_note(sigrenderer, channel); - if (channel->playing) { - channel->playing->note = note; - channel->playing->slide = slide; - // Should we be preserving sample_vibrato_time? depth? - } - } - } - - if ((entry->mask & IT_ENTRY_VOLPAN) && entry->volpan >= 193 && entry->volpan <= 202) { - /* Tone Portamento in the volume column */ - static const unsigned char slidetable[] = {0, 1, 4, 8, 16, 32, 64, 96, 128, 255}; - unsigned char v = slidetable[entry->volpan - 193]; - if (sigdata->flags & IT_COMPATIBLE_GXX) { - if (v == 0) - v = channel->lastG; - channel->lastG = v; - } else { - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - } - if (entry->mask & IT_ENTRY_NOTE) - if (channel->sample) - channel->destnote = channel->truenote; - channel->toneporta = v << 4; - } else { - /* Tone Portamento in the effect column */ - unsigned char v; - if (entry->effect == IT_TONE_PORTAMENTO) - v = entry->effectvalue; - else - v = 0; - if (sigdata->flags & IT_COMPATIBLE_GXX) { - if (v == 0) - v = channel->lastG; - channel->lastG = v; - } else { - if (v == 0) - v = channel->lastEF; - channel->lastEF = v; - } - if (entry->mask & IT_ENTRY_NOTE) - if (channel->sample) - channel->destnote = channel->truenote; - channel->toneporta = v << 4; - } - } else if ((entry->mask & IT_ENTRY_NOTE) || - ((entry->mask & IT_ENTRY_INSTRUMENT) && (!channel->playing || entry->instrument != channel->playing->instnum))) - { - if (channel->note < 120) { - get_true_pan(sigdata, channel); - it_retrigger_note(sigrenderer, channel); - } - } - - if (entry->mask & IT_ENTRY_VOLPAN) { - if (entry->volpan <= 64) { - /* Volume */ - channel->volume = entry->volpan; - } else if (entry->volpan <= 74) { - /* Fine volume slide up */ - unsigned char v = entry->volpan - 65; - if (v == 0) - v = channel->lastvolslide; - channel->lastvolslide = v; - /* = effect DxF where x == entry->volpan - 65 */ - channel->volume += v; - if (channel->volume > 64) channel->volume = 64; - } else if (entry->volpan <= 84) { - /* Fine volume slide down */ - unsigned char v = entry->volpan - 75; - if (v == 0) - v = channel->lastvolslide; - channel->lastvolslide = v; - /* = effect DFx where x == entry->volpan - 75 */ - channel->volume -= v; - if (channel->volume > 64) channel->volume = 0; - } else if (entry->volpan < 128) { - /* Volume slide up */ - /* Volume slide down */ - /* Portamento down */ - /* Portamento up */ - } else if (entry->volpan <= 192) { - /* Pan */ - channel->pan = entry->volpan - 128; - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - } - /* else */ - /* Tone Portamento */ - /* Vibrato */ - } - return 0; -} - - - -static void retrigger_xm_envelopes(IT_PLAYING *playing) -{ - playing->volume_envelope.next_node = 0; - playing->volume_envelope.tick = -1; - playing->pan_envelope.next_node = 0; - playing->pan_envelope.tick = -1; - playing->fadeoutcount = 1024; -} - - - -static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel]; - - if (entry->mask & IT_ENTRY_INSTRUMENT) { - channel->instrument = entry->instrument; - instrument_to_sample(sigdata, channel); - if (channel->playing) { - /* Retrigger vol/pan envelopes if enabled, and cancel fadeout. - * Also reset vol/pan to that of _original_ instrument. - */ - channel->playing->flags &= ~(IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING); - it_playing_update_resamplers(channel->playing); - - channel->volume = channel->playing->sample->default_volume; - if (channel->pan >= 128 && channel->pan <= 192) - channel->pan = channel->playing->sample->default_pan - 128; - - retrigger_xm_envelopes(channel->playing); - } - } - - if (entry->mask & IT_ENTRY_NOTE) { - if (!(entry->mask & IT_ENTRY_INSTRUMENT)) - instrument_to_sample(sigdata, channel); - - if (channel->note >= 120) { - if (channel->playing) { - if (!(sigdata->instrument[channel->instrument-1].volume_envelope.flags & IT_ENVELOPE_ON)) - if (!(entry->mask & IT_ENTRY_INSTRUMENT)) - channel->volume = 0; - channel->playing->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING; - it_playing_update_resamplers(channel->playing); - } - } else if (channel->sample == 0) { - /** If we get here, one of the following is the case: - ** 1. The instrument has never been specified on this channel. - ** 2. The specified instrument is invalid. - ** 3. The instrument has no sample mapped to the selected note. - ** What should happen? - ** - ** Experimentation shows that any existing note stops and cannot - ** be brought back. A subsequent instrument change fixes that. - **/ - if (channel->playing) { - free(channel->playing); - channel->playing = NULL; - } - return; - } else if (channel->playing && (entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) { - /* Don't retrigger note; portamento in the volume column. */ - } else if (channel->playing && - (entry->mask & IT_ENTRY_EFFECT) && - (entry->effect == IT_TONE_PORTAMENTO || - entry->effect == IT_VOLSLIDE_TONEPORTA)) { - /* Don't retrigger note; portamento in the effects column. */ - } else { - channel->destnote = IT_NOTE_OFF; - - if (!channel->playing) { - channel->playing = malloc(sizeof(*channel->playing)); - if (!channel->playing) - return; - // Adding the following seems to do the trick for the case where a piece starts with an instrument alone and then some notes alone. - retrigger_xm_envelopes(channel->playing); - } - - channel->playing->flags = 0; - channel->playing->channel = channel; - channel->playing->sample = &sigdata->sample[channel->sample-1]; - if (sigdata->flags & IT_USE_INSTRUMENTS) - channel->playing->instrument = &sigdata->instrument[channel->instrument-1]; - else - channel->playing->instrument = NULL; - channel->playing->env_instrument = channel->playing->instrument; - channel->playing->sampnum = channel->sample; - channel->playing->instnum = channel->instrument; - channel->playing->channel_volume = channel->channelvolume; - channel->playing->note = channel->truenote; - channel->playing->filter_cutoff = 127; - channel->playing->filter_resonance = 0; - channel->playing->true_filter_cutoff = 127 << 8; - channel->playing->true_filter_resonance = 0; - channel->playing->vibrato_speed = 0; - channel->playing->vibrato_depth = 0; - channel->playing->vibrato_n = 0; - channel->playing->vibrato_time = 0; - channel->playing->tremolo_speed = 0; - channel->playing->tremolo_depth = 0; - channel->playing->tremolo_time = 0; - channel->playing->sample_vibrato_time = 0; - channel->playing->sample_vibrato_depth = 0; - channel->playing->slide = 0; - it_reset_filter_state(&channel->playing->filter_state[0]); // Are these - it_reset_filter_state(&channel->playing->filter_state[1]); // necessary? - it_playing_reset_resamplers(channel->playing, 0); - - /** WARNING - is everything initialised? */ - } - } - - if ((entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) == (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) { - if (channel->playing) retrigger_xm_envelopes(channel->playing); - get_default_volpan(sigdata, channel); - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - } - - if ((entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) { - /* Tone Portamento */ - unsigned char v = (entry->volpan & 15) << 4; - if (v == 0) - v = channel->lastG; - channel->lastG = v; - if (entry->mask & IT_ENTRY_NOTE) - if (channel->sample) - channel->destnote = channel->truenote; - channel->toneporta = v << 4; - } else if ((entry->mask & IT_ENTRY_EFFECT) && - (entry->effect == IT_TONE_PORTAMENTO || - entry->effect == IT_VOLSLIDE_TONEPORTA)) { - unsigned char v; - if (entry->effect == IT_TONE_PORTAMENTO) - v = entry->effectvalue; - else - v = 0; - if (v == 0) - v = channel->lastG; - channel->lastG = v; - if (entry->mask & IT_ENTRY_NOTE) - if (channel->sample) - channel->destnote = channel->truenote; - channel->toneporta = v << 4; - } - - if (entry->mask & IT_ENTRY_VOLPAN) { - int effect = entry->volpan >> 4; - int value = entry->volpan & 15; - switch (effect) { - case 0x6: /* Volume slide down */ - channel->xm_volslide = -value; - break; - case 0x7: /* Volume slide up */ - channel->xm_volslide = value; - break; - case 0x8: /* Fine volume slide down */ - channel->volume -= value; - if (channel->volume > 64) channel->volume = 0; - break; - case 0x9: /* Fine volume slide up */ - channel->volume += value; - if (channel->volume > 64) channel->volume = 64; - break; - case 0xA: /* Set vibrato speed */ - if (value) - channel->lastHspeed = value; - if (channel->playing) - channel->playing->vibrato_speed = channel->lastHspeed; - break; - case 0xB: /* Vibrato */ - if (value) - channel->lastHdepth = value << 2; /** WARNING: correct ? */ - if (channel->playing) { - channel->playing->vibrato_depth = channel->lastHdepth; - channel->playing->vibrato_speed = channel->lastHspeed; - channel->playing->vibrato_n++; - } - break; - case 0xC: /* Set panning */ - channel->pan = (value*64)/15; - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - break; - case 0xD: /* Pan slide left */ - // TODO - // channel->xm_panslide = -value; - break; - case 0xE: /* Pan slide Right */ - // TODO - // channel->xm_panslide = value; - break; - case 0xF: /* Tone porta */ - break; - default: /* Volume */ - channel->volume = entry->volpan - 0x10; - break; - } - } -} - - - -/* This function assumes !IT_IS_END_ROW(entry). */ -static int process_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - - if (sigdata->flags & IT_WAS_AN_XM) - process_xm_note_data(sigrenderer, entry); - else - if (process_it_note_data(sigrenderer, entry)) return 0; - - return process_effects(sigrenderer, entry); -} - - - -static int process_entry(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry) -{ - IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel]; - - if (entry->mask & IT_ENTRY_NOTE) - channel->note = entry->note; - - if ((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_S) { - /* channel->lastS was set in update_pattern_variables(). */ - unsigned char effectvalue = channel->lastS; - if (effectvalue >> 4 == IT_S_NOTE_DELAY) { - channel->note_delay_count = effectvalue & 15; - if (channel->note_delay_count == 0) - channel->note_delay_count = 1; - channel->note_delay_entry = entry; - return 0; - } - } - - return process_note_data(sigrenderer, entry); -} - - - -static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer) -{ - int i; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; - - if (channel->note_cut_count) { - channel->note_cut_count--; - if (channel->note_cut_count == 0) { - if (sigrenderer->sigdata->flags & IT_WAS_AN_XM) - channel->volume = 0; - else if (channel->playing) { - free(channel->playing); - channel->playing = NULL; - } - } - } else if (channel->note_delay_count) { - channel->note_delay_count--; - if (channel->note_delay_count == 0) - process_note_data(sigrenderer, channel->note_delay_entry); - /* Don't bother checking the return value; if the note - * was delayed, there can't have been a speed=0. - */ - } - } -} - - - -static int envelope_get_y(IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe) -{ - int ys, ye; - int ts, te; - int t; - - if (pe->next_node <= 0) - return envelope->node_y[0] << IT_ENVELOPE_SHIFT; - - if (pe->next_node >= envelope->n_nodes) - return envelope->node_y[envelope->n_nodes-1] << IT_ENVELOPE_SHIFT; - - ys = envelope->node_y[pe->next_node-1] << IT_ENVELOPE_SHIFT; - ts = envelope->node_t[pe->next_node-1]; - te = envelope->node_t[pe->next_node]; - - if (ts == te) - return ys; - - ye = envelope->node_y[pe->next_node] << IT_ENVELOPE_SHIFT; - - t = pe->tick; - - return ys + (ye - ys) * (t - ts) / (te - ts); -} - - - -static int it_envelope_end(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe) -{ - if (pe->next_node >= envelope->n_nodes) - return 1; - - if (pe->tick < envelope->node_t[pe->next_node]) return 0; - - if ((envelope->flags & IT_ENVELOPE_LOOP_ON) && - envelope->loop_end >= pe->next_node && - envelope->node_t[envelope->loop_end] <= pe->tick) return 0; - - if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && - !(playing->flags & IT_PLAYING_SUSTAINOFF) && - envelope->sus_loop_end >= pe->next_node && - envelope->node_t[envelope->sus_loop_end] <= pe->tick) return 0; - - if (envelope->node_t[envelope->n_nodes-1] <= pe->tick) return 1; - - return 0; -} - - - -/* This returns 1 if the envelope finishes. */ -static int update_it_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe) -{ - if (!(envelope->flags & IT_ENVELOPE_ON)) - return 0; - - if (pe->next_node >= envelope->n_nodes) - return 1; - - while (pe->tick >= envelope->node_t[pe->next_node]) { - if ((envelope->flags & IT_ENVELOPE_LOOP_ON) && pe->next_node == envelope->loop_end) { - pe->next_node = envelope->loop_start; - pe->tick = envelope->node_t[envelope->loop_start]; - return it_envelope_end(playing, envelope, pe); - } - if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF) && pe->next_node == envelope->sus_loop_end) { - pe->next_node = envelope->sus_loop_start; - pe->tick = envelope->node_t[envelope->sus_loop_start]; - return it_envelope_end(playing, envelope, pe); - } - - pe->next_node++; - - if (pe->next_node >= envelope->n_nodes) - return 1; - } - - pe->tick++; - - return it_envelope_end(playing, envelope, pe); -} - - - -static void update_it_envelopes(IT_PLAYING *playing) -{ - IT_ENVELOPE *envelope = &playing->env_instrument->volume_envelope; - - if (update_it_envelope(playing, envelope, &playing->volume_envelope)) { - playing->flags |= IT_PLAYING_FADING; - if (envelope->n_nodes && envelope->node_y[envelope->n_nodes-1] == 0) - playing->flags |= IT_PLAYING_DEAD; - } - - update_it_envelope(playing, &playing->env_instrument->pan_envelope, &playing->pan_envelope); - update_it_envelope(playing, &playing->env_instrument->pitch_envelope, &playing->pitch_envelope); -} - - - -static int xm_envelope_is_sustaining(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe) -{ - if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) - if (envelope->sus_loop_start < envelope->n_nodes) - if (pe->tick == envelope->node_t[envelope->sus_loop_start]) - return 1; - return 0; -} - - - -static void update_xm_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe) -{ - if (!(envelope->flags & IT_ENVELOPE_ON)) - return; - - if (xm_envelope_is_sustaining(playing, envelope, pe)) - return; - - if (pe->tick >= envelope->node_t[envelope->n_nodes-1]) - return; - - pe->tick++; - - /* pe->next_node must be kept up to date for envelope_get_y(). */ - while (pe->tick > envelope->node_t[pe->next_node]) - pe->next_node++; - - if ((envelope->flags & IT_ENVELOPE_LOOP_ON) && envelope->loop_end < envelope->n_nodes) { - if (pe->tick == envelope->node_t[envelope->loop_end]) { - pe->next_node = MID(0, envelope->loop_start, envelope->n_nodes - 1); - pe->tick = envelope->node_t[pe->next_node]; - } - } - - if (xm_envelope_is_sustaining(playing, envelope, pe)) - return; - - if (pe->tick >= envelope->node_t[envelope->n_nodes-1]) - return; -} - - - -static void update_xm_envelopes(IT_PLAYING *playing) -{ - update_xm_envelope(playing, &playing->env_instrument->volume_envelope, &playing->volume_envelope); - update_xm_envelope(playing, &playing->env_instrument->pan_envelope, &playing->pan_envelope); -} - - - -static void update_fadeout(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing) -{ - if (playing->flags & IT_PLAYING_FADING) { - playing->fadeoutcount -= playing->env_instrument->fadeout; - if (playing->fadeoutcount <= 0) { - playing->fadeoutcount = 0; - if (!(sigdata->flags & IT_WAS_AN_XM)) - playing->flags |= IT_PLAYING_DEAD; - } - } -} - - - -static void process_playing(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing) -{ - if (playing->instrument) { - if (sigdata->flags & IT_WAS_AN_XM) - update_xm_envelopes(playing); - else - update_it_envelopes(playing); - update_fadeout(sigdata, playing); - } - - //Calculate final volume if required - //Calculate final pan if required - - if (sigdata->flags & IT_WAS_AN_XM) { - /* 'depth' is used to store the tick number for XM files. */ - if (playing->sample_vibrato_depth < playing->sample->vibrato_rate) - playing->sample_vibrato_depth++; - } else { - playing->sample_vibrato_depth += playing->sample->vibrato_rate; - if (playing->sample_vibrato_depth > playing->sample->vibrato_depth << 8) - playing->sample_vibrato_depth = playing->sample->vibrato_depth << 8; - } - - playing->sample_vibrato_time += playing->sample->vibrato_speed; -} - - - -static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - int i; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; - IT_PLAYING *playing = channel->playing; - - if (playing) { - int vibrato_shift = it_sine[playing->vibrato_time]; - vibrato_shift *= playing->vibrato_n; - vibrato_shift *= playing->vibrato_depth; - vibrato_shift >>= 4; - - if (sigdata->flags & IT_OLD_EFFECTS) - vibrato_shift = -vibrato_shift; - - playing->volume = channel->volume; - playing->pan = channel->truepan; - - if (sigdata->flags & IT_LINEAR_SLIDES) { - int currpitch = ((playing->note - 60) << 8) + playing->slide - + vibrato_shift; - - /* We add a feature here, which is that of keeping the pitch - * within range. Otherwise it crashes. Trust me. It happened. - * The limit 32768 gives almost 11 octaves either way. - */ - if (currpitch < -32768) - currpitch = -32768; - else if (currpitch > 32767) - currpitch = 32767; - - playing->delta = (float)pow(DUMB_PITCH_BASE, currpitch); - playing->delta *= playing->sample->C5_speed / 65536.0f; - } else { - int slide = playing->slide + vibrato_shift; - - playing->delta = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note); - /* playing->delta is 1.0 for C-5, 0.5 for C-6, etc. */ - - playing->delta *= 1.0f / playing->sample->C5_speed; - - playing->delta -= slide / AMIGA_DIVISOR; - - if (playing->delta < (1.0f / 65536.0f) / 32768.0f) { - // Should XM notes die if Amiga slides go out of range? - playing->flags |= IT_PLAYING_DEAD; - continue; - } - - playing->delta = (1.0f / 65536.0f) / playing->delta; - } - - playing->delta *= (float)pow(DUMB_SEMITONE_BASE, channel->arpeggio >> 8); - - playing->filter_cutoff = channel->filter_cutoff; - playing->filter_resonance = channel->filter_resonance; - } - } - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - if (sigrenderer->channel[i].playing) { - process_playing(sigdata, sigrenderer->channel[i].playing); - if (!(sigdata->flags & IT_WAS_AN_XM)) { - if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) { - free(sigrenderer->channel[i].playing); - sigrenderer->channel[i].playing = NULL; - } - } - } - } - - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { - if (sigrenderer->playing[i]) { - process_playing(sigdata, sigrenderer->playing[i]); - if (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) { - free(sigrenderer->playing[i]); - sigrenderer->playing[i] = NULL; - } - } - } -} - - - -static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer) -{ - DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; - - // Set note vol/freq to vol/freq set for each channel - - if (sigrenderer->speed && --sigrenderer->tick == 0) { - reset_tick_counts(sigrenderer); - sigrenderer->tick = sigrenderer->speed; - sigrenderer->rowcount--; - if (sigrenderer->rowcount == 0) { - sigrenderer->rowcount = 1; - if (sigrenderer->pat_loop_row >= 0) { - int n = sigrenderer->pat_loop_row - 1; - sigrenderer->row = sigrenderer->processrow = n; - sigrenderer->pat_loop_row = -1; - if (n < 0) - sigrenderer->entry = NULL; - else { - sigrenderer->entry = sigrenderer->entry_start; - while (n) { - while (sigrenderer->entry < sigrenderer->entry_end) { - if (IT_IS_END_ROW(sigrenderer->entry)) { - sigrenderer->entry++; - break; - } - sigrenderer->entry++; - } - n--; - } - } - } - - sigrenderer->processrow++; - - if (sigrenderer->processrow >= sigrenderer->n_rows) { - IT_PATTERN *pattern; - int n; - - sigrenderer->processrow = sigrenderer->breakrow; - sigrenderer->breakrow = 0; - - for (;;) { - sigrenderer->processorder++; - - if (sigrenderer->processorder >= sigdata->n_orders) { - sigrenderer->processorder = sigdata->restart_position; - if (sigrenderer->processorder >= sigdata->n_orders) { - /* Restarting beyond end. We'll loop for now. */ - sigrenderer->processorder = -1; - continue; - } - } - - n = sigdata->order[sigrenderer->processorder]; - - if (n < sigdata->n_patterns) - break; - -#ifdef INVALID_ORDERS_END_SONG - if (n != IT_ORDER_SKIP) - sigrenderer->processorder = -1; -#else - if (n == IT_ORDER_END) - sigrenderer->processorder = -1; -#endif - } - - pattern = &sigdata->pattern[n]; - - sigrenderer->n_rows = pattern->n_rows; - - if (sigrenderer->processrow >= sigrenderer->n_rows) - sigrenderer->processrow = 0; - -/** WARNING - everything pertaining to a new pattern initialised? */ - - sigrenderer->entry = sigrenderer->entry_start = pattern->entry; - sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries; - - if (sigrenderer->order >= sigrenderer->processorder) { - if (sigrenderer->callbacks->loop) { - if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data)) - return 1; - if (sigrenderer->speed == 0) - goto speed0; /* I love goto */ - } - } - sigrenderer->order = sigrenderer->processorder; - - n = sigrenderer->processrow; - while (n) { - while (sigrenderer->entry < sigrenderer->entry_end) { - if (IT_IS_END_ROW(sigrenderer->entry)) { - sigrenderer->entry++; - break; - } - sigrenderer->entry++; - } - n--; - } - sigrenderer->row = sigrenderer->processrow; - } else { - if (sigrenderer->entry) { - while (sigrenderer->entry < sigrenderer->entry_end) { - if (IT_IS_END_ROW(sigrenderer->entry)) { - sigrenderer->entry++; - break; - } - sigrenderer->entry++; - } - sigrenderer->row++; - } else { - sigrenderer->entry = sigrenderer->entry_start; - sigrenderer->row = 0; - } - } - - reset_effects(sigrenderer); - - { - IT_ENTRY *entry = sigrenderer->entry; - - while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) - update_pattern_variables(sigrenderer, entry++); - } - - { - IT_ENTRY *entry = sigrenderer->entry; - - while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) - if (process_entry(sigrenderer, entry++)) - return 1; - } - - if (!(sigdata->flags & IT_OLD_EFFECTS)) - update_smooth_effects(sigrenderer); - } else { - { - IT_ENTRY *entry = sigrenderer->entry; - - while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) - process_effects(sigrenderer, entry++); - /* Don't bother checking the return value; if there - * was a pattern delay, there can't be a speed=0. - */ - } - - update_effects(sigrenderer); - } - } else { - speed0: - update_effects(sigrenderer); - update_tick_counts(sigrenderer); - } - - process_all_playing(sigrenderer); - - sigrenderer->time_left += TICK_TIME_DIVIDEND / sigrenderer->tempo; - - return 0; -} - - - -int dumb_it_max_to_mix = 64; - - - -static float calculate_volume(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume) -{ - if (volume != 0) { - int vol; - - if (playing->channel->flags & IT_CHANNEL_MUTED) - return 0; - - if ((playing->channel->tremor_time & 192) == 128) - return 0; - - vol = it_sine[playing->tremolo_time]; - vol *= playing->tremolo_depth; - - vol = (playing->volume << 5) + vol; - - if (vol <= 0) - return 0; - - if (vol > 64 << 5) - vol = 64 << 5; - - volume *= vol; /* 64 << 5 */ - volume *= playing->sample->global_volume; /* 64 */ - volume *= playing->channel_volume; /* 64 */ - volume *= sigrenderer->globalvolume; /* 128 */ - volume *= sigrenderer->sigdata->mixing_volume; /* 128 */ - volume *= 1.0f / ((64 << 5) * 64.0f * 64.0f * 128.0f * 128.0f); - - if (volume && playing->instrument) { - if (playing->env_instrument->volume_envelope.flags & IT_ENVELOPE_ON) { - volume *= envelope_get_y(&playing->env_instrument->volume_envelope, &playing->volume_envelope); - volume *= 1.0f / (64 << IT_ENVELOPE_SHIFT); - } - volume *= playing->instrument->global_volume; /* 128 */ - volume *= playing->fadeoutcount; /* 1024 */ - volume *= 1.0f / (128.0f * 1024.0f); - } - } - - return volume; -} - - - -static int apply_pan_envelope(IT_PLAYING *playing) -{ - int pan = playing->pan; - if (pan <= 64 << IT_ENVELOPE_SHIFT && playing->env_instrument && (playing->env_instrument->pan_envelope.flags & IT_ENVELOPE_ON)) { - int p = envelope_get_y(&playing->env_instrument->pan_envelope, &playing->pan_envelope); - if (pan > 32 << IT_ENVELOPE_SHIFT) - p *= (64 << IT_ENVELOPE_SHIFT) - pan; - else - p *= pan; - pan += p >> (5 + IT_ENVELOPE_SHIFT); - } - return pan; -} - - - -/* Note: if a click remover is provided, and store_end_sample is set, then - * the end point will be computed twice. This situation should not arise. - */ -static long render_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume, float delta, long pos, long size, sample_t **samples, int store_end_sample, int *left_to_mix) -{ - int pan; - - long size_rendered; - - if (playing->flags & IT_PLAYING_DEAD) - return 0; - - if (*left_to_mix <= 0) - volume = 0; - - pan = apply_pan_envelope(playing); - -#define RESAMPLERV(rv, resampler, dst, volume) \ -{ \ - rv = dumb_resample(resampler, dst, size, volume, delta); \ - if (store_end_sample) \ - (dst)[rv] = RESAMPLE_VALUE(resampler, volume); \ -} - -#define RESAMPLE(resampler, dst, volume) \ -{ \ - int i; \ - RESAMPLERV(i, resampler, dst, volume); \ -} - -#define RESAMPLE_VALUE(resampler, volume) \ - dumb_resample_get_current_sample(resampler, volume) - - if (volume == 0) { - size_rendered = dumb_resample(&playing->resampler[0], NULL, size, 0, delta); - if (playing->sample->flags & IT_SAMPLE_STEREO) - dumb_resample(&playing->resampler[1], NULL, size, 0, delta); - } else { - if (sigrenderer->n_channels == 2) { - float vol = volume; - DUMB_RESAMPLER start = playing->resampler[0]; - if (!IT_IS_SURROUND_SHIFTED(pan)) vol *= 2.0f - pan * (1.0f / (32 << IT_ENVELOPE_SHIFT)); - if (sigrenderer->click_remover && sigrenderer->click_remover[0]) - dumb_record_click(sigrenderer->click_remover[0], pos, RESAMPLE_VALUE(&playing->resampler[0], vol)); - RESAMPLERV(size_rendered, &playing->resampler[0], samples[0] + pos, vol); - if (sigrenderer->click_remover && sigrenderer->click_remover[0]) - dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[0], vol)); - vol = -vol; - if (!IT_IS_SURROUND_SHIFTED(pan)) vol += 2.0f * volume; - if (playing->sample->flags & IT_SAMPLE_STEREO) { - if (sigrenderer->click_remover && sigrenderer->click_remover[1]) - dumb_record_click(sigrenderer->click_remover[1], pos, RESAMPLE_VALUE(&playing->resampler[1], vol)); - RESAMPLE(&playing->resampler[1], samples[1] + pos, vol); - if (sigrenderer->click_remover && sigrenderer->click_remover[1]) - dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[1], vol)); - } else { - playing->resampler[0] = start; - if (sigrenderer->click_remover && sigrenderer->click_remover[1]) - dumb_record_click(sigrenderer->click_remover[1], pos, RESAMPLE_VALUE(&playing->resampler[0], vol)); - RESAMPLE(&playing->resampler[0], samples[1] + pos, vol); - if (sigrenderer->click_remover && sigrenderer->click_remover[1]) - dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[0], vol)); - } - } else { - if (playing->sample->flags & IT_SAMPLE_STEREO) { - float vol = 0.5f * volume; - if (!IT_IS_SURROUND_SHIFTED(pan)) vol *= 2.0f - pan * (1.0f / (32 << IT_ENVELOPE_SHIFT)); - if (sigrenderer->click_remover && sigrenderer->click_remover[0]) { - sample_t startstep, endstep; - startstep = RESAMPLE_VALUE(&playing->resampler[0], vol); - RESAMPLE(&playing->resampler[0], samples[0] + pos, vol); - endstep = RESAMPLE_VALUE(&playing->resampler[0], vol); - if (!IT_IS_SURROUND_SHIFTED(pan)) vol = 2.0f * volume - vol; - startstep += RESAMPLE_VALUE(&playing->resampler[1], vol); - RESAMPLERV(size_rendered, &playing->resampler[1], samples[0] + pos, vol); - endstep += RESAMPLE_VALUE(&playing->resampler[1], vol); - dumb_record_click(sigrenderer->click_remover[0], pos, startstep); - dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -endstep); - } else { - RESAMPLE(&playing->resampler[0], samples[0] + pos, vol); - if (!IT_IS_SURROUND_SHIFTED(pan)) vol = 2.0f * volume - vol; - RESAMPLERV(size_rendered, &playing->resampler[1], samples[0] + pos, vol); - } - } else { - if (sigrenderer->click_remover && sigrenderer->click_remover[0]) - dumb_record_click(sigrenderer->click_remover[0], pos, RESAMPLE_VALUE(&playing->resampler[0], volume)); - RESAMPLERV(size_rendered, &playing->resampler[0], samples[0] + pos, volume); - if (sigrenderer->click_remover && sigrenderer->click_remover[0]) - dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[0], volume)); - } - } - (*left_to_mix)--; - } - - if (playing->resampler[0].dir == 0) - playing->flags |= IT_PLAYING_DEAD; - - return size_rendered; -} - - - -typedef struct IT_TO_MIX -{ - IT_PLAYING *playing; - float volume; -} -IT_TO_MIX; - - - -static int it_to_mix_compare(const void *e1, const void *e2) -{ - if (((const IT_TO_MIX *)e1)->volume > ((const IT_TO_MIX *)e2)->volume) - return -1; - - if (((const IT_TO_MIX *)e1)->volume < ((const IT_TO_MIX *)e2)->volume) - return 1; - - return 0; -} - - - -static void apply_pitch_modifications(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing, float *delta, int *cutoff) -{ - { - int sample_vibrato_shift = it_sine[playing->sample_vibrato_time]; - - if (sigdata->flags & IT_WAS_AN_XM) { - int depth = playing->sample->vibrato_depth; /* True depth */ - if (playing->sample->vibrato_rate) { - depth *= playing->sample_vibrato_depth; /* Tick number */ - depth /= playing->sample->vibrato_rate; /* XM sweep */ - } - sample_vibrato_shift *= depth; - } else - sample_vibrato_shift *= playing->sample_vibrato_depth >> 8; - - sample_vibrato_shift >>= 4; - - *delta *= (float)pow(DUMB_PITCH_BASE, sample_vibrato_shift); - } - - if (playing->env_instrument && - (playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_ON)) - { - int p = envelope_get_y(&playing->env_instrument->pitch_envelope, &playing->pitch_envelope); - if (playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_PITCH_IS_FILTER) - *cutoff = (*cutoff * (p+(32<> (6 + IT_ENVELOPE_SHIFT); - else - *delta *= (float)pow(DUMB_PITCH_BASE, p >> (IT_ENVELOPE_SHIFT - 7)); - } -} - - - -static void render(DUMB_IT_SIGRENDERER *sigrenderer, float volume, float delta, long pos, long size, sample_t **samples) -{ - int i; - - int n_to_mix = 0; - IT_TO_MIX to_mix[DUMB_IT_TOTAL_CHANNELS]; - int left_to_mix = dumb_it_max_to_mix; - - sample_t **samples_to_filter = NULL; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - if (sigrenderer->channel[i].playing && !(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) { - to_mix[n_to_mix].playing = sigrenderer->channel[i].playing; - to_mix[n_to_mix].volume = volume == 0 ? 0 : calculate_volume(sigrenderer, sigrenderer->channel[i].playing, volume); - n_to_mix++; - } - } - - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { - if (sigrenderer->playing[i]) { /* Won't be dead; it would have been freed. */ - to_mix[n_to_mix].playing = sigrenderer->playing[i]; - to_mix[n_to_mix].volume = volume == 0 ? 0 : calculate_volume(sigrenderer, sigrenderer->playing[i], volume); - n_to_mix++; - } - } - - if (volume != 0) - qsort(to_mix, n_to_mix, sizeof(IT_TO_MIX), &it_to_mix_compare); - - for (i = 0; i < n_to_mix; i++) { - IT_PLAYING *playing = to_mix[i].playing; - float note_delta = delta * playing->delta; - int cutoff = playing->filter_cutoff << IT_ENVELOPE_SHIFT; - - apply_pitch_modifications(sigrenderer->sigdata, playing, ¬e_delta, &cutoff); - - if (cutoff != 127 << IT_ENVELOPE_SHIFT || playing->filter_resonance != 0) { - playing->true_filter_cutoff = cutoff; - playing->true_filter_resonance = playing->filter_resonance; - } - - if (to_mix[i].volume && (playing->true_filter_cutoff != 127 << IT_ENVELOPE_SHIFT || playing->true_filter_resonance != 0)) { - if (!samples_to_filter) { - samples_to_filter = create_sample_buffer(sigrenderer->n_channels, size + 1); - if (!samples_to_filter) { - render_playing(sigrenderer, playing, 0, note_delta, pos, size, NULL, 0, &left_to_mix); - continue; - } - } - { - long size_rendered; - DUMB_CLICK_REMOVER **cr = sigrenderer->click_remover; - dumb_silence(samples_to_filter[0], sigrenderer->n_channels * (size + 1)); - sigrenderer->click_remover = NULL; - size_rendered = render_playing(sigrenderer, playing, to_mix[i].volume, note_delta, 0, size, samples_to_filter, 1, &left_to_mix); - sigrenderer->click_remover = cr; - it_filter(cr ? cr[0] : NULL, &playing->filter_state[0], samples[0], pos, samples_to_filter[0], size_rendered, - 65536.0f/delta, playing->true_filter_cutoff, playing->true_filter_resonance); - if (sigrenderer->n_channels == 2) - it_filter(cr ? cr[1] : NULL, &playing->filter_state[1], samples[1], pos, samples_to_filter[1], size_rendered, - 65536.0f/delta, playing->true_filter_cutoff, playing->true_filter_resonance); - // warning: filtering is not prevented by low left_to_mix! - } - } else { - it_reset_filter_state(&playing->filter_state[0]); - it_reset_filter_state(&playing->filter_state[1]); - render_playing(sigrenderer, playing, to_mix[i].volume, note_delta, pos, size, samples, 0, &left_to_mix); - } - } - - destroy_sample_buffer(samples_to_filter); - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - if (sigrenderer->channel[i].playing) { - if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) { - free(sigrenderer->channel[i].playing); - sigrenderer->channel[i].playing = NULL; - } - } - } - - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { - if (sigrenderer->playing[i]) { - if (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) { - free(sigrenderer->playing[i]); - sigrenderer->playing[i] = NULL; - } - } - } -} - - - -static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_channels, int startorder, IT_CALLBACKS *callbacks, DUMB_CLICK_REMOVER **cr) -{ - DUMB_IT_SIGRENDERER *sigrenderer; - int i; - - if (startorder > sigdata->n_orders) { - free(callbacks); - dumb_destroy_click_remover_array(n_channels, cr); - return NULL; - } - - sigrenderer = malloc(sizeof(*sigrenderer)); - if (!sigrenderer) { - free(callbacks); - dumb_destroy_click_remover_array(n_channels, cr); - return NULL; - } - - sigrenderer->callbacks = callbacks; - sigrenderer->click_remover = cr; - - sigrenderer->sigdata = sigdata; - sigrenderer->n_channels = n_channels; - sigrenderer->globalvolume = sigdata->global_volume; - sigrenderer->tempo = sigdata->tempo; - - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) { - IT_CHANNEL *channel = &sigrenderer->channel[i]; -#if IT_CHANNEL_MUTED != 1 -#error this is wrong -#endif - channel->flags = sigdata->channel_pan[i] >> 7; - channel->volume = (sigdata->flags & IT_WAS_AN_XM) ? 0 : 64; - channel->pan = sigdata->channel_pan[i] & 0x7F; - channel->truepan = channel->pan << IT_ENVELOPE_SHIFT; - channel->channelvolume = sigdata->channel_volume[i]; - channel->instrument = 0; - channel->note = 0; - channel->SFmacro = 0; - channel->filter_cutoff = 127; - channel->filter_resonance = 0; - channel->xm_retrig = 0; - channel->retrig_tick = 0; - channel->tremor_time = 0; - channel->midi_state = 0; - channel->lastvolslide = 0; - channel->lastDKL = 0; - channel->lastEF = 0; - channel->lastG = 0; - channel->lastHspeed = 0; - channel->lastHdepth = 0; - channel->lastRspeed = 0; - channel->lastRdepth = 0; - channel->lastI = 0; - channel->lastJ = 0; - channel->lastN = 0; - channel->lastO = 0; - channel->high_offset = 0; - channel->lastQ = 0; - channel->lastS = 0; - channel->pat_loop_row = 0; - channel->pat_loop_count = 0; - channel->lastW = 0; - channel->xm_lastE1 = 0; - channel->xm_lastE2 = 0; - channel->xm_lastEA = 0; - channel->xm_lastEB = 0; - channel->xm_lastX1 = 0; - channel->xm_lastX2 = 0; - channel->playing = NULL; - } - - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) - sigrenderer->playing[i] = NULL; - - sigrenderer->speed = sigdata->speed; - - sigrenderer->processrow = 0; - sigrenderer->breakrow = 0; - sigrenderer->pat_loop_row = -1; - sigrenderer->rowcount = 1; - - reset_tick_counts(sigrenderer); - - sigrenderer->tick = sigrenderer->speed; - - { - IT_PATTERN *pattern; - int n; - - sigrenderer->processorder = startorder; - for (;;) { - n = sigdata->order[sigrenderer->processorder]; - - if (n < sigdata->n_patterns) - break; - -#ifdef INVALID_ORDERS_END_SONG - if (n != IT_ORDER_SKIP) -#else - if (n == IT_ORDER_END) -#endif - { - _dumb_it_end_sigrenderer(sigrenderer); - return NULL; - } - - sigrenderer->processorder++; - if (sigrenderer->processorder >= sigdata->n_orders) - sigrenderer->processorder = 0; - if (sigrenderer->processorder == startorder) { - _dumb_it_end_sigrenderer(sigrenderer); - return NULL; - } - } - - pattern = &sigdata->pattern[n]; - - sigrenderer->n_rows = pattern->n_rows; - -/** WARNING - everything pertaining to a new pattern initialised? */ - - sigrenderer->entry = sigrenderer->entry_start = pattern->entry; - sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries; - - sigrenderer->order = sigrenderer->processorder; - sigrenderer->row = 0; - } - - reset_effects(sigrenderer); - - { - IT_ENTRY *entry = sigrenderer->entry; - - while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) - update_pattern_variables(sigrenderer, entry++); - } - - { - IT_ENTRY *entry = sigrenderer->entry; - - while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) { - if (process_entry(sigrenderer, entry++)) { - /* Oops, that song ended quickly! */ - _dumb_it_end_sigrenderer(sigrenderer); - return NULL; - } - } - } - - if (!(sigdata->flags & IT_OLD_EFFECTS)) - update_smooth_effects(sigrenderer); - - process_all_playing(sigrenderer); - - sigrenderer->time_left = TICK_TIME_DIVIDEND / sigrenderer->tempo; - sigrenderer->sub_time_left = 0; - - return sigrenderer; -} - - - -void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data) -{ - if (sigrenderer) { - sigrenderer->callbacks->loop = callback; - sigrenderer->callbacks->loop_data = data; - } -} - - - -void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data) -{ - if (sigrenderer) { - sigrenderer->callbacks->xm_speed_zero = callback; - sigrenderer->callbacks->xm_speed_zero_data = data; - } -} - - - -void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char byte), void *data) -{ - if (sigrenderer) { - sigrenderer->callbacks->midi = callback; - sigrenderer->callbacks->midi_data = data; - } -} - - - -static IT_CALLBACKS *create_callbacks(void) -{ - IT_CALLBACKS *callbacks = malloc(sizeof(*callbacks)); - if (!callbacks) return NULL; - callbacks->loop = NULL; - callbacks->xm_speed_zero = NULL; - callbacks->midi = NULL; - return callbacks; -} - - - -static DUMB_IT_SIGRENDERER *dumb_it_init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_channels, int startorder) -{ - IT_CALLBACKS *callbacks; - - if (!sigdata) return NULL; - - callbacks = create_callbacks(); - if (!callbacks) return NULL; - - return init_sigrenderer(sigdata, n_channels, startorder, callbacks, - dumb_create_click_remover_array(n_channels)); -} - - - -DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder) -{ - DUMB_IT_SIGDATA *itsd = duh_get_it_sigdata(duh); - DUMB_IT_SIGRENDERER *itsr = dumb_it_init_sigrenderer(itsd, n_channels, startorder); - return duh_encapsulate_it_sigrenderer(itsr, n_channels, 0); -} - - - -static sigrenderer_t *it_start_sigrenderer(DUH *duh, sigdata_t *vsigdata, int n_channels, long pos) -{ - DUMB_IT_SIGDATA *sigdata = vsigdata; - DUMB_IT_SIGRENDERER *sigrenderer; - - (void)duh; - - { - IT_CALLBACKS *callbacks = create_callbacks(); - if (!callbacks) return NULL; - - if (sigdata->checkpoint) { - IT_CHECKPOINT *checkpoint = sigdata->checkpoint; - while (checkpoint->next && checkpoint->next->time < pos) - checkpoint = checkpoint->next; - sigrenderer = dup_sigrenderer(checkpoint->sigrenderer, n_channels, callbacks); - if (!sigrenderer) return NULL; - sigrenderer->click_remover = dumb_create_click_remover_array(n_channels); - pos -= checkpoint->time; - } else { - sigrenderer = init_sigrenderer(sigdata, n_channels, 0, callbacks, - dumb_create_click_remover_array(n_channels)); - if (!sigrenderer) return NULL; - } - } - - for (;;) { - if (sigrenderer->time_left >= pos) - break; - - render(sigrenderer, 0, 1.0f, 0, sigrenderer->time_left, NULL); - - pos -= sigrenderer->time_left; - sigrenderer->time_left = 0; - - if (process_tick(sigrenderer)) { - _dumb_it_end_sigrenderer(sigrenderer); - return NULL; - } - } - - render(sigrenderer, 0, 1.0f, 0, pos, NULL); - sigrenderer->time_left -= pos; - - /** WARNING - everything initialised? */ - - return sigrenderer; -} - - - -static long it_sigrenderer_get_samples( - sigrenderer_t *vsigrenderer, - float volume, float delta, - long size, sample_t **samples -) -{ - DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer; - long pos; - int dt; - long todo; - LONG_LONG t; - - if (sigrenderer->order < 0) return 0; - - pos = 0; - dt = (int)(delta * 65536.0f + 0.5f); - - /* When samples is finally used in render_playing(), it won't be used if - * volume is 0. - */ - if (!samples) volume = 0; - - for (;;) { - todo = (long)((((LONG_LONG)sigrenderer->time_left << 16) | sigrenderer->sub_time_left) / dt); - - if (todo >= size) - break; - - render(sigrenderer, volume, delta, pos, todo, samples); - - pos += todo; - size -= todo; - - t = sigrenderer->sub_time_left - (LONG_LONG)todo * dt; - sigrenderer->sub_time_left = (long)t & 65535; - sigrenderer->time_left += (long)(t >> 16); - - if (process_tick(sigrenderer)) { - sigrenderer->order = -1; - sigrenderer->row = -1; - return pos; - } - } - - render(sigrenderer, volume, delta, pos, size, samples); - - pos += size; - - t = sigrenderer->sub_time_left - (LONG_LONG)size * dt; - sigrenderer->sub_time_left = (long)t & 65535; - sigrenderer->time_left += (long)(t >> 16); - - dumb_remove_clicks_array(sigrenderer->n_channels, sigrenderer->click_remover, samples, pos, 512.0f / delta); - - return pos; -} - - - -static void it_sigrenderer_get_current_sample(sigrenderer_t *vsigrenderer, float volume, sample_t *samples) -{ - DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer; - (void)volume; // for consideration: in any of these such functions, is 'volume' going to be required? - dumb_click_remover_get_offset_array(sigrenderer->n_channels, sigrenderer->click_remover, samples); -} - - - -void _dumb_it_end_sigrenderer(sigrenderer_t *vsigrenderer) -{ - DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer; - - int i; - - if (sigrenderer) { - for (i = 0; i < DUMB_IT_N_CHANNELS; i++) - if (sigrenderer->channel[i].playing) - free(sigrenderer->channel[i].playing); - - for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) - if (sigrenderer->playing[i]) - free(sigrenderer->playing[i]); - - dumb_destroy_click_remover_array(sigrenderer->n_channels, sigrenderer->click_remover); - - if (sigrenderer->callbacks) - free(sigrenderer->callbacks); - - free(vsigrenderer); - } -} - - - -DUH_SIGTYPE_DESC _dumb_sigtype_it = { - SIGTYPE_IT, - NULL, - &it_start_sigrenderer, - NULL, - &it_sigrenderer_get_samples, - &it_sigrenderer_get_current_sample, - &_dumb_it_end_sigrenderer, - &_dumb_it_unload_sigdata -}; - - - -DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos) -{ - return duh_encapsulate_raw_sigrenderer(it_sigrenderer, &_dumb_sigtype_it, n_channels, pos); -} - - - -DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer) -{ - return duh_get_raw_sigrenderer(sigrenderer, SIGTYPE_IT); -} - - - -/* Values of 64 or more will access NNA channels here. */ -void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state) -{ - IT_PLAYING *playing; - int t; /* temporary var for holding accurate pan and filter cutoff */ - float delta; - ASSERT(channel < DUMB_IT_TOTAL_CHANNELS); - if (!sr) { state->sample = 0; return; } - if (channel >= DUMB_IT_N_CHANNELS) { - playing = sr->playing[channel - DUMB_IT_N_CHANNELS]; - if (!playing) { state->sample = 0; return; } - } else { - playing = sr->channel[channel].playing; - if (!playing) { state->sample = 0; return; } - } - - if (playing->flags & IT_PLAYING_DEAD) { state->sample = 0; return; } - - state->channel = playing->channel - sr->channel; - state->sample = playing->sampnum; - state->volume = calculate_volume(sr, playing, 1.0f); - - t = apply_pan_envelope(playing); - state->pan = (unsigned char)((t + 128) >> IT_ENVELOPE_SHIFT); - state->subpan = (signed char)t; - - delta = playing->delta * 65536.0f; - t = playing->filter_cutoff << IT_ENVELOPE_SHIFT; - apply_pitch_modifications(sr->sigdata, playing, &delta, &t); - state->freq = (int)delta; - if (t == 127 << IT_ENVELOPE_SHIFT && playing->filter_resonance == 0) { - state->filter_resonance = playing->true_filter_resonance; - t = playing->true_filter_cutoff; - } else - state->filter_resonance = playing->filter_resonance; - state->filter_cutoff = (unsigned char)(t >> 8); - state->filter_subcutoff = (unsigned char)t; -} - - - -int dumb_it_callback_terminate(void *data) -{ - (void)data; - return 1; -} - - - -int dumb_it_callback_midi_block(void *data, int channel, unsigned char byte) -{ - (void)data; - (void)channel; - (void)byte; - return 1; -} - - - -#define IT_CHECKPOINT_INTERVAL (30 * 65536) /* Half a minute */ - - - -/* Returns the length of the module, up until it first loops. */ -long _dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata) -{ - IT_CHECKPOINT *checkpoint = malloc(sizeof(*checkpoint)); - if (!checkpoint) return 0; - checkpoint->time = 0; - checkpoint->sigrenderer = dumb_it_init_sigrenderer(sigdata, 0, 0); - if (!checkpoint->sigrenderer) { - free(checkpoint); - return 0; - } - checkpoint->sigrenderer->callbacks->loop = &dumb_it_callback_terminate; - checkpoint->sigrenderer->callbacks->xm_speed_zero = &dumb_it_callback_terminate; - sigdata->checkpoint = checkpoint; - - for (;;) { - long l; - DUMB_IT_SIGRENDERER *sigrenderer = dup_sigrenderer(checkpoint->sigrenderer, 0, checkpoint->sigrenderer->callbacks); - checkpoint->sigrenderer->callbacks = NULL; - if (!sigrenderer) { - checkpoint->next = NULL; - return checkpoint->time; - } - - l = it_sigrenderer_get_samples(sigrenderer, 0, 1.0f, IT_CHECKPOINT_INTERVAL, NULL); - if (l < IT_CHECKPOINT_INTERVAL) { - _dumb_it_end_sigrenderer(sigrenderer); - checkpoint->next = NULL; - return checkpoint->time + l; - } - - checkpoint->next = malloc(sizeof(*checkpoint->next)); - if (!checkpoint->next) { - _dumb_it_end_sigrenderer(sigrenderer); - return checkpoint->time + IT_CHECKPOINT_INTERVAL; - } - - checkpoint->next->time = checkpoint->time + IT_CHECKPOINT_INTERVAL; - checkpoint = checkpoint->next; - checkpoint->sigrenderer = sigrenderer; - } -} diff --git a/Engine/libsrc/dumb-0.9.2/it/itunload.c b/Engine/libsrc/dumb-0.9.2/it/itunload.c deleted file mode 100644 index 8f282bea2e7..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/itunload.c +++ /dev/null @@ -1,71 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * itunload.c - Code to free an Impulse Tracker / / \ \ - * module from memory. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include - -#include "dumb.h" -#include "internal/it.h" - - - -void _dumb_it_unload_sigdata(sigdata_t *vsigdata) -{ - if (vsigdata) { - DUMB_IT_SIGDATA *sigdata = vsigdata; - int n; - - if (sigdata->order) - free(sigdata->order); - - if (sigdata->instrument) - free(sigdata->instrument); - - if (sigdata->sample) { - for (n = 0; n < sigdata->n_samples; n++) { - if (sigdata->sample[n].left) - free(sigdata->sample[n].left); - if (sigdata->sample[n].right) - free(sigdata->sample[n].right); - } - free(sigdata->sample); - } - - if (sigdata->pattern) { - for (n = 0; n < sigdata->n_patterns; n++) - if (sigdata->pattern[n].entry) - free(sigdata->pattern[n].entry); - free(sigdata->pattern); - } - - if (sigdata->midi) - free(sigdata->midi); - - { - IT_CHECKPOINT *checkpoint = sigdata->checkpoint; - while (checkpoint) { - IT_CHECKPOINT *next = checkpoint->next; - _dumb_it_end_sigrenderer(checkpoint->sigrenderer); - free(checkpoint); - checkpoint = next; - } - } - - free(vsigdata); - } -} diff --git a/Engine/libsrc/dumb-0.9.2/it/loadmod.c b/Engine/libsrc/dumb-0.9.2/it/loadmod.c deleted file mode 100644 index f7bbcb50e67..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/loadmod.c +++ /dev/null @@ -1,42 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * loadmod.c - Code to read a good old-fashioned / / \ \ - * Amiga module file, opening and | < / \_ - * closing it for you. | \/ /\ / - * \_ / > / - * By entheh. | \ / / - * | ' / - * \__/ - */ - -#include "dumb.h" -#include "internal/it.h" - - - -/* dumb_load_mod(): loads a MOD file into a DUH struct, returning a pointer - * to the DUH struct. When you have finished with it, you must pass the - * pointer to unload_duh() so that the memory can be freed. - */ -DUH *dumb_load_mod(const char *filename) -{ - DUH *duh; - DUMBFILE *f = dumbfile_open(filename); - - if (!f) - return NULL; - - duh = dumb_read_mod(f); - - dumbfile_close(f); - - return duh; -} diff --git a/Engine/libsrc/dumb-0.9.2/it/loads3m.c b/Engine/libsrc/dumb-0.9.2/it/loads3m.c deleted file mode 100644 index dfe6a9268e2..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/loads3m.c +++ /dev/null @@ -1,42 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * loads3m.c - Code to read a ScreamTracker 3 / / \ \ - * file, opening and closing it for | < / \_ - * you. | \/ /\ / - * \_ / > / - * By entheh. | \ / / - * | ' / - * \__/ - */ - -#include "dumb.h" -#include "internal/it.h" - - - -/* dumb_load_s3m(): loads an S3M file into a DUH struct, returning a pointer - * to the DUH struct. When you have finished with it, you must pass the - * pointer to unload_duh() so that the memory can be freed. - */ -DUH *dumb_load_s3m(const char *filename) -{ - DUH *duh; - DUMBFILE *f = dumbfile_open(filename); - - if (!f) - return NULL; - - duh = dumb_read_s3m(f); - - dumbfile_close(f); - - return duh; -} diff --git a/Engine/libsrc/dumb-0.9.2/it/loadxm.c b/Engine/libsrc/dumb-0.9.2/it/loadxm.c deleted file mode 100644 index 9cee06d6ee5..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/loadxm.c +++ /dev/null @@ -1,42 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * loadxm.c - Code to read a Fast Tracker II / / \ \ - * file, opening and closing it for | < / \_ - * you. | \/ /\ / - * \_ / > / - * By entheh. | \ / / - * | ' / - * \__/ - */ - -#include "dumb.h" -#include "internal/it.h" - - - -/* dumb_load_xm(): loads an XM file into a DUH struct, returning a pointer - * to the DUH struct. When you have finished with it, you must pass the - * pointer to unload_duh() so that the memory can be freed. - */ -DUH *dumb_load_xm(const char *filename) -{ - DUH *duh; - DUMBFILE *f = dumbfile_open(filename); - - if (!f) - return NULL; - - duh = dumb_read_xm(f); - - dumbfile_close(f); - - return duh; -} diff --git a/Engine/libsrc/dumb-0.9.2/it/readmod.c b/Engine/libsrc/dumb-0.9.2/it/readmod.c deleted file mode 100644 index 452c8900a4d..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/readmod.c +++ /dev/null @@ -1,594 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * readmod.c - Code to read a good old-fashioned / / \ \ - * Amiga module from an open file. | < / \_ - * | \/ /\ / - * By Ben Davis. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -#include -#include -#include - -#include "dumb.h" -#include "internal/it.h" - - - -static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer) -{ - int pos; - int channel; - int row; - IT_ENTRY *entry; - - pattern->n_rows = 64; - - if (n_channels == 0) { - /* Read the first four channels, leaving gaps for the rest. */ - for (pos = 0; pos < 64*8*4; pos += 8*4) - dumbfile_getnc(buffer + pos, 4*4, f); - /* Read the other channels into the gaps we left. */ - for (pos = 4*4; pos < 64*8*4; pos += 8*4) - dumbfile_getnc(buffer + pos, 4*4, f); - - n_channels = 8; - } else - dumbfile_getnc(buffer, 64 * n_channels * 4, f); - - if (dumbfile_error(f)) - return -1; - - /* compute number of entries */ - pattern->n_entries = 64; /* Account for the row end markers */ - pos = 0; - for (row = 0; row < 64; row++) { - for (channel = 0; channel < n_channels; channel++) { - if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3]) - pattern->n_entries++; - pos += 4; - } - } - - pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry)); - if (!pattern->entry) - return -1; - - entry = pattern->entry; - pos = 0; - for (row = 0; row < 64; row++) { - for (channel = 0; channel < n_channels; channel++) { - if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3]) { - unsigned char sample = (buffer[pos+0] & 0xF0) | (buffer[pos+2] >> 4); - int period = ((int)(buffer[pos+0] & 0x0F) << 8) | buffer[pos+1]; - - entry->channel = channel; - entry->mask = 0; - - if (period) { - int note; - entry->mask |= IT_ENTRY_NOTE; - - /* frequency = (AMIGA_DIVISOR / 8) / (period * 2) - * C-1: period = 214 -> frequency = 16726 - * so, set C5_speed to 16726 - * and period = 214 should translate to C5 aka 60 - * halve the period, go up an octive - * - * period = 214 / pow(DUMB_SEMITONE_BASE, note - 60) - * pow(DUMB_SEMITONE_BASE, note - 60) = 214 / period - * note - 60 = log(214/period) / log(DUMB_SEMITONE_BASE) - */ - note = (int)floor(log(214.0/period) / log(DUMB_SEMITONE_BASE) + 60.5); - entry->note = MID(0, note, 119); - // or should we preserve the period? - //entry->note = buffer[pos+0] & 0x0F; /* High nibble */ - //entry->volpan = buffer[pos+1]; /* Low byte */ - // and what about finetune? - } - - if (sample) { - entry->mask |= IT_ENTRY_INSTRUMENT; - entry->instrument = sample; - } - - _dumb_it_xm_convert_effect(buffer[pos+2] & 0x0F, buffer[pos+3], entry); - - entry++; - } - pos += 4; - } - IT_SET_END_ROW(entry); - entry++; - } - - return 0; -} - - - -/* This function does not skip the name (22 bytes); it is assumed the caller - * has already done that. - */ -static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) -{ - int finetune; - -/** - 21 22 Chars Sample 1 name. If the name is not a full - 22 chars in length, it will be null - terminated. - -If -the sample name begins with a '#' character (ASCII $23 (35)) then this is -assumed not to be an instrument name, and is probably a message. -*/ - sample->length = dumbfile_mgetw(f) << 1; - finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */ -/** Each finetune step changes the note 1/8th of a semitone. */ - sample->global_volume = 64; - sample->default_volume = dumbfile_getc(f); // Should we be setting global_volume to this instead? - sample->loop_start = dumbfile_mgetw(f) << 1; - sample->loop_end = sample->loop_start + (dumbfile_mgetw(f) << 1); -/** -Once this sample has been played completely from beginning -to end, if the repeat length (next field) is greater than two bytes it -will loop back to this position in the sample and continue playing. Once -it has played for the repeat length, it continues to loop back to the -repeat start offset. This means the sample continues playing until it is -told to stop. -*/ - - if (sample->length <= 0) { - sample->flags = 0; - return 0; - } - - sample->flags = IT_SAMPLE_EXISTS; - - sample->default_pan = 0; - sample->C5_speed = (long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32)); - // the above line might be wrong - - if (sample->loop_end > sample->length) - sample->loop_end = sample->length; - - if (sample->loop_end - sample->loop_start > 2) - sample->flags |= IT_SAMPLE_LOOP; - - sample->vibrato_speed = 0; - sample->vibrato_depth = 0; - sample->vibrato_rate = 0; - sample->vibrato_waveform = 0; // do we have to set _all_ these? - - return dumbfile_error(f); -} - - - -static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f) -{ - long i; - long truncated_size; - - /* let's get rid of the sample data coming after the end of the loop */ - if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) { - truncated_size = sample->length - sample->loop_end; - sample->length = sample->loop_end; - } else { - truncated_size = 0; - } - - sample->left = malloc(sample->length * sizeof(*sample->left)); - - if (!sample->left) - return -1; - - /* Sample data are stored in "8-bit two's compliment format" (sic). */ - for (i = 0; i < sample->length; i++) - sample->left[i] = (int)(signed char)dumbfile_getc(f) << 16; - - /* skip truncated data */ - dumbfile_skip(f, truncated_size); - // Should we be truncating it? - - if (dumbfile_error(f)) - return -1; - - return 0; -} - - - -typedef struct BUFFERED_MOD BUFFERED_MOD; - -struct BUFFERED_MOD -{ - unsigned char *buffered; - long ptr, len; - DUMBFILE *remaining; -}; - - - -static int buffer_mod_skip(void *f, long n) -{ - BUFFERED_MOD *bm = f; - if (bm->buffered) { - bm->ptr += n; - if (bm->ptr >= bm->len) { - free(bm->buffered); - bm->buffered = NULL; - return dumbfile_skip(bm->remaining, bm->ptr - bm->len); - } - return 0; - } - return dumbfile_skip(bm->remaining, n); -} - - - -static int buffer_mod_getc(void *f) -{ - BUFFERED_MOD *bm = f; - if (bm->buffered) { - int rv = bm->buffered[bm->ptr++]; - if (bm->ptr >= bm->len) { - free(bm->buffered); - bm->buffered = NULL; - } - return rv; - } - return dumbfile_getc(bm->remaining); -} - - - -static long buffer_mod_getnc(char *ptr, long n, void *f) -{ - BUFFERED_MOD *bm = f; - if (bm->buffered) { - int left = bm->len - bm->ptr; - if (n >= left) { - int rv; - memcpy(ptr, bm->buffered + bm->ptr, left); - free(bm->buffered); - bm->buffered = NULL; - rv = dumbfile_getnc(ptr + left, n - left, bm->remaining); - return left + MAX(rv, 0); - } - memcpy(ptr, bm->buffered + bm->ptr, n); - bm->ptr += n; - return n; - } - return dumbfile_getnc(ptr, n, bm->remaining); -} - - - -static void buffer_mod_close(void *f) -{ - BUFFERED_MOD *bm = f; - if (bm->buffered) free(bm->buffered); - /* Do NOT close bm->remaining */ - free(f); -} - - - -DUMBFILE_SYSTEM buffer_mod_dfs = { - NULL, - &buffer_mod_skip, - &buffer_mod_getc, - &buffer_mod_getnc, - &buffer_mod_close -}; - - - -#define MOD_FFT_OFFSET (20 + 31*(22+2+1+1+2+2) + 1 + 1 + 128) - -static DUMBFILE *dumbfile_buffer_mod(DUMBFILE *f, unsigned long *fft) -{ - BUFFERED_MOD *bm = malloc(sizeof(*bm)); - if (!bm) return NULL; - - bm->buffered = malloc(MOD_FFT_OFFSET + 4); - if (!bm->buffered) { - free(bm); - return NULL; - } - - bm->len = dumbfile_getnc(bm->buffered, MOD_FFT_OFFSET + 4, f); - - if (bm->len > 0) { - if (bm->len >= MOD_FFT_OFFSET + 4) - *fft = (unsigned long)bm->buffered[MOD_FFT_OFFSET ] << 24 - | (unsigned long)bm->buffered[MOD_FFT_OFFSET+1] << 16 - | (unsigned long)bm->buffered[MOD_FFT_OFFSET+2] << 8 - | (unsigned long)bm->buffered[MOD_FFT_OFFSET+3]; - else - *fft = 0; - bm->ptr = 0; - } else { - free(bm->buffered); - bm->buffered = NULL; - } - - bm->remaining = f; - - return dumbfile_open_ex(bm, &buffer_mod_dfs); -} - - - -static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f) -{ - DUMB_IT_SIGDATA *sigdata; - int n_channels; - int i; - unsigned long fft; - - f = dumbfile_buffer_mod(f, &fft); - if (!f) - return NULL; - - /** - 1 20 Chars Title of the song. If the title is not a - full 20 chars in length, it will be null- - terminated. - */ - if (dumbfile_skip(f, 20)) { - dumbfile_close(f); - return NULL; - } - - sigdata = malloc(sizeof(*sigdata)); - if (!sigdata) { - dumbfile_close(f); - return NULL; - } - - sigdata->n_samples = 31; - - switch (fft) { - case DUMB_ID('M','.','K','.'): - case DUMB_ID('M','!','K','!'): - case DUMB_ID('M','&','K','!'): - case DUMB_ID('N','.','T','.'): - case DUMB_ID('F','L','T','4'): - n_channels = 4; - break; - case DUMB_ID('F','L','T','8'): - n_channels = 0; - /* 0 indicates a special case; two four-channel patterns must be - * combined into one eight-channel pattern. Pattern indexes must - * be halved. Why oh why do they obfuscate so? - */ - for (i = 0; i < 128; i++) - sigdata->order[i] >>= 1; - break; - case DUMB_ID('C','D','8','1'): - case DUMB_ID('O','C','T','A'): - case DUMB_ID('O','K','T','A'): - n_channels = 8; - break; - case DUMB_ID('1','6','C','N'): - n_channels = 16; - break; - case DUMB_ID('3','2','C','N'): - n_channels = 32; - break; - default: - /* If we get an illegal tag, assume 4 channels 15 samples. */ - if ((fft & 0x0000FFFFL) == DUMB_ID(0,0,'C','H')) { - if (fft >= '1' << 24 && fft < '4' << 24) { - n_channels = ((fft & 0x00FF0000L) >> 16) - '0'; - if ((unsigned int)n_channels >= 10) { - /* Rightmost character wasn't a digit. */ - n_channels = 4; - sigdata->n_samples = 15; - } else { - n_channels += (((fft & 0xFF000000L) >> 24) - '0') * 10; - /* MODs should really only go up to 32 channels, but we're lenient. */ - if ((unsigned int)(n_channels - 1) >= DUMB_IT_N_CHANNELS - 1) { - /* No channels or too many? Can't be right... */ - n_channels = 4; - sigdata->n_samples = 15; - } - } - } else { - n_channels = 4; - sigdata->n_samples = 15; - } - } else if ((fft & 0x00FFFFFFL) == DUMB_ID(0,'C','H','N')) { - n_channels = (fft >> 24) - '0'; - if ((unsigned int)(n_channels - 1) >= 9) { - /* Character was '0' or it wasn't a digit */ - n_channels = 4; - sigdata->n_samples = 15; - } - } else if ((fft & 0xFFFFFF00L) == DUMB_ID('T','D','Z',0)) { - n_channels = (fft & 0x000000FFL) - '0'; - if ((unsigned int)(n_channels - 1) >= 9) { - /* We've been very lenient, given that it should have - * been 1, 2 or 3, but this MOD has been very naughty and - * must be punished. - */ - n_channels = 4; - sigdata->n_samples = 15; - } - } else { - n_channels = 4; - sigdata->n_samples = 15; - } - } - - sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); - if (!sigdata->sample) { - free(sigdata); - dumbfile_close(f); - return NULL; - } - - sigdata->order = NULL; - sigdata->instrument = NULL; - sigdata->pattern = NULL; - sigdata->midi = NULL; - sigdata->checkpoint = NULL; - - for (i = 0; i < sigdata->n_samples; i++) - sigdata->sample[i].right = sigdata->sample[i].left = NULL; - - for (i = 0; i < sigdata->n_samples; i++) { - if (dumbfile_skip(f, 22) || - it_mod_read_sample_header(&sigdata->sample[i], f)) - { - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - } - - sigdata->n_orders = dumbfile_getc(f); - sigdata->restart_position = dumbfile_getc(f); - // what if this is >= 127? what about with Fast Tracker II? - - if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right? - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - - //if (sigdata->restart_position >= sigdata->n_orders) - //sigdata->restart_position = 0; - - sigdata->order = malloc(128); /* We may need to scan the extra ones! */ - if (!sigdata->order) { - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - if (dumbfile_getnc(sigdata->order, 128, f) < 128) { - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - - /* "The old NST format contains only 15 samples (instead of 31). Further - * it doesn't contain a file format tag (id). So Pattern data offset is - * at 20+15*30+1+1+128." - * - Then I shall assume the File Format Tag never exists if there are - * only 15 samples. I hope this isn't a faulty assumption... - */ - if (sigdata->n_samples == 31) - dumbfile_skip(f, 4); - - /* Work out how many patterns there are. */ - sigdata->n_patterns = -1; - for (i = 0; i < 128; i++) - if (sigdata->n_patterns < sigdata->order[i]) - sigdata->n_patterns = sigdata->order[i]; - sigdata->n_patterns++; - - /* May as well try to save a tiny bit of memory. */ - if (sigdata->n_orders < 128) { - unsigned char *order = realloc(sigdata->order, sigdata->n_orders); - if (order) sigdata->order = order; - } - - sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); - if (!sigdata->pattern) { - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - for (i = 0; i < sigdata->n_patterns; i++) - sigdata->pattern[i].entry = NULL; - - /* Read in the patterns */ - { - unsigned char *buffer = malloc(256 * n_channels); /* 64 rows * 4 bytes */ - if (!buffer) { - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - for (i = 0; i < sigdata->n_patterns; i++) { - if (it_mod_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) { - free(buffer); - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - } - free(buffer); - } - - /* And finally, the sample data */ - for (i = 0; i < sigdata->n_samples; i++) { - if (it_mod_read_sample_data(&sigdata->sample[i], f)) { - _dumb_it_unload_sigdata(sigdata); - dumbfile_close(f); - return NULL; - } - } - - dumbfile_close(f); /* Destroy the BUFFERED_MOD DUMBFILE we were using. */ - /* The DUMBFILE originally passed to our function is intact. */ - - /* Now let's initialise the remaining variables, and we're done! */ - sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; - - sigdata->global_volume = 128; - sigdata->mixing_volume = 48; - /* We want 50 ticks per second; 50/6 row advances per second; - * 50*10=500 row advances per minute; 500/4=125 beats per minute. - */ - sigdata->speed = 6; - sigdata->tempo = 125; - sigdata->pan_separation = 128; - - memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); - - for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) { - sigdata->channel_pan[i+0] = 16; - sigdata->channel_pan[i+1] = 48; - sigdata->channel_pan[i+2] = 48; - sigdata->channel_pan[i+3] = 16; - } - - _dumb_it_fix_invalid_orders(sigdata); - - return sigdata; -} - - - -DUH *dumb_read_mod(DUMBFILE *f) -{ - sigdata_t *sigdata; - long length; - - DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; - - sigdata = it_mod_load_sigdata(f); - - if (!sigdata) - return NULL; - - length = _dumb_it_build_checkpoints(sigdata); - - return make_duh(length, 1, &descptr, &sigdata); -} diff --git a/Engine/libsrc/dumb-0.9.2/it/reads3m.c b/Engine/libsrc/dumb-0.9.2/it/reads3m.c deleted file mode 100644 index 6a8b84dd550..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/reads3m.c +++ /dev/null @@ -1,668 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * reads3m.c - Code to read a ScreamTracker 3 / / \ \ - * module from an open file. | < / \_ - * | \/ /\ / - * By entheh. \_ / > / - * | \ / / - * | ' / - * \__/ - */ - -// IT_STEREO... :o -#include -#include - -#include "dumb.h" -#include "internal/it.h" - - - -/** WARNING: this is duplicated in itread.c */ -static int it_seek(DUMBFILE *f, long offset) -{ - long pos = dumbfile_pos(f); - - if (pos > offset) - return -1; - - if (pos < offset) - if (dumbfile_skip(f, offset - pos)) - return -1; - - return 0; -} - - - -static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *f) -{ - unsigned char type; - int flags; - - type = dumbfile_getc(f); - - if (type > 1) { - /** WARNING: no adlib support */ - } - - /* Skip DOS Filename */ - dumbfile_skip(f, 13); - - *offset = dumbfile_igetw(f) << 4; - - sample->length = dumbfile_igetl(f); - sample->loop_start = dumbfile_igetl(f); - sample->loop_end = dumbfile_igetl(f); - - sample->default_volume = dumbfile_getc(f); - - dumbfile_skip(f, 1); - - if (dumbfile_getc(f) != 0) - /* Sample is packed apparently (or error reading from file). We don't - * know how to read packed samples. - */ - return -1; - - flags = dumbfile_getc(f); - - sample->C5_speed = dumbfile_igetl(f) << 1; - - /* Skip four unused bytes, three internal variables and sample name. */ - dumbfile_skip(f, 4+2+2+4+28); - - if (type == 0) { - /* Looks like no-existy. Anyway, there's for sure no 'SCRS'... */ - sample->flags &= ~IT_SAMPLE_EXISTS; - return dumbfile_error(f); - } - - if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','S')) - return -1; - - sample->global_volume = 64; - - sample->flags = IT_SAMPLE_EXISTS; - if (flags & 1) sample->flags |= IT_SAMPLE_LOOP; - if (flags & 2) sample->flags |= IT_SAMPLE_STEREO; - if (flags & 4) sample->flags |= IT_SAMPLE_16BIT; - - sample->default_pan = 0; // 0 = don't use, or 160 = centre? - - if (sample->length <= 0) - sample->flags &= ~IT_SAMPLE_EXISTS; - else if (sample->flags & IT_SAMPLE_LOOP) { - if ((unsigned int)sample->loop_end > (unsigned int)sample->length) - sample->flags &= ~IT_SAMPLE_LOOP; - else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end) - sample->flags &= ~IT_SAMPLE_LOOP; - else - /* ScreamTracker seems not to save what comes after the loop end - * point, but rather to assume it is a duplicate of what comes at - * the loop start point. I am not completely sure of this though. - * It is easy to evade; simply truncate the sample. - */ - sample->length = sample->loop_end; - } - - - //Do we need to set all these? - sample->vibrato_speed = 0; - sample->vibrato_depth = 0; - sample->vibrato_rate = 0; - sample->vibrato_waveform = IT_VIBRATO_SINE; - - return dumbfile_error(f); -} - - - -static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi, DUMBFILE *f) -{ - long n; - - sample->left = malloc(sample->length * sizeof(*sample->left)); - if (!sample->left) - return -1; - - if (sample->flags & IT_SAMPLE_STEREO) { - sample->right = malloc(sample->length * sizeof(*sample->right)); - if (!sample->right) - return -1; - } - - if (sample->flags & IT_SAMPLE_STEREO) { - if (sample->flags & IT_SAMPLE_16BIT) { - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8; - for (n = 0; n < sample->length; n++) - sample->right[n] = (int)(signed short)dumbfile_igetw(f) << 8; - } else { - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16; - for (n = 0; n < sample->length; n++) - sample->right[n] = (int)(signed char)dumbfile_getc(f) << 16; - } - } else if (sample->flags & IT_SAMPLE_16BIT) - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8; - else - for (n = 0; n < sample->length; n++) - sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16; - - if (dumbfile_error(f)) - return -1; - - if (ffi != 1) { - /* Convert to signed. */ - for (n = 0; n < sample->length; n++) - sample->left[n] ^= 0xFF800000; - - if (sample->right) - for (n = 0; n < sample->length; n++) - sample->right[n] ^= 0xFF800000; - } - - return 0; -} - - - -static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer) -{ - int buflen = 0; - int bufpos = 0; - - IT_ENTRY *entry; - - unsigned char channel; - - /* Haha, this is hilarious! - * - * Well, after some experimentation, it seems that different S3M writers - * define the format in different ways. The S3M docs say that the first - * two bytes hold the "length of [the] packed pattern", and the packed - * pattern data follow. Judging by the contents of ARMANI.S3M, packaged - * with ScreamTracker itself, the measure of length _includes_ the two - * bytes used to store the length; in other words, we should read - * (length - 2) more bytes. However, aryx.s3m, packaged with ModPlug - * Tracker, excludes these two bytes, so (length) more bytes must be - * read. - * - * Call me crazy, but I just find it insanely funny that the format was - * misunderstood in this way :D - * - * Now we can't just risk reading two extra bytes, because then we - * overshoot, and DUMBFILEs don't support backward seeking (for a good - * reason). Luckily, there is a way. We can read the data little by - * little, and stop when we have 64 rows in memory. Provided we protect - * against buffer overflow, this method should work with all sensibly - * written S3M files. If you find one for which it does not work, please - * let me know at entheh@users.sf.net so I can look at it. - */ - - /* Discard the length. */ - dumbfile_skip(f, 2); - - if (dumbfile_error(f)) - return -1; - - pattern->n_rows = 0; - pattern->n_entries = 0; - - /* Read in the pattern data, little by little, and work out how many - * entries we need room for. Sorry, but this is just so funny... - */ - for (;;) { - unsigned char b = buffer[buflen++] = dumbfile_getc(f); - -#if 1 - static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5}; - channel = b & 31; - b >>= 5; - pattern->n_entries++; - if (b) { - if (buflen + used[b] >= 65536) return -1; - dumbfile_getnc(buffer + buflen, used[b], f); - buflen += used[b]; - } else { - /* End of row */ - if (++pattern->n_rows == 64) break; - if (buflen >= 65536) return -1; - } -#else - if (b == 0) { - /* End of row */ - pattern->n_entries++; - if (++pattern->n_rows == 64) break; - if (buflen >= 65536) return -1; - } else { - static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5}; - channel = b & 31; - b >>= 5; - if (b) { - pattern->n_entries++; - if (buflen + used[b] >= 65536) return -1; - dumbfile_getnc(buffer + buflen, used[b], f); - buflen += used[b]; - } - } -#endif - - /* We have ensured that buflen < 65536 at this point, so it is safe - * to iterate and read at least one more byte without checking. - * However, now would be a good time to check for errors reading from - * the file. - */ - - if (dumbfile_error(f)) - return -1; - } - - pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry)); - - if (!pattern->entry) - return -1; - - entry = pattern->entry; - - while (bufpos < buflen) { - unsigned char b = buffer[bufpos++]; - -#if 1 - if (!(b & ~31)) -#else - if (b == 0) -#endif - { - /* End of row */ - IT_SET_END_ROW(entry); - entry++; - continue; - } - - channel = b & 31; - - if (b & 224) { - entry->mask = 0; - entry->channel = channel; - - if (b & 32) { - unsigned char n = buffer[bufpos++]; - if (n != 255) { - if (n == 254) - entry->note = IT_NOTE_CUT; - else - entry->note = (n >> 4) * 12 + (n & 15); - entry->mask |= IT_ENTRY_NOTE; - } - - entry->instrument = buffer[bufpos++]; - if (entry->instrument) - entry->mask |= IT_ENTRY_INSTRUMENT; - } - - if (b & 64) { - entry->volpan = buffer[bufpos++]; - if (entry->volpan != 255) - entry->mask |= IT_ENTRY_VOLPAN; - } - - if (b & 128) { - entry->effect = buffer[bufpos++]; - entry->effectvalue = buffer[bufpos++]; - if (entry->effect != 255) { - entry->mask |= IT_ENTRY_EFFECT; - if (entry->effect == IT_BREAK_TO_ROW) - entry->effectvalue -= (entry->effectvalue >> 4) * 6; - } - /** WARNING: ARGH! CONVERT TEH EFFECTS!@~ */ - } - - entry++; - } - } - - ASSERT(entry == pattern->entry + pattern->n_entries); - - return 0; -} - - - -/** WARNING: this is duplicated in itread.c - also bad practice to use the same struct name unless they are unified in a header */ -/* Currently we assume the sample data are stored after the sample headers in - * module files. This assumption may be unjustified; let me know if you have - * trouble. - */ - -#define IT_COMPONENT_INSTRUMENT 1 -#define IT_COMPONENT_PATTERN 2 -#define IT_COMPONENT_SAMPLE 3 - -typedef struct IT_COMPONENT -{ - unsigned char type; - unsigned char n; - long offset; - short sampfirst; /* component[sampfirst] = first sample data after this */ - short sampnext; /* sampnext is used to create linked lists of sample data */ -} -IT_COMPONENT; - - - -static int it_component_compare(const void *e1, const void *e2) -{ - return ((const IT_COMPONENT *)e1)->offset - - ((const IT_COMPONENT *)e2)->offset; -} - - - -static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f) -{ - DUMB_IT_SIGDATA *sigdata; - - int flags, cwtv, ffi; - int default_pan_present; - - IT_COMPONENT *component; - int n_components = 0; - - int n; - - unsigned char *buffer; - - /* Skip song name. */ - if (dumbfile_skip(f, 28)) return NULL; - - if (dumbfile_getc(f) != 0x1A) return NULL; - if (dumbfile_getc(f) != 16) return NULL; - - if (dumbfile_skip(f, 2)) return NULL; - - sigdata = malloc(sizeof(*sigdata)); - - if (!sigdata) - return NULL; - - sigdata->order = NULL; - sigdata->instrument = NULL; - sigdata->sample = NULL; - sigdata->pattern = NULL; - sigdata->midi = NULL; - sigdata->checkpoint = NULL; - - sigdata->n_orders = dumbfile_igetw(f); - sigdata->n_instruments = 0; - sigdata->n_samples = dumbfile_igetw(f); - sigdata->n_patterns = dumbfile_igetw(f); - - if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_samples > 256 || sigdata->n_patterns > 256) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - sigdata->order = malloc(sigdata->n_orders); - if (!sigdata->order) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (sigdata->n_samples) { - sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); - if (!sigdata->sample) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (n = 0; n < sigdata->n_samples; n++) - sigdata->sample[n].right = sigdata->sample[n].left = NULL; - } - - if (sigdata->n_patterns) { - sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); - if (!sigdata->pattern) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (n = 0; n < sigdata->n_patterns; n++) - sigdata->pattern[n].entry = NULL; - } - - flags = dumbfile_igetw(f); - - cwtv = dumbfile_igetw(f); - - if (cwtv == 0x1300) { - /** WARNING: volume slides on every frame */ - } - - ffi = dumbfile_igetw(f); - - /** WARNING: which ones? */ - sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; - - if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','M')) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - sigdata->global_volume = dumbfile_getc(f) << 1; - sigdata->speed = dumbfile_getc(f); - if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo? - sigdata->tempo = dumbfile_getc(f); - /*master_volume = */dumbfile_getc(f); // 7 bits; +128 for stereo - //what do we do with master_volume? it's not the same as mixing volume... - sigdata->mixing_volume = 48; - - /* Skip GUS Ultra Click Removal byte. */ - dumbfile_getc(f); - - default_pan_present = dumbfile_getc(f); - - dumbfile_skip(f, 8); - - /* Skip Special Custom Data Pointer. */ - /** WARNING: investigate this? */ - dumbfile_igetw(f); - - /* Channel settings for 32 channels, 255=unused, +128=disabled */ - { - int i; - for (i = 0; i < 32; i++) { - int c = dumbfile_getc(f); - if (!(c & (128 | 16))) { /* +128=disabled, +16=Adlib */ - sigdata->channel_volume[i] = 64; - sigdata->channel_pan[i] = c & 8 ? 12 : 3; - /** WARNING: ah, but it should be 7 for mono... */ - } else { - /** WARNING: this could be improved if we support channel muting... */ - sigdata->channel_volume[i] = 0; - sigdata->channel_pan[i] = 7; - } - } - } - - /* Orders, byte each, length = sigdata->n_orders (should be even) */ - dumbfile_getnc(sigdata->order, sigdata->n_orders, f); - sigdata->restart_position = 0; - - component = malloc(768*sizeof(*component)); - if (!component) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - for (n = 0; n < sigdata->n_samples; n++) { - component[n_components].type = IT_COMPONENT_SAMPLE; - component[n_components].n = n; - component[n_components].offset = dumbfile_igetw(f) << 4; - component[n_components].sampfirst = -1; - n_components++; - } - - for (n = 0; n < sigdata->n_patterns; n++) { - long offset = dumbfile_igetw(f) << 4; - if (offset) { - component[n_components].type = IT_COMPONENT_PATTERN; - component[n_components].n = n; - component[n_components].offset = offset; - component[n_components].sampfirst = -1; - n_components++; - } else { - /** WARNING: Empty 64-row pattern ... ? (this does happen!) */ - sigdata->pattern[n].n_rows = 64; - sigdata->pattern[n].n_entries = 0; - } - } - - qsort(component, n_components, sizeof(IT_COMPONENT), &it_component_compare); - - /* I found a really dumb S3M file that claimed to contain default pan - * data but didn't contain any. Programs would load it by reading part of - * the first instrument header, assuming the data to be default pan - * positions, and then rereading the instrument module. We cannot do this - * without obfuscating the file input model, so we insert an extra check - * here that we won't overrun the start of the first component. - */ - if (default_pan_present == 252 && component[0].offset >= dumbfile_pos(f) + 32) { - /* Channel default pan positions */ - int i; - for (i = 0; i < 32; i++) { - int c = dumbfile_getc(f); - if (c & 32) - sigdata->channel_pan[i] = c & 15; - } - } - - { - int i; - for (i = 0; i < 32; i++) { - sigdata->channel_pan[i] -= (sigdata->channel_pan[i] & 8) >> 3; - sigdata->channel_pan[i] = ((int)sigdata->channel_pan[i] << 5) / 7; - } - } - - /** WARNING: is this right? */ - sigdata->pan_separation = 64; - - if (dumbfile_error(f)) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - buffer = malloc(65536); - if (!buffer) { - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - for (n = 0; n < n_components; n++) { - long offset; - int m; - - if (it_seek(f, component[n].offset)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - switch (component[n].type) { - - case IT_COMPONENT_PATTERN: - if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - break; - - case IT_COMPONENT_SAMPLE: - if (it_s3m_read_sample_header(&sigdata->sample[component[n].n], &offset, f)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (sigdata->sample[component[n].n].flags & IT_SAMPLE_EXISTS) { - short *sample; - - for (m = n + 1; m < n_components; m++) - if (component[m].offset > offset) - break; - m--; - - sample = &component[m].sampfirst; - - while (*sample >= 0 && component[*sample].offset <= offset) - sample = &component[*sample].sampnext; - - component[n].sampnext = *sample; - *sample = n; - - component[n].offset = offset; - } - } - - m = component[n].sampfirst; - - while (m >= 0) { - if (it_seek(f, component[m].offset)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (it_s3m_read_sample_data(&sigdata->sample[component[m].n], ffi, f)) { - free(buffer); - free(component); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - m = component[m].sampnext; - } - } - - free(buffer); - free(component); - - _dumb_it_fix_invalid_orders(sigdata); - - return sigdata; -} - - - -DUH *dumb_read_s3m(DUMBFILE *f) -{ - sigdata_t *sigdata; - long length; - - DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; - - sigdata = it_s3m_load_sigdata(f); - - if (!sigdata) - return NULL; - - length = _dumb_it_build_checkpoints(sigdata); - - return make_duh(length, 1, &descptr, &sigdata); -} diff --git a/Engine/libsrc/dumb-0.9.2/it/readxm.c b/Engine/libsrc/dumb-0.9.2/it/readxm.c deleted file mode 100644 index 2aeda1fa67f..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/readxm.c +++ /dev/null @@ -1,998 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * readxm.c - Code to read a Fast Tracker II / / \ \ - * module from an open file. | < / \_ - * | \/ /\ / - * By Julien Cugniere. Some bits of code taken \_ / > / - * from reads3m.c. | \ / / - * | ' / - * \__/ - */ - -#include -#include -#include - -#include "dumb.h" -#include "internal/it.h" - - - -/** TODO: - - * XM_TREMOLO doesn't sound quite right... - * XM_E_SET_FINETUNE todo. - * XM_SET_ENVELOPE_POSITION todo. - - * VIBRATO conversion needs to be checked (sample/effect/volume). Plus check - that effect memory is correct when using XM_VOLSLIDE_VIBRATO. - - sample vibrato (instrument vibrato) is now handled correctly. - entheh - - * XM_E_SET_VIBRATO/TREMOLO_CONTROL: effectvalue&4 -> don't retrig wave when - a new instrument is played. In retrigger_note()?. Is it worth implementing? - - * Lossy fadeout approximation. 0..31 converted to 0 --> won't fade at all. - - * Replace DUMB's sawtooth by ramp_down/ramp_up. Update XM loader. - - * A lot of things need to be reset when the end of the song is reached. - - * It seems that IT and XM don't behave the same way when dealing with - mixed loops. When IT encounters multiple SBx (x>0) commands on the same - row, it decrements the loop count for all, but only execute the loop of - the last one (highest channel). FT2 only decrements the loop count of the - last one. Not that I know of any modules using so convoluted combinations! - - * Maybe we could remove patterns that don't appear in the order table ? Or - provide a function to "optimize" a DUMB_IT_SIGDATA ? - -*/ - - - -#define XM_LINEAR_FREQUENCY 1 /* otherwise, use amiga slides */ - -#define XM_ENTRY_PACKED 128 -#define XM_ENTRY_NOTE 1 -#define XM_ENTRY_INSTRUMENT 2 -#define XM_ENTRY_VOLUME 4 -#define XM_ENTRY_EFFECT 8 -#define XM_ENTRY_EFFECTVALUE 16 - -#define XM_NOTE_OFF 97 - -#define XM_ENVELOPE_ON 1 -#define XM_ENVELOPE_SUSTAIN 2 -#define XM_ENVELOPE_LOOP 4 - -#define XM_SAMPLE_NO_LOOP 0 -#define XM_SAMPLE_FORWARD_LOOP 1 -#define XM_SAMPLE_PINGPONG_LOOP 2 -#define XM_SAMPLE_16BIT 16 -#define XM_SAMPLE_STEREO 32 - -#define XM_VIBRATO_SINE 0 -#define XM_VIBRATO_SQUARE 1 -#define XM_VIBRATO_RAMP_DOWN 2 -#define XM_VIBRATO_RAMP_UP 3 - - - -/* Probably useless :) */ -static const char xm_convert_vibrato[] = { - IT_VIBRATO_SINE, - IT_VIBRATO_SQUARE, - IT_VIBRATO_SAWTOOTH, - IT_VIBRATO_SAWTOOTH -}; - - - -#define XM_MAX_SAMPLES_PER_INSTRUMENT 16 - - - -/* Extra data that doesn't fit inside IT_INSTRUMENT */ -typedef struct XM_INSTRUMENT_EXTRA -{ - int n_samples; - int vibrato_type; - int vibrato_sweep; /* 0-0xFF */ - int vibrato_depth; /* 0-0x0F */ - int vibrato_speed; /* 0-0x3F */ -} -XM_INSTRUMENT_EXTRA; - - - -/* Frees the original block if it can't resize it or if size is 0, and acts - * as malloc if ptr is NULL. - */ -static void *safe_realloc(void *ptr, size_t size) -{ - if (ptr == NULL) - return malloc(size); - - if (size == 0) { - free(ptr); - return NULL; - } else { - void *new_block = realloc(ptr, size); - if (!new_block) - free(ptr); - return new_block; - } -} - - - -/* The interpretation of the XM volume column is left to the player. Here, we - * just filter bad values. - */ -// This function is so tiny now, should we inline it? -static void it_xm_convert_volume(int volume, IT_ENTRY *entry) -{ - entry->mask |= IT_ENTRY_VOLPAN; - entry->volpan = volume; - - switch (volume >> 4) { - case 0xA: /* set vibrato speed */ - case 0xB: /* vibrato */ - case 0xF: /* tone porta */ - case 0x6: /* vol slide up */ - case 0x7: /* vol slide down */ - case 0x8: /* fine vol slide up */ - case 0x9: /* fine vol slide down */ - case 0xC: /* set panning */ - case 0xD: /* pan slide left */ - case 0xE: /* pan slide right */ - case 0x1: /* set volume */ - case 0x2: /* set volume */ - case 0x3: /* set volume */ - case 0x4: /* set volume */ - break; - - case 0x5: - if (volume == 0x50) - break; /* set volume */ - /* else fall through */ - - default: - entry->mask &= ~IT_ENTRY_VOLPAN; - break; - } -} - - - -static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer) -{ - int size; - int pos; - int channel; - int row; - int effect, effectvalue; - IT_ENTRY *entry; - - /* pattern header size */ - if (dumbfile_igetl(f) != 0x09) { - TRACE("XM error: unexpected pattern header size\n"); - return -1; - } - - /* pattern data packing type */ - if (dumbfile_getc(f) != 0) { - TRACE("XM error: unexpected pattern packing type\n"); - return -1; - } - - pattern->n_rows = dumbfile_igetw(f); /* 1..256 */ - size = dumbfile_igetw(f); - pattern->n_entries = 0; - - if (dumbfile_error(f)) - return -1; - - if (size == 0) - return 0; - - if (size > 1280 * n_channels) { - TRACE("XM error: pattern data size > %d bytes\n", 1280 * n_channels); - return -1; - } - - if (dumbfile_getnc(buffer, size, f) < size) - return -1; - - /* compute number of entries */ - pattern->n_entries = 0; - pos = channel = row = 0; - while (pos < size) { - if (!(buffer[pos] & XM_ENTRY_PACKED) || (buffer[pos] & 31)) - pattern->n_entries++; - - channel++; - if (channel >= n_channels) { - channel = 0; - row++; - pattern->n_entries++; - } - - if (buffer[pos] & XM_ENTRY_PACKED) { - static const char offset[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 }; - pos += 1 + offset[buffer[pos] & 31]; - } else { - pos += 5; - } - } - - if (row != pattern->n_rows) { - TRACE("XM error: wrong number of rows in pattern data\n"); - return -1; - } - - pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry)); - if (!pattern->entry) - return -1; - - /* read the entries */ - entry = pattern->entry; - pos = channel = row = 0; - while (pos < size) { - unsigned char mask; - - if (buffer[pos] & XM_ENTRY_PACKED) - mask = buffer[pos++] & 31; - else - mask = 31; - - if (mask) { - ASSERT(entry < pattern->entry + pattern->n_entries); - - entry->channel = channel; - entry->mask = 0; - - if (mask & XM_ENTRY_NOTE) { - int note = buffer[pos++]; /* 1-96 <=> C0-B7 */ - entry->note = (note == XM_NOTE_OFF) ? (IT_NOTE_OFF) : (note-1); - entry->mask |= IT_ENTRY_NOTE; - } - - if (mask & XM_ENTRY_INSTRUMENT) { - entry->instrument = buffer[pos++]; /* 1-128 */ - entry->mask |= IT_ENTRY_INSTRUMENT; - } - - if (mask & XM_ENTRY_VOLUME) - it_xm_convert_volume(buffer[pos++], entry); - - effect = effectvalue = 0; - if (mask & XM_ENTRY_EFFECT) effect = buffer[pos++]; - if (mask & XM_ENTRY_EFFECTVALUE) effectvalue = buffer[pos++]; - _dumb_it_xm_convert_effect(effect, effectvalue, entry); - - entry++; - } - - channel++; - if (channel >= n_channels) { - channel = 0; - row++; - IT_SET_END_ROW(entry); - entry++; - } - } - - return 0; -} - - - -static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data, int y_offset) -{ - int i, pos; - - if (envelope->n_nodes > 12) { - TRACE("XM error: wrong number of envelope nodes (%d)\n", envelope->n_nodes); - envelope->n_nodes = 0; - return -1; - } - - pos = 0; - for (i = 0; i < envelope->n_nodes; i++) { - envelope->node_t[i] = data[pos++]; - if (data[pos] > 64) { - TRACE("XM error: out-of-range envelope node (node_y[%d]=%d)\n", i, data[pos]); - envelope->n_nodes = 0; - return -1; - } - envelope->node_y[i] = (signed char)(data[pos++] + y_offset); - } - - return 0; -} - - - -static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA *extra, DUMBFILE *f) -{ - unsigned long size, bytes_read; - unsigned short vol_points[24]; - unsigned short pan_points[24]; - int i, type; - - /* Header size. Tends to be more than the actual size of the structure. - * So unread bytes must be skipped before reading the first sample - * header. - */ - size = dumbfile_igetl(f); - - //memset(instrument, 0, sizeof(*instrument)); - dumbfile_skip(f, 22); /* Instrument name */ - dumbfile_skip(f, 1); /* Instrument type. Should be 0, but seems random. */ - extra->n_samples = dumbfile_igetw(f); - - if (dumbfile_error(f) || (unsigned int)extra->n_samples > XM_MAX_SAMPLES_PER_INSTRUMENT) - return -1; - - bytes_read = 4 + 22 + 1 + 2; - - if (extra->n_samples) { - /* sample header size */ - if (dumbfile_igetl(f) != 0x28) { - TRACE("XM error: unexpected sample header size\n"); - return -1; - } - - /* sample map */ - for (i = 0; i < 96; i++) { - instrument->map_sample[i] = dumbfile_getc(f) + 1; - instrument->map_note[i] = i; - } - - if (dumbfile_error(f)) - return 1; - - /* volume/panning envelopes */ - for (i = 0; i < 24; i++) - vol_points[i] = dumbfile_igetw(f); - for (i = 0; i < 24; i++) - pan_points[i] = dumbfile_igetw(f); - - instrument->volume_envelope.n_nodes = dumbfile_getc(f); - instrument->pan_envelope.n_nodes = dumbfile_getc(f); - - if (dumbfile_error(f)) - return -1; - - instrument->volume_envelope.sus_loop_start = dumbfile_getc(f); - instrument->volume_envelope.loop_start = dumbfile_getc(f); - instrument->volume_envelope.loop_end = dumbfile_getc(f); - - instrument->pan_envelope.sus_loop_start = dumbfile_getc(f); - instrument->pan_envelope.loop_start = dumbfile_getc(f); - instrument->pan_envelope.loop_end = dumbfile_getc(f); - - /* The envelope handler for XM files won't use sus_loop_end. */ - - type = dumbfile_getc(f); - instrument->volume_envelope.flags = 0; - if ((type & XM_ENVELOPE_ON) && instrument->volume_envelope.n_nodes) - instrument->volume_envelope.flags |= IT_ENVELOPE_ON; - if (type & XM_ENVELOPE_LOOP) instrument->volume_envelope.flags |= IT_ENVELOPE_LOOP_ON; -#if 1 - if (type & XM_ENVELOPE_SUSTAIN) instrument->volume_envelope.flags |= IT_ENVELOPE_SUSTAIN_LOOP; -#else // This is now handled in itrender.c - /* let's avoid fading out when reaching the last envelope node */ - if (!(type & XM_ENVELOPE_LOOP)) { - instrument->volume_envelope.loop_start = instrument->volume_envelope.n_nodes-1; - instrument->volume_envelope.loop_end = instrument->volume_envelope.n_nodes-1; - } - instrument->volume_envelope.flags |= IT_ENVELOPE_LOOP_ON; -#endif - - type = dumbfile_getc(f); - instrument->pan_envelope.flags = 0; - if ((type & XM_ENVELOPE_ON) && instrument->pan_envelope.n_nodes) - instrument->pan_envelope.flags |= IT_ENVELOPE_ON; - if (type & XM_ENVELOPE_LOOP) instrument->pan_envelope.flags |= IT_ENVELOPE_LOOP_ON; // should this be here? - if (type & XM_ENVELOPE_SUSTAIN) instrument->pan_envelope.flags |= IT_ENVELOPE_SUSTAIN_LOOP; - - if (it_xm_make_envelope(&instrument->volume_envelope, vol_points, 0) != 0) { - TRACE("XM error: volume envelope\n"); - if (instrument->volume_envelope.flags & IT_ENVELOPE_ON) return -1; - } - - if (it_xm_make_envelope(&instrument->pan_envelope, pan_points, -32) != 0) { - TRACE("XM error: pan envelope\n"); - if (instrument->pan_envelope.flags & IT_ENVELOPE_ON) return -1; - } - - instrument->pitch_envelope.flags = 0; - - extra->vibrato_type = dumbfile_getc(f); - extra->vibrato_sweep = dumbfile_getc(f); - extra->vibrato_depth = dumbfile_getc(f); - extra->vibrato_speed = dumbfile_getc(f); - - if (dumbfile_error(f) || extra->vibrato_type >= 4) - return -1; - - /** WARNING: lossy approximation */ - instrument->fadeout = (dumbfile_igetw(f)*128 + 64)/0xFFF; - - dumbfile_skip(f, 2); /* reserved */ - - bytes_read += 4 + 96 + 48 + 48 + 14*1 + 2 + 2; - } - - if (dumbfile_skip(f, size - bytes_read)) - return -1; - - instrument->new_note_action = NNA_NOTE_CUT; - instrument->dup_check_type = DCT_OFF; - instrument->dup_check_action = DCA_NOTE_CUT; - instrument->pp_separation = 0; - instrument->pp_centre = 60; /* C-5 */ - instrument->global_volume = 128; - instrument->default_pan = 32; - instrument->random_volume = 0; - instrument->random_pan = 0; - instrument->filter_cutoff = 0; - instrument->filter_resonance = 0; - - return 0; -} - - - -/* I (entheh) have two XM files saved by a very naughty program. After a - * 16-bit sample, it saved a rogue byte. The length of the sample was indeed - * an odd number, incremented to include the rogue byte. - * - * In this function we are converting sample lengths and loop points so they - * are measured in samples. This means we forget about the extra bytes, and - * they don't get skipped. So we fail trying to read the next instrument. - * - * To get around this, this function returns the number of rogue bytes that - * won't be accounted for by reading sample->length samples. It returns a - * negative number on failure. - */ -static int it_xm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) -{ - int type; - int relative_note_number; /* relative to C4 */ - int finetune; - int roguebytes; - int roguebytesmask; - - sample->length = dumbfile_igetl(f); - sample->loop_start = dumbfile_igetl(f); - sample->loop_end = sample->loop_start + dumbfile_igetl(f); - sample->global_volume = 64; - sample->default_volume = dumbfile_getc(f); - finetune = (signed char)dumbfile_getc(f); /* -128..127 <=> -1 semitone .. +127/128 of a semitone */ - type = dumbfile_getc(f); - sample->default_pan = (dumbfile_getc(f)*64)/255 | 128; /* 0-255 */ - relative_note_number = (signed char)dumbfile_getc(f); - - dumbfile_skip(f, 1); /* reserved */ - dumbfile_skip(f, 22); /* sample name */ - - if (dumbfile_error(f)) - return -1; - - sample->C5_speed = (long)(16726.0*pow(DUMB_SEMITONE_BASE, relative_note_number)*pow(DUMB_PITCH_BASE, finetune*2)); - - sample->flags = IT_SAMPLE_EXISTS; - - roguebytes = (int)sample->length; - roguebytesmask = 3; - - if (type & XM_SAMPLE_16BIT) { - sample->flags |= IT_SAMPLE_16BIT; - sample->length >>= 1; - sample->loop_start >>= 1; - sample->loop_end >>= 1; - } else - roguebytesmask >>= 1; - - if (type & XM_SAMPLE_STEREO) { - sample->flags |= IT_SAMPLE_STEREO; - sample->length >>= 1; - sample->loop_start >>= 1; - sample->loop_end >>= 1; - } else - roguebytesmask >>= 1; - - roguebytes &= roguebytesmask; - - if ((unsigned int)sample->loop_start < (unsigned int)sample->loop_end) { - if (type & XM_SAMPLE_FORWARD_LOOP) sample->flags |= IT_SAMPLE_LOOP; - if (type & XM_SAMPLE_PINGPONG_LOOP) sample->flags |= IT_SAMPLE_LOOP | IT_SAMPLE_PINGPONG_LOOP; - } - - if (sample->length <= 0) - sample->flags &= ~IT_SAMPLE_EXISTS; - else if ((unsigned int)sample->loop_end > (unsigned int)sample->length) - sample->flags &= ~IT_SAMPLE_LOOP; - else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end) - sample->flags &= ~IT_SAMPLE_LOOP; - - return roguebytes; -} - - - -static int it_xm_read_sample_data(IT_SAMPLE *sample, unsigned char roguebytes, DUMBFILE *f) -{ - int old; - long i; - long truncated_size; - - if (!(sample->flags & IT_SAMPLE_EXISTS)) - return dumbfile_skip(f, roguebytes); - - /* let's get rid of the sample data coming after the end of the loop */ - if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) { - truncated_size = sample->length - sample->loop_end; - sample->length = sample->loop_end; - } else { - truncated_size = 0; - } - - sample->left = malloc(sample->length * sizeof(*sample->left)); - if (!sample->left) - return -1; - - if (sample->flags & IT_SAMPLE_STEREO) { - sample->right = malloc(sample->length * sizeof(*sample->right)); - if (!sample->right) - return -1; - } - - /* sample data is stored as signed delta values */ - old = 0; - if (sample->flags & IT_SAMPLE_16BIT) { - for (i = 0; i < sample->length; i++) { - old = sample->left[i] = (int)(signed short)(old + dumbfile_igetw(f)); - sample->left[i] <<= 8; - } - } else { - for (i = 0; i < sample->length; i++) { - old = sample->left[i] = (int)(signed char)(old + dumbfile_getc(f)); - sample->left[i] <<= 16; - } - } - - /* skip truncated data */ - dumbfile_skip(f, (sample->flags & IT_SAMPLE_16BIT) ? (2*truncated_size) : (truncated_size)); - - if (sample->flags & IT_SAMPLE_STEREO) { - old = 0; - if (sample->flags & IT_SAMPLE_16BIT) { - for (i = 0; i < sample->length; i++) { - old = sample->right[i] = (int)(signed short)(old + dumbfile_igetw(f)); - sample->right[i] <<= 8; - } - } else { - for (i = 0; i < sample->length; i++) { - old = sample->right[i] = (int)(signed char)(old + dumbfile_getc(f)); - sample->right[i] <<= 16; - } - } - /* skip truncated data */ - dumbfile_skip(f, (sample->flags & IT_SAMPLE_16BIT) ? (2*truncated_size) : (truncated_size)); - } - - dumbfile_skip(f, roguebytes); - - if (dumbfile_error(f)) - return -1; - - return 0; -} - - - -/* "Real programmers don't document. If it was hard to write, - * it should be hard to understand." - * - * (Never trust the documentation provided with a tracker. - * Real files are the only truth...) - */ -static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f) -{ - DUMB_IT_SIGDATA *sigdata; - char id_text[18]; - - int flags; - int n_channels; - int total_samples; - int i, j; - - /* check ID text */ - if (dumbfile_getnc(id_text, 17, f) < 17) - return NULL; - id_text[17] = 0; - if (strcmp(id_text, "Extended Module: ") != 0) { - TRACE("XM error: Not an Extended Module\n"); - return NULL; - } - - /* song name */ - if (dumbfile_skip(f, 20)) - return NULL; - - if (dumbfile_getc(f) != 0x1A) { - TRACE("XM error: 0x1A not found\n"); - return NULL; - } - - /* tracker name */ - if (dumbfile_skip(f, 20)) - return NULL; - - /* version number */ - if (dumbfile_igetw(f) != 0x0104) { - TRACE("XM error: wrong format version\n"); - return NULL; - } - - /* - ------------------ - --- Header --- - ------------------ - */ - - /* header size */ - if (dumbfile_igetl(f) != 0x0114) { - TRACE("XM error: unexpected header size\n"); - return NULL; - } - - sigdata = malloc(sizeof(*sigdata)); - if (!sigdata) - return NULL; - - sigdata->order = NULL; - sigdata->instrument = NULL; - sigdata->sample = NULL; - sigdata->pattern = NULL; - sigdata->midi = NULL; - sigdata->checkpoint = NULL; - - sigdata->n_samples = 0; - sigdata->n_orders = dumbfile_igetw(f); - sigdata->restart_position = dumbfile_igetw(f); - n_channels = dumbfile_igetw(f); /* max 32 but we'll be lenient */ - sigdata->n_patterns = dumbfile_igetw(f); - sigdata->n_instruments = dumbfile_igetw(f); /* max 128 */ - flags = dumbfile_igetw(f); - sigdata->speed = dumbfile_igetw(f); - sigdata->tempo = dumbfile_igetw(f); - - /* sanity checks */ - if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > 256 || sigdata->n_patterns > 256 || sigdata->n_instruments > 128 || n_channels > DUMB_IT_N_CHANNELS) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - //if (sigdata->restart_position >= sigdata->n_orders) - //sigdata->restart_position = 0; - - /* order table */ - sigdata->order = malloc(sigdata->n_orders*sizeof(*sigdata->order)); - if (!sigdata->order) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - dumbfile_getnc(sigdata->order, sigdata->n_orders, f); - dumbfile_skip(f, 256 - sigdata->n_orders); - - if (dumbfile_error(f)) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - /* - -------------------- - --- Patterns --- - -------------------- - */ - - sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); - if (!sigdata->pattern) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (i = 0; i < sigdata->n_patterns; i++) - sigdata->pattern[i].entry = NULL; - - { - unsigned char *buffer = malloc(1280 * n_channels); /* 256 rows * 5 bytes */ - if (!buffer) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (i = 0; i < sigdata->n_patterns; i++) { - if (it_xm_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) { - free(buffer); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - } - free(buffer); - } - - /* - ----------------------------------- - --- Instruments and Samples --- - ----------------------------------- - */ - - sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument)); - if (!sigdata->instrument) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - /* With XM, samples are not global, they're part of an instrument. In a - * file, each instrument is stored with its samples. Because of this, I - * don't know how to find how many samples are present in the file. Thus - * I have to do n_instruments reallocation on sigdata->sample. - * Looking at FT2, it doesn't seem possible to have more than 16 samples - * per instrument (even though n_samples is stored as 2 bytes). So maybe - * we could allocate a 128*16 array of samples, and shrink it back to the - * correct size when we know it? - * Alternatively, I could allocate samples by blocks of N (still O(n)), - * or double the number of allocated samples when I need more (O(log n)). - */ - total_samples = 0; - sigdata->sample = NULL; - - for (i = 0; i < sigdata->n_instruments; i++) { - XM_INSTRUMENT_EXTRA extra; - - if (it_xm_read_instrument(&sigdata->instrument[i], &extra, f) < 0) { - TRACE("XM error: instrument %d\n", i+1); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - - if (extra.n_samples) { - unsigned char roguebytes[XM_MAX_SAMPLES_PER_INSTRUMENT]; - - /* adjust instrument sample map (make indices absolute) */ - for (j = 0; j < 96; j++) - sigdata->instrument[i].map_sample[j] += total_samples; - - sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples)); - if (!sigdata->sample) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - for (j = total_samples; j < total_samples+extra.n_samples; j++) - sigdata->sample[j].right = sigdata->sample[j].left = NULL; - - /* read instrument's samples */ - for (j = 0; j < extra.n_samples; j++) { - IT_SAMPLE *sample = &sigdata->sample[total_samples+j]; - int b = it_xm_read_sample_header(sample, f); - if (b < 0) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - roguebytes[j] = b; - // Any reason why these can't be set inside it_xm_read_sample_header()? - sample->vibrato_speed = extra.vibrato_speed; - sample->vibrato_depth = extra.vibrato_depth; - sample->vibrato_rate = extra.vibrato_sweep; - /* Rate and sweep don't match, but the difference is - * accounted for in itrender.c. - */ - sample->vibrato_waveform = xm_convert_vibrato[extra.vibrato_type]; - } - for (j = 0; j < extra.n_samples; j++) { - if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } - } - total_samples += extra.n_samples; - } - } - - sigdata->n_samples = total_samples; - - sigdata->flags = IT_WAS_AN_XM | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO | IT_USE_INSTRUMENTS; - // Are we OK with IT_COMPATIBLE_GXX off? - // - // When specifying note + instr + tone portamento, and an old note is still playing (even after note off): - // - If Compatible Gxx is on, the new note will be triggered only if the instrument _changes_. - // - If Compatible Gxx is off, the new note will always be triggered, provided the instrument is specified. - // - FT2 seems to do the latter (unconfirmed). - - // Err, wait. XM playback has its own code. The change made to the IT - // playbackc code didn't affect XM playback. Forget this then. There's - // still a bug in XM playback though, and it'll need some investigation... - // tomorrow... - - // UPDATE: IT_COMPATIBLE_GXX is required to be on, so that tone porta has - // separate memory from portamento. - - if (flags & XM_LINEAR_FREQUENCY) - sigdata->flags |= IT_LINEAR_SLIDES; - - sigdata->global_volume = 128; - sigdata->mixing_volume = 48; - sigdata->pan_separation = 128; - - memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); - memset(sigdata->channel_pan, 32, DUMB_IT_N_CHANNELS); - - _dumb_it_fix_invalid_orders(sigdata); - - return sigdata; -} - - - -#if 0 // no fucking way, dude! - -/* The length returned is the time required to play from the beginning of the - * file to the last row of the last order (which is when the player will - * loop). Depending on the song, the sound might stop sooner. - * Due to fixed point roundoffs, I think this is only reliable to the second. - * Full precision could be achieved by using a double during the computation, - * or maybe a LONG_LONG. - */ -long it_compute_length(const DUMB_IT_SIGDATA *sigdata) -{ - IT_PATTERN *pattern; - int tempo, speed; - int loop_start[IT_N_CHANNELS]; - char loop_count[IT_N_CHANNELS]; - int order, entry; - int row_first_entry = 0; - int jump, jump_dest; - int delay, fine_delay; - int i; - long t; - - if (!sigdata) - return 0; - - tempo = sigdata->tempo; - speed = sigdata->speed; - order = entry = 0; - jump = jump_dest = 0; - t = 0; - - /* for each PATTERN */ - for (order = 0; order < sigdata->n_orders; order++) { - - if (sigdata->order[order] == IT_ORDER_END) break; - if (sigdata->order[order] == IT_ORDER_SKIP) continue; - - for (i = 0; i < IT_N_CHANNELS; i++) - loop_count[i] = -1; - - pattern = &sigdata->pattern[ sigdata->order[order] ]; - entry = 0; - if (jump == IT_BREAK_TO_ROW) { - int row = 0; - while (row < jump_dest) - if (pattern->entry[entry++].channel >= IT_N_CHANNELS) - row++; - } - - /* for each ROW */ - while (entry < pattern->n_entries) { - row_first_entry = entry; - delay = fine_delay = 0; - jump = 0; - - /* for each note NOTE */ - while (entry < pattern->n_entries && pattern->entry[entry].channel < IT_N_CHANNELS) { - int value = pattern->entry[entry].effectvalue; - int channel = pattern->entry[entry].channel; - - switch (pattern->entry[entry].effect) { - - case IT_SET_SPEED: speed = value; break; - - case IT_JUMP_TO_ORDER: - if (value <= order) /* infinite loop */ - return 0; - jump = IT_JUMP_TO_ORDER; - jump_dest = value; - break; - - case IT_BREAK_TO_ROW: - jump = IT_BREAK_TO_ROW; - jump_dest = value; - break; - - case IT_S: - switch (HIGH(value)) { - case IT_S_PATTERN_DELAY: delay = LOW(value); break; - case IT_S_FINE_PATTERN_DELAY: fine_delay = LOW(value); break; - case IT_S_PATTERN_LOOP: - if (LOW(value) == 0) { - loop_start[channel] = row_first_entry; - } else { - if (loop_count[channel] == -1) - loop_count[channel] = LOW(value); - - if (loop_count[channel]) { - jump = IT_S_PATTERN_LOOP; - jump_dest = loop_start[channel]; - } - loop_count[channel]--; - } - break; - } - break; - - case IT_SET_SONG_TEMPO: - switch (HIGH(value)) { /* slides happen every non-row frames */ - case 0: tempo = tempo - LOW(value)*(speed-1); break; - case 1: tempo = tempo + LOW(value)*(speed-1); break; - default: tempo = value; - } - tempo = MID(32, tempo, 255); - break; - } - - entry++; - } - - /* end of ROW */ - entry++; - t += TICK_TIME_DIVIDEND * (speed*(1+delay) + fine_delay) / tempo; - - if (jump == IT_JUMP_TO_ORDER) { - order = jump_dest - 1; - break; - } else if (jump == IT_BREAK_TO_ROW) - break; - else if (jump == IT_S_PATTERN_LOOP) - entry = jump_dest - 1; - } - - /* end of PATTERN */ - } - - return t; -} - -#endif /* 0 */ - - - -DUH *dumb_read_xm(DUMBFILE *f) -{ - sigdata_t *sigdata; - long length; - - DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; - - sigdata = it_xm_load_sigdata(f); - - if (!sigdata) - return NULL; - - length = _dumb_it_build_checkpoints(sigdata); - - return make_duh(length, 1, &descptr, &sigdata); -} diff --git a/Engine/libsrc/dumb-0.9.2/it/xmeffect.c b/Engine/libsrc/dumb-0.9.2/it/xmeffect.c deleted file mode 100644 index 51995f3bb82..00000000000 --- a/Engine/libsrc/dumb-0.9.2/it/xmeffect.c +++ /dev/null @@ -1,242 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * xmeffect.c - Code for converting MOD/XM / / \ \ - * effects to IT effects. | < / \_ - * | \/ /\ / - * By Julien Cugniere. Ripped out of readxm.c \_ / > / - * by entheh. | \ / / - * | ' / - * \__/ - */ - - - -#include -#include - -#include "dumb.h" -#include "internal/it.h" - - - -#if 0 -unsigned char **_dumb_malloc2(int w, int h) -{ - unsigned char **line = malloc(h * sizeof(*line)); - int i; - if (!line) return NULL; - - line[0] = malloc(w * h * sizeof(*line[0])); - if (!line[0]) { - free(line); - return NULL; - } - - for (i = 1; i < h; i++) - line[i] = line[i-1] + w; - - memset(line[0], 0, w*h); - - return line; -} - - - -void _dumb_free2(unsigned char **line) -{ - if (line) { - if (line[0]) - free(line[0]); - free(line); - } -} - - - -/* Effects having a memory. 2 means that the two parts of the effectvalue - * should be handled separately. - */ -static const char xm_has_memory[] = { -/* 0 1 2 3 4 5 6 7 8 9 A B C D (E) F G H K L P R T (X) */ - 0, 1, 1, 1, 2, 1, 1, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, - -/* E0 E1 E2 E3 E4 E5 E6 E7 E9 EA EB EC ED EE X1 X2 */ - 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; -#endif - - - -/* Effects marked with 'special' are handled specifically in itrender.c */ -void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry) -{ -const int log = 0; - - if ((!effect && !value) || (effect >= XM_N_EFFECTS)) - return; - -if (log) printf("%c%02X", (effect<10)?('0'+effect):('A'+effect-10), value); - - /* Linearisation of the effect number... */ - if (effect == XM_E) { - effect = EBASE + HIGH(value); - value = LOW(value); - } else if (effect == XM_X) { - effect = XBASE + HIGH(value); - value = LOW(value); - } - -if (log) printf(" - %2d %02X", effect, value); - -#if 0 // This should be handled in itrender.c! - /* update effect memory */ - switch (xm_has_memory[effect]) { - case 1: - if (!value) - value = memory[entry->channel][effect]; - else - memory[entry->channel][effect] = value; - break; - - case 2: - if (!HIGH(value)) - SET_HIGH(value, HIGH(memory[entry->channel][effect])); - else - SET_HIGH(memory[entry->channel][effect], HIGH(value)); - - if (!LOW(value)) - SET_LOW(value, LOW(memory[entry->channel][effect])); - else - SET_LOW(memory[entry->channel][effect], LOW(value)); - break; - } -#endif - - /* convert effect */ - entry->mask |= IT_ENTRY_EFFECT; - switch (effect) { - - case XM_APPREGIO: effect = IT_ARPEGGIO; break; - case XM_VIBRATO: effect = IT_VIBRATO; break; - case XM_TONE_PORTAMENTO: effect = IT_TONE_PORTAMENTO; break; /** TODO: glissando control */ - case XM_TREMOLO: effect = IT_TREMOLO; break; - case XM_SET_PANNING: effect = IT_SET_PANNING; break; - case XM_SAMPLE_OFFSET: effect = IT_SET_SAMPLE_OFFSET; break; - case XM_POSITION_JUMP: effect = IT_JUMP_TO_ORDER; break; - case XM_MULTI_RETRIG: effect = IT_RETRIGGER_NOTE; break; - case XM_TREMOR: effect = IT_TREMOR; break; - case XM_PORTAMENTO_UP: effect = IT_XM_PORTAMENTO_UP; break; - case XM_PORTAMENTO_DOWN: effect = IT_XM_PORTAMENTO_DOWN; break; - case XM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break; /* special */ - case XM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break; /* special */ - case XM_VOLSLIDE_VIBRATO: effect = IT_VOLSLIDE_VIBRATO; break; /* special */ - - case XM_PATTERN_BREAK: - effect = IT_BREAK_TO_ROW; - value = BCD_TO_NORMAL(value); - break; - - case XM_VOLUME_SLIDE: /* special */ - effect = IT_VOLUME_SLIDE; - value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value)); - break; - - case XM_PANNING_SLIDE: - effect = IT_PANNING_SLIDE; - value = HIGH(value) ? EFFECT_VALUE(0, HIGH(value)) : EFFECT_VALUE(LOW(value), 0); - break; - - case XM_GLOBAL_VOLUME_SLIDE: /* special */ - effect = IT_GLOBAL_VOLUME_SLIDE; - value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value)); - break; - - case XM_SET_TEMPO_BPM: - effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO); - break; - - case XM_SET_GLOBAL_VOLUME: - effect = IT_SET_GLOBAL_VOLUME; - value *= 2; - break; - - case XM_KEY_OFF: - /** WARNING: In FT2, the value seems to do something... Oh well, - * this is undocumented anyway! - */ - entry->mask &= ~IT_ENTRY_EFFECT; - entry->mask |= IT_ENTRY_NOTE; - entry->note = IT_NOTE_OFF; - break; - - case EBASE+XM_E_SET_FILTER: effect = SBASE+IT_S_SET_FILTER; break; - case EBASE+XM_E_SET_GLISSANDO_CONTROL: effect = SBASE+IT_S_SET_GLISSANDO_CONTROL; break; /** TODO */ - case EBASE+XM_E_SET_FINETUNE: effect = SBASE+IT_S_FINETUNE; break; /** TODO */ - case EBASE+XM_E_SET_LOOP: effect = SBASE+IT_S_PATTERN_LOOP; break; - case EBASE+XM_E_NOTE_CUT: effect = SBASE+IT_S_DELAYED_NOTE_CUT; break; - case EBASE+XM_E_NOTE_DELAY: effect = SBASE+IT_S_NOTE_DELAY; break; - case EBASE+XM_E_PATTERN_DELAY: effect = SBASE+IT_S_PATTERN_DELAY; break; - case EBASE+XM_E_FINE_VOLSLIDE_UP: effect = IT_XM_FINE_VOLSLIDE_UP; break; - case EBASE+XM_E_FINE_VOLSLIDE_DOWN: effect = IT_XM_FINE_VOLSLIDE_DOWN; break; - - case EBASE + XM_E_FINE_PORTA_UP: - effect = IT_PORTAMENTO_UP; - value = EFFECT_VALUE(0xF, value); - break; - - case EBASE + XM_E_FINE_PORTA_DOWN: - effect = IT_PORTAMENTO_DOWN; - value = EFFECT_VALUE(0xF, value); - break; - - case EBASE + XM_E_RETRIG_NOTE: - effect = IT_XM_RETRIGGER_NOTE; - value = EFFECT_VALUE(0, value); - break; - - case EBASE + XM_E_SET_VIBRATO_CONTROL: - effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM; - value &= ~4; /** TODO: value&4 -> don't retrig wave */ - break; - - case EBASE + XM_E_SET_TREMOLO_CONTROL: - effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM; - value &= ~4; /** TODO: value&4 -> don't retrig wave */ - break; - - case XBASE + XM_X_EXTRAFINE_PORTA_UP: - effect = IT_PORTAMENTO_UP; - value = EFFECT_VALUE(0xE, value); - break; - - case XBASE + XM_X_EXTRAFINE_PORTA_DOWN: - effect = IT_PORTAMENTO_DOWN; - value = EFFECT_VALUE(0xE, value); - break; - - default: - /* user effect (often used in demos for synchronisation) */ - entry->mask &= ~IT_ENTRY_EFFECT; - } - -if (log) printf(" - %2d %02X", effect, value); - - /* Inverse linearisation... */ - if (effect >= SBASE && effect < SBASE+16) { - value = EFFECT_VALUE(effect-SBASE, value); - effect = IT_S; - } - -if (log) printf(" - %c%02X\n", 'A'+effect-1, value); - - entry->effect = effect; - entry->effectvalue = value; -} diff --git a/Engine/libsrc/dumb-0.9.2/readme.txt b/Engine/libsrc/dumb-0.9.2/readme.txt deleted file mode 100644 index 45abd1a17ac..00000000000 --- a/Engine/libsrc/dumb-0.9.2/readme.txt +++ /dev/null @@ -1,421 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * readme.txt - General information on DUMB. / / \ \ - * | < / \_ - * | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - - -******************** -*** Introduction *** -******************** - - -Thank you for downloading DUMB! You should have the following documentation: - - readme.txt - This file - licence.txt - Conditions for the use of this software - release.txt - Release notes and changes for this and past releases - docs/ - howto.txt - Step-by-step instructions on adding DUMB to your project - faq.txt - Frequently asked questions and answers to them - dumb.txt - DUMB library reference - deprec.txt - Information about deprecated parts of the API - ptr.txt - Quick introduction to pointers for those who need it - fnptr.txt - Explanation of function pointers for those who need it - modplug.txt - Our official position regarding ModPlug Tracker - -This file will help you get DUMB set up. If you have not yet done so, please -read licence.txt and release.txt before proceeding. After you've got DUMB set -up, please refer to the files in the docs/ directory at your convenience. I -recommend you start with howto.txt. - - -**************** -*** Features *** -**************** - - -Here is the statutory feature list: - -- Freeware - -- Supports playback of IT, XM, S3M and MOD files - -- Faithful to the original trackers, especially IT; if it plays your module - wrongly, please tell me so I can fix the bug! (But please don't complain - about differences between DUMB and ModPlug Tracker; see docs/modplug.txt) - -- Accurate support for low-pass resonant filters for IT files - -- Very accurate timing and pitching; completely deterministic playback - -- Click removal - -- Facility to embed music files in other files (e.g. Allegro datafiles) - -- Three resampling quality settings: aliasing, linear interpolation and cubic - interpolation - -- Number of samples playing at once can be limited to reduce processor usage, - but samples will come back in when other louder ones stop - -- All notes will be present and correct even if you start a piece of music in - the middle - -- Fast seeking to any point before the music first loops (seeking time - increases beyond this point) - -- Audio generated can be used in any way; DUMB does not necessarily send it - straight to a sound output system - -- Makefile provided for DJGPP, MinGW, Linux, BeOS and Mac OS X; project file - provided for MSVC 6 (please contact me if you'd like to submit or request - support for a new platform; the code itself should port anywhere that has a - 32-bit C compiler) - -- Can be used with Allegro, can be used without (if you'd like to help make - DUMB more approachable to people who aren't using Allegro, please contact - me) - - -********************* -*** What you need *** -********************* - - -To use DUMB, you need a 32-bit C compiler (GCC and MSVC are fine). If you -have Allegro, DUMB can integrate with its audio streams and datafiles, making -your life easier. If you do not wish to use Allegro, you will have to do some -work to get music playing back. The 'dumbplay' example program requires -Allegro. - - Allegro - http://alleg.sf.net/ - -Neil Walker has kindly uploaded some DUMB binaries at -http://retrospec.sgn.net/allegro/ . They may not always be up to date, so you -should try to compile it yourself first. - - -********************************************** -*** How to set DUMB up with DJGPP or MinGW *** -********************************************** - - -You should have got the .zip version. If for some reason you got the .tar.gz -version instead, you may have to convert make/config.bat to DOS text file -format. WinZip does this automatically by default. Otherwise, loading it into -MS EDIT and saving it again should do the trick. You will have to do the same -for any files you want to view in Windows Notepad. If you have problems, just -go and download the .zip instead. - -Make sure you preserved the directory structure when you extracted DUMB from -the archive. Most unzipping programs will do this by default, but pkunzip -requires you to pass -d. If not, please delete DUMB and extract it again -properly. - -If you are using Windows, open an MS-DOS Prompt or a Windows Command Line. -Change to the directory into which you unzipped DUMB. - -Type the following: - - make - -DUMB will ask you whether you wish to compile for DJGPP or MinGW. Then it -will ask you whether you want support for Allegro. (You have to have made and -installed Allegro's optimised library for this to work.) Finally, it will -compile optimised and debugging builds of DUMB, along with the example -programs. When it has finished, run the following to install the libraries: - - make install - -All done! If you ever need the configuration again (e.g. if you compiled for -DJGPP before and you want to compile for MinGW now), run the following: - - make config - -See the comments in the makefile for other targets. - -Note: the makefile will only work properly if you have COMSPEC or ComSpec set -to point to command.com or cmd.exe. If you set it to point to a Unix-style -shell, the makefile won't work. - -Please let me know if you have any trouble. - -Scroll down for information on the example programs. Refer to docs/howto.txt -when you are ready to start programming with DUMB. If you use DUMB in a game, -let me know - I might decide to place a link to your game on DUMB's website! - - -****************************************************** -*** How to set DUMB up with Microsoft Visual C++ 6 *** -****************************************************** - - -You should have got the .zip version. If for some reason you got the .tar.gz -version instead, you may have to convert some files to DOS text file format. -WinZip does this automatically by default. Otherwise, loading such files into -MS EDIT and saving them again should do the trick. You will have to do this -for any files you want to view in Windows Notepad. If you have problems, just -go and download the .zip instead. - -Make sure you preserved the directory structure when you extracted DUMB from -the archive. Most unzipping programs will do this by default, but pkunzip -requires you to pass -d. If not, please delete DUMB and extract it again -properly. - -DUMB now comes with a project file for Microsoft Visual C++ 6. To add DUMB to -your project: - -1. Open your project in VC++. -2. Select Project|Insert Project into Workspace... -3. Navigate to the dumb\vc6 directory, and select dumb.dsp. -4. Select Build|Set Active Configuration..., and reselect one of your - project's configurations. -5. Select Project|Dependencies... and ensure your project is dependent on - DUMB. -6. Select Project|Settings..., Settings for: All Configurations, C/C++ tab, - Preprocessor category. Add the DUMB include directory to the Additional - Include Directories box. -7. Ensure that for all the projects in the workspace (or more likely just all - the projects in a particular dependency chain) the run-time libraries are - the same. That's in Project|Settings, C/C++ tab, Code generation category, - Use run-time library dropdown. The settings for Release and Debug are - separate, so you'll have to change them one at a time. Exactly which run- - time library you use will depend on what you need; it doesn't appear that - DUMB has any particular requirements, so set it to whatever you're using - now. - -Good thing you only have to do all that once ... - -If you have the Intel compiler installed, it will - well, should - be used to -compile DUMB. The only setting I added is /QxiM. This allows the compiler to -use PPro and MMX instructions, and so when compiling with Intel the resultant -EXE will require a Pentium II or greater. I don't think this is unreasonable. -After all, it is 2003 :) - -If you don't have the Intel compiler, VC will compile DUMB as normal. - -This project file and these instructions were provided by Tom Seddon (I hope -I got his name right; I had to guess it from his e-mail address!). They are -untested by me. If you have problems, check the download page at -http://dumb.sf.net/ to see if they are addressed; failing that, direct -queries to me and I'll try to figure them out. - -When you are ready to start using DUMB, refer to docs/howto.txt. If you use -DUMB in a game, let me know - I might decide to place a link to your game on -DUMB's website! - - -******************************************************************** -*** How to set DUMB up on Linux, BeOS and possibly even Mac OS X *** -******************************************************************** - - -You should have got the .tar.gz version. If for some reason you got the .zip -version instead, you may have to use dtou on some or all of the text files. -If you have problems, just go and download the .tar.gz instead. - -First, run the following command as a normal user: - - make - -You will be asked whether you want Allegro support. Then, unless you are on -BeOS, you will be asked where you'd like DUMB to install its headers, -libraries and examples (which will go in the include/, lib/ and bin/ -subdirectories of the prefix you specify). BeOS has fixed locations for these -files. Once you have specified these pieces of information, the optimised and -debugging builds of DUMB will be compiled, along with the examples. When it -has finished, you can install them with: - - make install - -You may need to be root for this to work. It depends on the prefix you chose. - -Note: the makefile will only work if COMSPEC and ComSpec are both undefined. -If either of these is defined, the makefile will try to build for a Windows -system, and will fail. - -Please let me know if you have any trouble. - -Information on the example programs is just below. Refer to docs/howto.txt -when you are ready to start programming with DUMB. If you use DUMB in a game, -let me know - I might decide to place a link to your game on DUMB's website! - - -**************************** -*** The example programs *** -**************************** - - -Two example programs are provided. On DOS and Windows, you can find them in -the examples subdirectory. On other systems they will be installed system- -wide. - -dumbplay - This program will only be built if you have Allegro. Pass it the filename - of an IT, XM, S3M or MOD file, and it will play it. It's not a polished - player with real-time threading or anything - so don't complain about it - stuttering while you use other programs - but it does show DUMB's fidelity - nicely. You can control the playback quality by editing dumb.ini, which - must be in the current working directory. (This is a flaw for systems - where the program is installed system-wide, but it is non-fatal.) Have a - look at the examples/dumb.ini file for further information. - -dumbout - This program does not need Allegro. You can use it to stream an IT, XM, - S3M or MOD file to raw PCM. This can be used as input to an encoder like - oggenc (with appropriate command-line options), or it can be sent to a - .pcm file which can be read by any respectable waveform editor. No .wav - support yet, sorry. This program is also convenient for timing DUMB. - Compare the time it takes to render a module with the module's playing - time! dumbout doesn't try to read any configuration file; the options are - set on the command line. - - -********************************************* -*** Downloading music or writing your own *** -********************************************* - - -If you would like to compose your own music modules, then first I must offer -a word of warning: not everyone is capable of composing music. Do not assume -you will be able to learn the art. By all means have a go; if you can learn -to play tunes on the computer keyboard, you're well on the way to being a -composer! - -The best programs for the job are the trackers that pioneered the file -formats: - - Impulse Tracker - IT files - http://www.noisemusic.org/it/ - Fast Tracker II - XM files - http://www.gwinternet.com/music/ft2/ - Scream Tracker 3 - S3M files - - http://www.united-trackers.org/resources/software/screamtracker.htm - -MOD files come from the Amiga; I do not know what PC tracker to recommend for -editing these. If you know of one, let me know! In the meantime, I would -recommend using a more advanced file format. However, don't convert your -existing MODs just for the sake of it. - -Note that Fast Tracker II is Shareware. It arguably offers the best -interface, but the IT file format is more powerful and better defined. -Impulse Tracker and Scream Tracker 3 are Freeware. DUMB is likely to be at -its best with IT files. - -These editors are DOS programs. Users of DOS-incapable operating systems may -like to try ModPlug Tracker, but should read docs/modplug.txt before using it -for any serious work. If you use a different operating system, or if you know -of any module editors for Windows that are more faithful to the original -trackers' playback, please give me some links so I can put them here! - - ModPlug Tracker - http://www.modplug.com/ - -BEWARE OF WINAMP! Although it's excellent for MP3s, it is notorious for being -one of the worst module players in existence; very few modules play correctly -with it. There are plug-ins available to improve Winamp's module support, for -example WSP. - - Winamp - http://www.winamp.com/ - WSP - http://www.spytech.cz/index.php?sec=demo - -Samples and instruments are the building blocks of music modules. You can -download samples at: - - http://www.tump.net/ - -If you would like to download module files composed by other people, check -the following sites: - - http://www.modarchive.com/ - http://www.scene.org/ - http://www.tump.net/ - http://www.homemusic.cc/main.php - http://www.modplug.com/ - -Once again, if you know of more sites where samples or module files are -available for download, please let me know. - -If you wish to use someone's music in your game, please respect the -composer's wishes. In general, you should ask the composer. Music that has -been placed in the Public Domain can be used by anyone for anything, but it -wouldn't do any harm to ask anyway if you know who the author is. In most -cases the author will be thrilled, so don't hesitate! - -A note about converting modules from one format to another: don't do it, -unless you are a musician and are prepared to go through the file and make -sure everything sounds the way it should! The module formats are all slightly -different, and converting from one format to another will usually do some -damage. - -Instead, it is recommended that you allow DUMB to interpret the original file -as it sees fit. DUMB may make mistakes (it does a lot of conversion on -loading), but future versions of DUMB will be able to rectify these mistakes. -On the other hand, if you convert the file, the damage is permanent. - - -*********************** -*** Contact details *** -*********************** - - -If you have trouble with DUMB, or want to contact me for any other reason, my -e-mail address is given below. However, I may be able to help more if you -come on to IRC EFnet #dumb. - -IRC stands for Internet Relay Chat, and is a type of chat network. Several -such networks exist, and EFnet is a popular one. In order to connect to an -IRC network, you first need an IRC client. Here are some: - - http://www.xchat.org/ - http://www.visualirc.net/beta.php - http://www.mirc.com/ - -Getting on to IRC can be a steep cliff, but it is not insurmountable, and -it's well worth it. Once you have set up the client software, you need to -connect to a server. Here is a list of EFnet servers I have had success with. -Type "/server" (without quotes), then a space, then the name of a server. - - irc.homelien.no - irc.webgiro.se - efnet.vuurwerk.nl - efnet.demon.co.uk - irc.isdnet.fr - irc.prison.net - -If these servers do not work, visit http://efnet.org/ircdb/servers.php for a -huge list of other EFnet servers to try. - -Once you're connected, type the following: - - /join #dumb - -A window will appear, and you can ask your question. It should be clear -what's going on from this point onwards. I am 'entheh'. Note that unlike many -other nerds I am not always at my computer, so if I don't answer your -question, don't take it personally! I will usually be able to read your -question when I come back. - - -****************** -*** Conclusion *** -****************** - - -This is the conclusion. - - -Ben Davis -entheh@users.sf.net -IRC EFnet #dumb diff --git a/Engine/libsrc/dumb-0.9.2/release.txt b/Engine/libsrc/dumb-0.9.2/release.txt deleted file mode 100644 index eff4b8ded89..00000000000 --- a/Engine/libsrc/dumb-0.9.2/release.txt +++ /dev/null @@ -1,406 +0,0 @@ -/* _______ ____ __ ___ ___ - * \ _ \ \ / \ / \ \ / / ' ' ' - * | | \ \ | | || | \/ | . . - * | | | | | | || ||\ /| | - * | | | | | | || || \/ | | ' ' ' - * | | | | | | || || | | . . - * | |_/ / \ \__// || | | - * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque - * / \ - * / . \ - * release.txt - Release notes for DUMB. / / \ \ - * | < / \_ - * | \/ /\ / - * \_ / > / - * | \ / / - * | ' / - * \__/ - */ - - -****************************************** -*** DUMB v0.9.2, released 2 April 2003 *** -****************************************** - -Yes, there really has been a release. This is not a day-late April fools' -joke. - -DUMB's full name has changed! The old "Dedicated Universal Music -Bastardisation" was rather silly, and not much more than a forced attempt at -finding words beginning with D, U, M and B. I spent weeks and weeks browsing -dictionaries and hopelessly asking others for bright ideas, until the -brilliant Chris "Kitty Cat" Robinson came up with "Dynamic". I decided to -keep the U as Universal, since a DUH struct can hold digital music in any -format. Now all that remained was the B, but it didn't take me long to come -up with Bibliotheque, which, despite looking French, is indeed considered an -English word by Oxford English Dictionary Online, to which my university has -a subscription. So there you have it - the name now makes sense. - -The two most significant additions to the project would have to be the new -thread safety (with an important restriction, detailed in docs/dumb.txt), and -the new build system. The silly 'makeall' and 'makecore' scripts are gone. If -you are a GCC user, all you need do now is run 'make' and 'make install', as -for other projects. You don't even have to run a 'fix' script any more! There -are some caveats, which are covered in readme.txt. If you use Microsoft -Visual C++ 6, you no longer need to obtain GCC and GNU Make - there is a -project file just for you. - -Huge thanks go to Steve Terry for testing on Windows XP - about five times - -and to lillo for testing on BeOS and Mac OS X. Thanks also to X-G for testing -on a Windows system that has consistently posed problems for DUMB's old -makefiles. - -There was a bug whereby al_poll_duh() would sometimes cause the music to -resume playing if you called it after al_pause_duh(). Whether this was DUMB's -fault for misusing Allegro's API, or a bug in Allegro, is unclear, but this -release makes it work. - -In one of my projects, I found that my AL_DUH_PLAYER stopped playing when -there were lots of other sound effects. In order to fix this, I programmed -DUMB to set the priority of the stream's voice to 255, the maximum. I also -added al_duh_set_priority(), so you can set the priority yourself if you need -to. - -The resampling code has undergone a transformation. The bad news is that the -linear average code is no longer in use. The good news is that where DUMB's -resamplers used to require three extra samples' worth of memory to be -allocated and initialised, it now copes with just the sample data. And it -does a very good job at bouncing off loop points and otherwise hurtling -around the sample. The resampling code is considerably more complicated, but -the code that uses the resamplers is considerably simpler - and if you -noticed a slight click in some bidirectionally looping samples, you'll be -pleased to know that that click is gone! - -I have also devoted some effort to optimisation. It seemed hopeless for a -while, but then I actually figured out a way of making it faster AND more -accurate at the same time! DUMB is now quite a bit faster than it was, and it -mixes not with 16-bit precision, but with 24-bit precision. (It used 32-bit -integers all along, but the difference is that it now makes use of 256 times -as much of the integer's range.) - -There have been the usual improvements to playback. The last release occurred -rather too soon after I had fixed the XM effect memories; EAx and EBx, fine -volume ramps, had been neglected. These are now handled properly. - -In previous versions of DUMB, muted channels in IT were actually played with -surround sound panning (where the right-hand channel is inverted). This has -been fixed, so muted channels will really be muted now. - -There were also some subtle problems with the way DUMB handled New Note -Actions for IT files. It turned out that, in all releases of DUMB so far, -pitch, filter and panning envelopes and sample vibrato were not being -processed for any note that was forced into the background by a new note on -the same channel! This only affected IT files. Not only has this been fixed, -but envelope interpolation is much more accurate. Long trailing envelope- -driven fade-outs sound a lot better now! - -Since panning and filter envelopes are more precise, extra fields have been -added to the DUMB_IT_CHANNEL_STATE struct, used by -dumb_it_sr_get_channel_state(). These fields hold the 'decimal' parts of the -pan and filter cut-off. See dumb.txt for details. - -Mxx (set channel volume) now correctly only modifies the last note played on -the channel, not any previous notes that have been forced into the background -by New Note Actions, and filter effect processing is now closer to what -Impulse Tracker does. - -The XM loader was slightly flawed and could crash on files containing samples -with out-of-range loop points. One such file was given to me. This has been -fixed. - -Finally, the legal stuff. Julien Cugniere has been added to the list of -copyright owners. He deserves it, for all the work he did on the XM support! -And the licence has been changed. You are no longer required to include a -link to DUMB in a project that uses DUMB; the reasons for this relaxation are -explained in licence.txt. However, the request is still there ... - -As usual, enjoy! - - -********************************************** -*** DUMB v0.9.1, released 19 December 2002 *** -********************************************** - -Hi again! Lots to say this time, so I shall cut right to the chase. - -DUMB now supports Impulse Tracker's low-pass resonant filters! Huge thanks go -to Jeffrey Lim, author of Impulse Tracker, for giving me what information he -still had regarding the algorithm; to cut a long story short, modifying -ModPlug Tracker's source code (which is in the Public Domain) led to an -algorithm whose output matched Impulse Tracker's perfectly. - -Please note that ModPlug Tracker's filters as they stand do not match Impulse -Tracker's, and I have no interest in supporting ModPlug Tracker's variant -(especially not the integer rounding problems). Please see docs/modplug.txt, -new in this release, for details. - -Thanks also go to Fatso Huuskonen for motivating me to add filter support, -and providing me with several great IT files to test it with! - -The other important feature added for this release is click removal. Up until -now, DUMB has generated clicks when cutting notes, starting samples in the -middle, and so on. This version of DUMB will remove any such clicks. Note -that DUMB does not use volume ramps to accomplish this; the algorithm will -not take the bite out of the music! - -In other news, DUMB now supports sample vibrato for IT files, and instrument -vibrato for XM files. A slight bug in New Note Action handling for IT files -has been fixed; Note Fade will not break the sustain loops of the sample and -envelope, as it did before. Tremor handling (Ixy) had a strange bug in it, -which has been fixed. - -Support for XM files has been greatly enhanced. The XM envelope handling new -in the last release contained a huge bug, resulting in notes seeming not to -stop when they should; this has been fixed. Some XM files crashed DUMB, while -others failed to load; these problems have been solved. Effect memories now -work properly for XM and MOD files, to the best of my knowledge. Some other -differences between IT and XM have been accounted for, most notably the -Retrigger Note effects, Rxy and E9x. - -DUMB's sound quality and accuracy are not the only areas that have been -enhanced. The API has been expanded, at last. You can now detect when a -module loops, or make it play through just once. You can ask DUMB to inform -you every time it generates some samples; this is useful for visualisation. -For IT files, you can intercept the MIDI messages generated by Zxx macros, -enabling you to synchronise your game with the music to some extent. (There -is no such method for XM, S3M or MOD files yet; sorry. Also note that the -function will be called before you actually hear the sound; I cannot improve -this until DUMB has its own sound drivers, which won't be for a while.) You -can query the current order and row. Finally, operations like changing the -speed and tempo are now possible, and you can query the playback state on -each channel. - -Some parts of DUMB's API have been deprecated. Simple programs that use -Allegro will be unaffected, but if you get some compiler warnings or errors, -please review docs/deprec.txt. This file explains why those parts of the API -were deprecated, and tells you how to adapt your code; the changes you need -to make are straightforward. Sorry for the inconvenience. - -For various reasons, I have made DUMB's makefiles use different compiler -flags depending on your GCC version (unless you are using MSVC). There is no -elegant way of getting the makefiles to detect when GCC is upgraded. If you -upgrade GCC, you should execute 'make clean' in order to make DUMB detect the -GCC version again. Otherwise you may get some annoying error messages. (It is -wise to do this in any case, so that all the object files are built with the -same GCC version.) - -DUMB's example players have been unified into a single player called -'dumbplay'. The player has been enhanced to display messages when the music -loops, and when XM and MOD files freeze (effect F00; more information on this -in docs/howto.txt). - -Finally, as noted on DUMB's website, the release notes from the last release -were inaccurate. It has been verified that DUMBOGG v0.5 does still work with -that release, and still works with this release. The esoteric DUMBOGG v0.6 -has not been created yet, since DUMBOGG v0.5 still works. - -Please scroll down and read through the indented paragraphs in the notes for -the last release; they are relevant for this release too. - -That's all folks! Until next time. - - -******************************************* -*** DUMB v0.9, released 16 October 2002 *** -******************************************* - -MOD support is here! DUMB now supports all four of the common module formats. -As usual, there have also been some improvements to the way modules are -played back. Most notably, handling of tone portamento in IT files has been -improved a lot, and XM envelopes are now processed correctly. - -The other major change is that DUMB now does a dummy run through each module -on loading. It stores the playback state at thirty-second intervals. It stops -when the module first loops, and then stores the playback time. This results -in a slightly longer load time and a greater memory overhead, but seeking is -faster (to any point before the module first loops) and the length is -calculated! duh_get_length() will return this and is now documented in -docs/howto.txt and docs/dumb.txt. - -DUMB's build process has been changed to use 'mingw' wherever it used -'mingw32' before; some directories have been renamed, and the 'fix' command -you had to run for MinGW has been changed from 'fix mingw32' to 'fix mingw'. - -Last time, I directed you to scroll down and read the notes from a past -release, but ignore this point, and that point applies to something else, and -so on. Did anyone do so? Well, if you're reading this at all, you probably -did. Nevertheless, this time I shall be much less confusing and restate any -relevant information. So the least you can do is read it! - -- If your program ever aborts with exit code 37 while loading an IT file, - PLEASE LET ME KNOW! The IT file in question has a stereo compressed sample - in it, and the format is unspecified for this case (Impulse Tracker itself - doesn't use stereo samples at all). I will need the IT file in question, - and any information you can give me about how the IT file was created (e.g. - what program). (If you don't get to see an exit code, let me know anyway.) - -- If your program ever outputs a line resembling "Inst 01 Env: 0,64 8,32 - 15,48" to stderr while loading an IT file, PLEASE LET ME KNOW! You have an - old IT file (saved by an Impulse Tracker version older than 2.00), and - support for such files is STILL untested. - -- Not all parts of DUMB's API are documented yet. You will find some - functions in dumb.h which are not listed in docs/dumb.txt; the reason is - that these functions still need work and will probably change. If you - really, really want to use them, talk to me first (IRC EFnet #dumb is a - good place for this; see readme.txt for details on using IRC). I intend to - finalise and document the whole of DUMB's API for Version 1.0. - -There have been some changes to the naming conventions in DUMB's undocumented -API. DUMBOGG v0.5 will not work with this and subsequent releases of DUMB; -please upgrade to DUMBOGG v0.6. These changes should not break anything in -your own code, since you didn't use those parts of the API, did you ;) - -There is still a great deal of work to be done before DUMB's API can be -finalised, and thus it will be a while before DUMB v1.0 comes out. It should -be worth the wait. In the meantime, there will be 0.9.x releases with -additional functionality, improved playback, and possibly support for some -extra file formats. - -Finally I should like to offer an apology; there is a strong possibility that -some of DUMB's official API will change in the near future. There will not be -any drastic changes, and the corresponding changes to your source code will -be simple enough. If I didn't make these changes, DUMB's API would start to -become limited, or messy, or both, so it's for the better. I apologise in -advance for this. - -Now scroll down and read the notes for the first r... oh wait, we already did -that. I guess that's it then. You can stop reading now. - -Right after you've read this. - -And this. - -Off you go. - -Bye. - - -******************************************** -*** DUMB v0.8.1, released 11 August 2002 *** -******************************************** - -This is a minor release that fixes a few bugs. One of these bugs, however, -was pretty serious. dumb_register_dat_xm() was never coded! It was prototyped -in aldumb.h, so code would compile, but there would be an unresolved symbol -at the linking stage. This has been fixed. - -Platforms other than Unix did not have a working 'make veryclean' target; -this has been fixed. In addition, the makefiles now use 'xcopy' instead of -'copy', since on some systems GNU Make seems to have trouble calling commands -built in to the shell. - -Contrary to the errata that was on the DUMB website, the makeall.sh and -makecore.sh scripts actually DID install in /usr. This has now been -corrected, and regardless of whether you use these scripts or call make -directly, the files will now be installed to /usr/local by default. - -The XM loader used to treat stereo samples as mono samples with the data for -the right channel positioned after the data for the left channel. This -generally resulted in an unwanted echo effect. This has been fixed. - -When playing XM files, specifying an invalid instrument would cause an old -note on that channel to come back (roughly speaking). Fast Tracker 2 does not -exhibit this behaviour. This has been fixed. - -The GCC makefiles used -mpentium, which is deprecated in gcc 3.x. This was -generating warnings, and has now been fixed. - -In XM files, the length of a sample is stored in bytes. DUMB was assuming -that the length of a 16-bit sample would be even. I had two XM files where -this was not the case, and DUMB was unable to load them. This has been fixed. - -In order to accommodate the extra part of the version number, -DUMB_REVISION_VERSION has been added. DUMB_VERSION has also been added in -order to facilitate checking if the version of DUMB installed is sufficient. -See docs/dumb.txt for details. - -As a last-minute fix, the XM "Break to row" effect is now loaded properly. It -was necessary to convert from binary-coded decimal to hexadecimal (those who -have experience with Fast Tracker 2 will know what I mean). In short, this -means the effect will now work properly when breaking to row 10 or greater. - -DUMB v0.8 had faulty release date constants; DUMB_MONTH and DUMB_DAY were -swapped! For this reason, DUMB_DATE should not be compared against any date -in 2002. This note has been added to docs/dumb.txt and also to dumb.h. - -Please scroll to the end and read the release notes for the first version, -DUMB v0.7. Most of them apply equally to this release. However, the -non-portable code was rewritten for DUMB v0.8, so that point does not apply. -The point about length not being calculated also applies to XM files. - -Enjoy :) - - -**************************************** -*** DUMB v0.8, released 14 June 2002 *** -**************************************** - -Welcome to the second release of DUMB! - -In addition to these notes, please read below the release notes for the -previous version, DUMB v0.7. Most of them apply equally to this release. -However, the non-portable code has been rewritten; DUMB should now port to -big-endian platforms. - -The main improvement in this release of DUMB is the support for XM files. -Enormous thanks go to Julien Cugniere for working on this while I had to -revise for my exams! - -There was a mistake in the makefiles in the last release. The debugging -Allegro interface library was mistakenly named libaldmbd.a instead of -libaldmd.a, meaning you had to compile with -laldmbd, contrary to what the -docs said. Apologies to everyone who lost sleep trying to work out what was -wrong! The reason for using libaldmd.a is to maintain compatibility with -plain DOS, where filenames are limited to eight characters (plus a three- -letter extension). The makefiles have now been changed to match the -information in the docs, so you may have to alter your project files -accordingly. - -The example programs were faulty, and crashed on Windows if they were unable -to load the file. It was also difficult to work out how to exit them (you had -to click the taskbar button that didn't have a window, then press a key). -They have been improved in both these respects. - -I have now added a docs/faq.txt file (Frequently Asked Questions), which is -based on problems and misconceptions people have had with the first release. -Please refer to it before contacting me with problems. - -Thanks to networm for touching up the Unix makefile and writing the -instructions on using it. - -Incidentally, today (Friday 14 June) is the Robinson College May Ball at -Cambridge Uni. God knows why it's called a May Ball if it's in June. I'm not -going myself (72 GBP, and I'd have to wear a suit, ugh), but with all the -noise outside I shall enjoy pumping up the speakers tonight! - - -**************************************** -*** DUMB v0.7, released 2 March 2002 *** -**************************************** - -This is the first release of DUMB, and parts of the library are not -crystallised. Don't let this put you off! Provided you don't try to use any -features that aren't documented in docs/dumb.txt, the library should be rock -solid and you should be able to upgrade more or less without problems. - -Here are some notes on this release: - -- There is some non-portable code in this release of DUMB. It is likely that - the library will fail to load IT files with compressed samples on - big-endian machines such as the Apple Macintosh. - -- If your program ever aborts with exit code 37 while loading an IT file, - PLEASE LET ME KNOW! The IT file in question has a stereo compressed sample - in it, and the format is unspecified for this case (Impulse Tracker itself - doesn't use stereo samples at all). I will need the IT file in question, - and any information you can give me about how the IT file was created (e.g. - what program). (If you don't get to see an exit code, let me know anyway.) - -- If your program ever outputs a line resembling "Inst 01 Env: 0,64 8,32 - 15,48" to stderr while loading an IT file, PLEASE LET ME KNOW! You have an - old IT file (saved by an Impulse Tracker version older than 2.00), and - support for such files is untested. - -- The length of IT and S3M files is not currently calculated. It is just set - to ten minutes. diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index b3211c97994..248b8e1906a 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -117,7 +117,7 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks @@ -145,7 +145,7 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks @@ -175,7 +175,7 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -208,7 +208,7 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Plugins;..\..\Engine\libsrc\glad\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -406,16 +406,6 @@ - - - - - - - - - - @@ -428,44 +418,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index 0ba99424beb..d0259febd57 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -133,21 +133,9 @@ {6d9175c0-5e3a-4fb2-9913-7095f88ce3c3} - - {a802fa47-7106-4211-a0d0-6efe0502ad18} - - - {62f2fb98-c4e6-418e-aae5-1b02af4e6778} - - - {142a7891-9b20-4486-a6de-9cbb99c7e58a} - {f9e0871b-6f2f-4d4d-944a-205740a1d5b5} - - {2ea2e632-361c-49d6-b446-def5de8efb15} - {0d737144-e555-4eda-bc62-cc15d7e48657} @@ -771,36 +759,6 @@ Source Files\game - - Library Sources\AllegroPatches - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\almp3 - - - Library Sources\alogg - Library Sources\apeg @@ -837,120 +795,6 @@ Library Sources\apeg - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - - - Library Sources\DUMB - Library Sources\Hq2x @@ -1017,6 +861,12 @@ Source Files\media\audio + + Source Files + + + Source Files + @@ -1877,6 +1727,18 @@ Header Files\media\audio + + Header Files + + + Header Files + + + Header Files + + + Header Files + From 14a7bc1791fd130ecff4a4f2206719fe2b2146bf Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 2 Oct 2020 02:15:14 +0300 Subject: [PATCH 08/41] AudioCore: fixed notify_all() called after return statement --- Engine/media/audio/audio_core.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Engine/media/audio/audio_core.cpp b/Engine/media/audio/audio_core.cpp index d086cd0af2b..b39dc04add6 100644 --- a/Engine/media/audio/audio_core.cpp +++ b/Engine/media/audio/audio_core.cpp @@ -226,14 +226,16 @@ void audio_core_slot_configure(int slot_handle, float volume, float speed, float float audio_core_slot_get_pos_ms(int slot_handle) { std::lock_guard lk(g_acore.mixer_mutex_m); - return g_acore.slots_[slot_handle]->decoder_.GetPositionMs(); + auto pos = g_acore.slots_[slot_handle]->decoder_.GetPositionMs(); g_acore.mixer_cv.notify_all(); + return pos; } AudioCorePlayState audio_core_slot_get_play_state(int slot_handle) { std::lock_guard lk(g_acore.mixer_mutex_m); - return g_acore.slots_[slot_handle]->decoder_.GetPlayState(); + auto state = g_acore.slots_[slot_handle]->decoder_.GetPlayState(); g_acore.mixer_cv.notify_all(); + return state; } From bfc5b0a07b6c55044da8e3f0326dbb8de30ee566 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Mon, 2 Nov 2020 03:27:21 +0300 Subject: [PATCH 09/41] Replaced allegro's main() with SDL main() --- Engine/main/{main_allegro.cpp => main_sdl2.cpp} | 3 +-- Solutions/Engine.App/Engine.App.vcxproj | 10 +++++----- Solutions/Engine.App/Engine.App.vcxproj.filters | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) rename Engine/main/{main_allegro.cpp => main_sdl2.cpp} (74%) diff --git a/Engine/main/main_allegro.cpp b/Engine/main/main_sdl2.cpp similarity index 74% rename from Engine/main/main_allegro.cpp rename to Engine/main/main_sdl2.cpp index 5a43762f44e..351e43f8166 100644 --- a/Engine/main/main_allegro.cpp +++ b/Engine/main/main_sdl2.cpp @@ -1,7 +1,6 @@ -#include "allegro.h" +#include #include "main/main.h" int main(int argc, char *argv[]) { return ags_entry_point(argc, argv); } -END_OF_MAIN() diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 248b8e1906a..ab5e4b511ae 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -130,7 +130,7 @@ 4013; 4150; 4477 - Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) @@ -159,7 +159,7 @@ 4013; 4150; 4477 - Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) @@ -187,7 +187,7 @@ 4013; 4150; 4477 - Common.lib;alleg-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common.lib;alleg-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) @@ -221,7 +221,7 @@ 4013; 4150; 4477 - Common.lib;alleg-static-mt.lib;SDL2.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common.lib;alleg-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) @@ -430,7 +430,7 @@ - + diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index d0259febd57..f22c271d4d3 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -837,9 +837,6 @@ Source Files\ac\dynobj - - Source Files\main - Source Files\platform\windows @@ -867,6 +864,9 @@ Source Files + + Source Files\main + From 169203706cd48f9f941a58538a046559058cba24 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 15:14:51 +0300 Subject: [PATCH 10/41] SDL-based window management Based on the work of @sonneveld (Nick Sonneveld). --- Engine/ac/game.cpp | 24 +-- Engine/ac/global_game.cpp | 15 +- Engine/ac/sys_events.cpp | 55 +++++- Engine/ac/sys_events.h | 16 ++ Engine/debug/debug.cpp | 4 +- Engine/device/mousew32.cpp | 5 +- Engine/game/savegame.cpp | 3 +- Engine/gfx/ali3dogl.cpp | 22 +-- Engine/main/engine.cpp | 16 +- Engine/main/engine_setup.cpp | 3 +- Engine/main/graphics_mode.cpp | 9 +- Engine/main/main.cpp | 3 +- Engine/main/quit.cpp | 6 +- Engine/platform/android/acpland.cpp | 5 - Engine/platform/base/agsplatformdriver.cpp | 26 --- Engine/platform/base/agsplatformdriver.h | 20 --- Engine/platform/base/sys_main.cpp | 170 ++++++++++++++++++ Engine/platform/base/sys_main.h | 67 +++++++ Engine/platform/linux/acpllnx.cpp | 36 ---- Engine/platform/osx/acplmac.cpp | 5 - Engine/platform/windows/acplwin.cpp | 119 +----------- Engine/platform/windows/gfx/ali3dd3d.cpp | 29 +-- .../platform/windows/media/video/acwavi.cpp | 3 +- .../platform/windows/media/video/acwavi3d.cpp | 7 +- Engine/platform/windows/setup/winsetup.cpp | 12 +- Engine/platform/windows/win_ex_handling.cpp | 6 +- Solutions/Engine.App/Engine.App.vcxproj | 2 + .../Engine.App/Engine.App.vcxproj.filters | 6 + 28 files changed, 383 insertions(+), 311 deletions(-) create mode 100644 Engine/platform/base/sys_main.cpp create mode 100644 Engine/platform/base/sys_main.h diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index 611185429c8..91cbea7cff7 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -77,6 +77,7 @@ #include "main/graphics_mode.h" #include "main/main.h" #include "media/audio/audio_system.h" +#include "platform/base/sys_main.h" #include "plugin/agsplugin.h" #include "plugin/plugin_engine.h" #include "script/cc_error.h" @@ -823,7 +824,7 @@ const char *Game_GetName() { void Game_SetName(const char *newName) { strncpy(play.game_name, newName, 99); play.game_name[99] = 0; - set_window_title(play.game_name); + sys_window_set_title(play.game_name); } int Game_GetSkippingCutscene() @@ -1929,23 +1930,18 @@ void display_switch_out() ags_clear_input_buffer(); // Always unlock mouse when switching out from the game Mouse::UnlockFromWindow(); - platform->DisplaySwitchOut(); - platform->ExitFullscreenMode(); } +// Called when game looses input focus and must pause until focus is returned void display_switch_out_suspend() { - // this is only called if in SWITCH_PAUSE mode - //debug_script_warn("display_switch_out"); display_switch_out(); switching_away_from_game++; platform->PauseApplication(); - // allow background running temporarily to halt the sound - if (set_display_switch_mode(SWITCH_BACKGROUND) == -1) - set_display_switch_mode(SWITCH_BACKAMNESIA); + // TODO: find out if anything has to be done here for SDL backend { // stop the sound stuttering @@ -1958,8 +1954,6 @@ void display_switch_out_suspend() } } // -- AudioChannelsLock - platform->Delay(1000); - // restore the callbacks SetMultitasking(0); @@ -1970,19 +1964,13 @@ void display_switch_out_suspend() void display_switch_in() { switched_away = false; - if (gfxDriver) - { - DisplayMode mode = gfxDriver->GetDisplayMode(); - if (!mode.Windowed) - platform->EnterFullscreenMode(mode); - } - platform->DisplaySwitchIn(); ags_clear_input_buffer(); // If auto lock option is set, lock mouse to the game window if (usetup.mouse_auto_lock && scsystem.windowed) Mouse::TryLockToWindow(); } +// Called when game gets input focus and must resume after pause void display_switch_in_resume() { display_switch_in(); @@ -2001,6 +1989,8 @@ void display_switch_in_resume() if (gfxDriver && gfxDriver->UsesMemoryBackBuffer()) gfxDriver->ClearRectangle(0, 0, game.GetGameRes().Width - 1, game.GetGameRes().Height - 1, nullptr); + // TODO: find out if anything has to be done here for SDL backend + platform->ResumeApplication(); } diff --git a/Engine/ac/global_game.cpp b/Engine/ac/global_game.cpp index 66f595e543b..ea9cc97bb77 100644 --- a/Engine/ac/global_game.cpp +++ b/Engine/ac/global_game.cpp @@ -60,6 +60,7 @@ #include "main/game_file.h" #include "util/string_utils.h" #include "media/audio/audio_system.h" +#include "platform/base/sys_main.h" using namespace AGS::Common; @@ -774,18 +775,14 @@ void SetMultitasking (int mode) { if ((mode == 1) && (!scsystem.windowed)) mode = 0; + // Install engine callbacks for switching in and out the window if (mode == 0) { - if (set_display_switch_mode(SWITCH_PAUSE) == -1) - set_display_switch_mode(SWITCH_AMNESIA); - // install callbacks to stop the sound when switching away - set_display_switch_callback(SWITCH_IN, display_switch_in_resume); - set_display_switch_callback(SWITCH_OUT, display_switch_out_suspend); + sys_set_background_mode(false); + sys_evt_set_focus_callbacks(display_switch_in_resume, display_switch_out_suspend); } else { - if (set_display_switch_mode (SWITCH_BACKGROUND) == -1) - set_display_switch_mode(SWITCH_BACKAMNESIA); - set_display_switch_callback(SWITCH_IN, display_switch_in); - set_display_switch_callback(SWITCH_OUT, display_switch_out); + sys_set_background_mode(true); + sys_evt_set_focus_callbacks(display_switch_in, display_switch_out); } } diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index ddbe0d5105e..98e50cc216d 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -11,14 +11,14 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - +#include "ac/sys_events.h" +#include #include "core/platform.h" #include "ac/common.h" #include "ac/gamesetupstruct.h" #include "ac/gamestate.h" #include "ac/keycode.h" #include "ac/mouse.h" -#include "ac/sys_events.h" #include "device/mousew32.h" #include "platform/base/agsplatformdriver.h" #include "ac/timer.h" @@ -204,3 +204,54 @@ void ags_wait_until_keypress() } ags_getch(); } + + +// ---------------------------------------------------------------------------- +// EVENTS +// ---------------------------------------------------------------------------- +static void(*_on_quit_callback)(void) = nullptr; +static void(*_on_switchin_callback)(void) = nullptr; +static void(*_on_switchout_callback)(void) = nullptr; + +void sys_evt_set_quit_callback(void(*proc)(void)) { + _on_quit_callback = proc; +} + +void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void)) { + _on_switchin_callback = switch_in; + _on_switchout_callback = switch_out; +} + +void sys_evt_process_one(const SDL_Event &event) { + switch (event.type) { + // GENERAL + case SDL_QUIT: + if (_on_quit_callback) { + _on_quit_callback(); + } + break; + // WINDOW + case SDL_WINDOWEVENT: + switch (event.window.event) + { + case SDL_WINDOWEVENT_FOCUS_GAINED: + if (_on_switchin_callback) { + _on_switchin_callback(); + } + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + if (_on_switchout_callback) { + _on_switchout_callback(); + } + break; + } + break; + } +} + +void sys_evt_process_pending(void) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + sys_evt_process_one(event); + } +} diff --git a/Engine/ac/sys_events.h b/Engine/ac/sys_events.h index bc7dfee9d05..b05bddc3592 100644 --- a/Engine/ac/sys_events.h +++ b/Engine/ac/sys_events.h @@ -18,6 +18,8 @@ #ifndef __AGS_EE_AC__SYS_EVENTS_H #define __AGS_EE_AC__SYS_EVENTS_H +// Input handling +// int ags_getch (); int ags_kbhit (); int ags_iskeypressed (int keycode); @@ -33,4 +35,18 @@ void ags_clear_input_buffer(); // TODO: seriously not a good design, replace with event listening void ags_wait_until_keypress(); + +// Events. +// +union SDL_Event; +// Set engine callback for when quit event is received by the backend. +void sys_evt_set_quit_callback(void(*proc)(void)); +// Set engine callback for when input focus is received or lost by the window. +void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void)); + +// Process single event. +void sys_evt_process_one(const SDL_Event &event); +// Process all events in the backend's queue. +void sys_evt_process_pending(void); + #endif // __AGS_EE_AC__SYS_EVENTS_H diff --git a/Engine/debug/debug.cpp b/Engine/debug/debug.cpp index 3268fcab18c..4710495d5cf 100644 --- a/Engine/debug/debug.cpp +++ b/Engine/debug/debug.cpp @@ -28,7 +28,7 @@ #include "debug/messagebuffer.h" #include "main/config.h" #include "media/audio/audio_system.h" -#include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "plugin/plugin_engine.h" #include "script/script.h" #include "script/script_common.h" @@ -376,7 +376,7 @@ bool send_message_to_editor(const char *msg, const char *errorMsg) char messageToSend[STD_BUFFER_SIZE]; sprintf(messageToSend, "", msg); #if AGS_PLATFORM_OS_WINDOWS - sprintf(&messageToSend[strlen(messageToSend)], " %d ", (int)win_get_window()); + sprintf(&messageToSend[strlen(messageToSend)], " %d ", (int)sys_win_get_window()); #endif sprintf(&messageToSend[strlen(messageToSend)], " ", callStack.GetCStr()); if (errorMsg != nullptr) diff --git a/Engine/device/mousew32.cpp b/Engine/device/mousew32.cpp index b939916fe99..40305f5f897 100644 --- a/Engine/device/mousew32.cpp +++ b/Engine/device/mousew32.cpp @@ -45,6 +45,7 @@ #include "gfx/gfx_util.h" #include "main/graphics_mode.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "util/math.h" #if AGS_SIMULATE_RIGHT_CLICK #include "ac/sys_events.h" // j for ags_iskeypressed @@ -337,13 +338,13 @@ bool Mouse::IsLockedToWindow() bool Mouse::TryLockToWindow() { if (!LockedToWindow) - LockedToWindow = platform->LockMouseToWindow(); + LockedToWindow = sys_window_lock_mouse(true); return LockedToWindow; } void Mouse::UnlockFromWindow() { - platform->UnlockMouse(); + sys_window_lock_mouse(false); LockedToWindow = false; } diff --git a/Engine/game/savegame.cpp b/Engine/game/savegame.cpp index 006ef030f87..c26e423a1d4 100644 --- a/Engine/game/savegame.cpp +++ b/Engine/game/savegame.cpp @@ -44,6 +44,7 @@ #include "main/engine.h" #include "main/main.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "plugin/agsplugin.h" #include "plugin/plugin_engine.h" #include "script/script.h" @@ -542,7 +543,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data) // ensure that the current cursor is locked spriteset.Precache(game.mcurs[r_data.CursorID].pic); - set_window_title(play.game_name); + sys_window_set_title(play.game_name); update_polled_stuff_if_runtime(); diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index 42c2fbe90f9..e333d3f3b2a 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -24,6 +24,7 @@ #include "gfx/gfx_util.h" #include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "util/math.h" #include "ac/timer.h" @@ -365,24 +366,16 @@ bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) ios_create_screen(); ios_select_buffer(); #elif AGS_PLATFORM_OS_WINDOWS - if (mode.Windowed) - { - platform->AdjustWindowStyleForWindowed(); - } - else - { - if (platform->EnterFullscreenMode(mode)) - platform->AdjustWindowStyleForFullscreen(); - } + sys_window_set_style(mode.Windowed); // NOTE: adjust_window may leave task bar visible, so we do not use it for fullscreen mode - if (mode.Windowed && adjust_window(mode.Width, mode.Height) != 0) + if (mode.Windowed && !sys_window_set_size(mode.Width, mode.Height)) { set_allegro_error("Window size not supported"); return false; } - _hWnd = win_get_window(); + _hWnd = sys_win_get_window(); if (!(_hDC = GetDC(_hWnd))) return false; @@ -416,7 +409,6 @@ bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) } CreateDesktopScreen(mode.Width, mode.Height, mode.ColorDepth); - win_grab_input(); #elif AGS_PLATFORM_OS_LINUX if (!_have_window) { @@ -990,8 +982,6 @@ void OGLGraphicsDriver::CreateVirtualScreen() return; // create initial stage screen for plugin raw drawing _stageVirtualScreen = CreateStageScreen(0, _srcRect.GetSize()); - // we must set Allegro's screen pointer to **something** - screen = (BITMAP*)_stageVirtualScreen->GetAllegroBitmap(); } bool OGLGraphicsDriver::SetNativeSize(const Size &src_size) @@ -1023,7 +1013,7 @@ int OGLGraphicsDriver::GetDisplayDepthForNativeDepth(int native_color_depth) con IGfxModeList *OGLGraphicsDriver::GetSupportedModeList(int color_depth) { std::vector modes; - platform->GetSystemDisplayModes(modes); + sys_get_desktop_modes(modes); return new OGLDisplayModeList(modes); } @@ -1046,7 +1036,7 @@ void OGLGraphicsDriver::ReleaseDisplayMode() gfx_driver = nullptr; - platform->ExitFullscreenMode(); + sys_window_set_style(false); } void OGLGraphicsDriver::UnInit() diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index 1ec03de7d58..4fe8b43d3f0 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -65,6 +65,7 @@ #include "main/main.h" #include "main/main_allegro.h" #include "media/audio/audio_core.h" +#include "platform/base/sys_main.h" #include "platform/util/pe.h" #include "util/directory.h" #include "util/error.h" @@ -122,6 +123,8 @@ bool engine_init_allegro() user_hint); return false; } + + sys_main_init(); return true; } @@ -144,11 +147,10 @@ void engine_setup_window() Debug::Printf(kDbgMsg_Info, "Setting up window"); our_eip = -198; - set_window_title("Adventure Game Studio"); - set_close_button_callback (winclosehook); + sys_window_create("Adventure Game Studio", 320, 200, true); + sys_window_set_icon(); + sys_evt_set_quit_callback(winclosehook); our_eip = -197; - - platform->SetGameWindowIcon(); } // Starts up setup application, if capable. @@ -184,6 +186,7 @@ bool engine_run_setup(const String &exe_path, ConfigTree &cfg, int &app_res) // Just re-reading the config file seems to cause a caching // problem on Win9x, so let's restart the process. + sys_main_shutdown(); allegro_exit(); char quotedpath[MAX_PATH]; snprintf(quotedpath, MAX_PATH, "\"%s\"", exe_path.GetCStr()); @@ -511,7 +514,6 @@ int engine_load_game_data() if (!err) { proper_exit=1; - platform->FinishedUsingGraphicsMode(); display_game_file_error(err); return EXIT_ERROR; } @@ -540,7 +542,7 @@ int engine_check_register_game() void engine_init_title() { our_eip=-91; - set_window_title(game.gamename); + sys_window_set_title(game.gamename); Debug::Printf(kDbgMsg_Info, "Game title: '%s'", game.gamename); } @@ -698,7 +700,7 @@ int engine_init_sprites() HError err = spriteset.InitFile(SpriteCache::DefaultSpriteFileName, SpriteCache::DefaultSpriteIndexName); if (!err) { - platform->FinishedUsingGraphicsMode(); + sys_main_shutdown(); allegro_exit(); proper_exit=1; platform->DisplayAlert("Could not load sprite set file %s\n%s", diff --git a/Engine/main/engine_setup.cpp b/Engine/main/engine_setup.cpp index ba9780030da..01f606695e5 100644 --- a/Engine/main/engine_setup.cpp +++ b/Engine/main/engine_setup.cpp @@ -35,6 +35,7 @@ #include "main/engine_setup.h" #include "media/video/video.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" using namespace AGS::Common; using namespace AGS::Engine; @@ -285,7 +286,7 @@ void engine_post_gfxmode_mouse_setup(const DisplayMode &dm, const Size &init_des if (usetup.mouse_speed_def == kMouseSpeed_CurrentDisplay) { Size cur_desktop; - if (get_desktop_resolution(&cur_desktop.Width, &cur_desktop.Height) == 0) + if (sys_get_desktop_resolution(cur_desktop.Width, cur_desktop.Height) == 0) Mouse::SetSpeedUnit(Math::Max((float)cur_desktop.Width / (float)init_desktop.Width, (float)cur_desktop.Height / (float)init_desktop.Height)); } diff --git a/Engine/main/graphics_mode.cpp b/Engine/main/graphics_mode.cpp index 1c853bce8a7..5e551dc7f82 100644 --- a/Engine/main/graphics_mode.cpp +++ b/Engine/main/graphics_mode.cpp @@ -31,6 +31,7 @@ #include "main/graphics_mode.h" #include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" // Don't try to figure out the window size on the mac because the port resizes itself. #if AGS_PLATFORM_OS_MACOS || defined(ALLEGRO_SDL2) || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID @@ -92,7 +93,7 @@ DisplayModeSetup::DisplayModeSetup() Size get_desktop_size() { Size sz; - get_desktop_resolution(&sz.Width, &sz.Height); + sys_get_desktop_resolution(sz.Width, sz.Height); return sz; } @@ -448,7 +449,6 @@ bool simple_create_gfx_driver_and_init_mode(const String &gfx_driver_id, void display_gfx_mode_error(const Size &game_size, const ScreenSetup &setup, const int color_depth) { proper_exit=1; - platform->FinishedUsingGraphicsMode(); String main_error; ScreenSizeSetup scsz = setup.DisplayMode.ScreenSize; @@ -472,7 +472,7 @@ bool graphics_mode_init_any(const Size game_size, const ScreenSetup &setup, cons { // Log out display information Size device_size; - if (get_desktop_resolution(&device_size.Width, &device_size.Height) == 0) + if (sys_get_desktop_resolution(device_size.Width, device_size.Height) == 0) Debug::Printf("Device display resolution: %d x %d", device_size.Width, device_size.Height); else Debug::Printf(kDbgMsg_Error, "Unable to obtain device resolution"); @@ -673,7 +673,4 @@ void graphics_mode_shutdown() GfxFactory->Shutdown(); GfxFactory = nullptr; gfxDriver = nullptr; - - // Tell Allegro that we are no longer in graphics mode - set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); } diff --git a/Engine/main/main.cpp b/Engine/main/main.cpp index da9296a9462..0357574e465 100644 --- a/Engine/main/main.cpp +++ b/Engine/main/main.cpp @@ -37,7 +37,7 @@ #include "main/engine.h" #include "main/mainheader.h" #include "main/main.h" -#include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "ac/route_finder.h" #include "core/assetmanager.h" #include "util/directory.h" @@ -478,6 +478,7 @@ int ags_entry_point(int argc, char *argv[]) { { int result = initialize_engine(startup_opts); // TODO: refactor engine shutdown routine (must shutdown and delete everything started and created) + sys_main_shutdown(); allegro_exit(); platform->PostAllegroExit(); return result; diff --git a/Engine/main/quit.cpp b/Engine/main/quit.cpp index 3c8f6b40306..5e3667a9791 100644 --- a/Engine/main/quit.cpp +++ b/Engine/main/quit.cpp @@ -36,6 +36,7 @@ #include "gfx/graphicsdriver.h" #include "gfx/bitmap.h" #include "core/assetmanager.h" +#include "platform/base/sys_main.h" #include "plugin/plugin_engine.h" #include "media/audio/audio_system.h" @@ -97,7 +98,7 @@ void quit_check_dynamic_sprites(QuitReason qreason) void quit_shutdown_platform(QuitReason qreason) { // Be sure to unlock mouse on exit, or users will hate us - platform->UnlockMouse(); + sys_window_lock_mouse(false); platform->AboutToQuitGame(); our_eip = 9016; @@ -106,8 +107,6 @@ void quit_shutdown_platform(QuitReason qreason) quit_check_dynamic_sprites(qreason); - platform->FinishedUsingGraphicsMode(); - if (use_cdplayer) platform->ShutdownCDPlayer(); } @@ -286,6 +285,7 @@ void quit(const char *quitmsg) // release backed library // WARNING: no Allegro objects should remain in memory after this, // if their destruction is called later, program will crash! + sys_main_shutdown(); allegro_exit(); platform->PostAllegroExit(); diff --git a/Engine/platform/android/acpland.cpp b/Engine/platform/android/acpland.cpp index 596c4aae577..04f5ca7555d 100644 --- a/Engine/platform/android/acpland.cpp +++ b/Engine/platform/android/acpland.cpp @@ -52,7 +52,6 @@ struct AGSAndroid : AGSPlatformDriver { virtual eScriptSystemOSID GetSystemOSID(); virtual int InitializeCDPlayer(); virtual void PostAllegroExit(); - virtual void SetGameWindowIcon(); virtual void ShutdownCDPlayer(); virtual void WriteStdOut(const char *fmt, ...); virtual void WriteStdErr(const char *fmt, ...); @@ -708,10 +707,6 @@ void AGSAndroid::PostAllegroExit() { java_environment->DeleteGlobalRef(java_class); } -void AGSAndroid::SetGameWindowIcon() { - // do nothing -} - void AGSAndroid::WriteStdOut(const char *fmt, ...) { // TODO: this check should probably be done once when setting up output targets for logging diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index 6fc7a92d3eb..678480c3be4 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -48,15 +48,8 @@ AGSPlatformDriver *platform = nullptr; void AGSPlatformDriver::AboutToQuitGame() { } void AGSPlatformDriver::PostAllegroInit(bool windowed) { } void AGSPlatformDriver::AttachToParentConsole() { } -void AGSPlatformDriver::DisplaySwitchOut() { } -void AGSPlatformDriver::DisplaySwitchIn() { } void AGSPlatformDriver::PauseApplication() { } void AGSPlatformDriver::ResumeApplication() { } -void AGSPlatformDriver::GetSystemDisplayModes(std::vector &dms) { } -bool AGSPlatformDriver::EnterFullscreenMode(const DisplayMode &dm) { return true; } -bool AGSPlatformDriver::ExitFullscreenMode() { return true; } -void AGSPlatformDriver::AdjustWindowStyleForFullscreen() { } -void AGSPlatformDriver::AdjustWindowStyleForWindowed() { } void AGSPlatformDriver::RegisterGameWithGameExplorer() { } void AGSPlatformDriver::UnRegisterGameWithGameExplorer() { } void AGSPlatformDriver::PlayVideo(const char* name, int skip, int flags) {} @@ -112,36 +105,17 @@ void AGSPlatformDriver::YieldCPU() { //std::this_thread::yield(); } -void AGSPlatformDriver::InitialiseAbufAtStartup() -{ - // because loading the game file accesses abuf, it must exist - // No no no, David Blain, no magic here :P - //abuf = BitmapHelper::CreateBitmap(10,10,8); -} - -void AGSPlatformDriver::FinishedUsingGraphicsMode() -{ - // don't need to do anything on any OS except DOS -} - SetupReturnValue AGSPlatformDriver::RunSetup(const ConfigTree &cfg_in, ConfigTree &cfg_out) { return kSetup_Cancel; } -void AGSPlatformDriver::SetGameWindowIcon() { - // do nothing -} - int AGSPlatformDriver::ConvertKeycodeToScanCode(int keycode) { keycode -= ('A' - KEY_A); return keycode; } -bool AGSPlatformDriver::LockMouseToWindow() { return false; } -void AGSPlatformDriver::UnlockMouse() { } - //----------------------------------------------- // IOutputHandler implementation //----------------------------------------------- diff --git a/Engine/platform/base/agsplatformdriver.h b/Engine/platform/base/agsplatformdriver.h index 208d9afca62..5b1653f9bcb 100644 --- a/Engine/platform/base/agsplatformdriver.h +++ b/Engine/platform/base/agsplatformdriver.h @@ -84,12 +84,9 @@ struct AGSPlatformDriver virtual eScriptSystemOSID GetSystemOSID() = 0; virtual void GetSystemTime(ScriptDateTime*); virtual void PlayVideo(const char* name, int skip, int flags); - virtual void InitialiseAbufAtStartup(); virtual void PostAllegroInit(bool windowed); virtual void PostAllegroExit() = 0; - virtual void FinishedUsingGraphicsMode(); virtual SetupReturnValue RunSetup(const Common::ConfigTree &cfg_in, Common::ConfigTree &cfg_out); - virtual void SetGameWindowIcon(); // Formats message and writes to standard platform's output; // Always adds trailing '\n' after formatted string virtual void WriteStdOut(const char *fmt, ...); @@ -97,25 +94,11 @@ struct AGSPlatformDriver // Always adds trailing '\n' after formatted string virtual void WriteStdErr(const char *fmt, ...); virtual void YieldCPU(); - // Called when the game window is being switch out from - virtual void DisplaySwitchOut(); - // Called when the game window is being switch back to - virtual void DisplaySwitchIn(); // Called when the application is being paused completely (e.g. when player alt+tabbed from it). // This function should suspend any platform-specific realtime processing. virtual void PauseApplication(); // Called when the application is being resumed. virtual void ResumeApplication(); - // Returns a list of supported display modes - virtual void GetSystemDisplayModes(std::vector &dms); - // Switch to system fullscreen mode; store previous mode parameters - virtual bool EnterFullscreenMode(const Engine::DisplayMode &dm); - // Return back to the mode was before switching to fullscreen - virtual bool ExitFullscreenMode(); - // Adjust application window's parameters to suit fullscreen mode - virtual void AdjustWindowStyleForFullscreen(); - // Adjust application window's parameters to suit windowed mode - virtual void AdjustWindowStyleForWindowed(); virtual void RegisterGameWithGameExplorer(); virtual void UnRegisterGameWithGameExplorer(); virtual int ConvertKeycodeToScanCode(int keyCode); @@ -126,9 +109,6 @@ struct AGSPlatformDriver virtual int CDPlayerCommand(int cmdd, int datt) = 0; virtual void ShutdownCDPlayer() = 0; - virtual bool LockMouseToWindow(); - virtual void UnlockMouse(); - static AGSPlatformDriver *GetDriver(); // Set whether PrintMessage should output to stdout or stderr diff --git a/Engine/platform/base/sys_main.cpp b/Engine/platform/base/sys_main.cpp new file mode 100644 index 00000000000..340afc3dc40 --- /dev/null +++ b/Engine/platform/base/sys_main.cpp @@ -0,0 +1,170 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +#include "platform/base/sys_main.h" +#include +#include +#include "util/string.h" + +namespace ags = AGS::Common; + +// ---------------------------------------------------------------------------- +// INIT / SHUTDOWN +// ---------------------------------------------------------------------------- + +int sys_main_init(/*config*/) { + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); // TODO: backend log verbosity from config + + // TODO: setup these subsystems in config rather than keep hardcoded? + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) != 0) { + SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); + return -1; + } + return 0; +} + +void sys_main_shutdown() { + sys_window_destroy(); + SDL_Quit(); +} + +void sys_set_background_mode(bool on) { + // TODO: consider if we want any implementation here, and what... +} + + +// ---------------------------------------------------------------------------- +// DISPLAY UTILS +// ---------------------------------------------------------------------------- +const int DEFAULT_DISPLAY_INDEX = 0; // TODO: is this always right? + +int sys_get_desktop_resolution(int &width, int &height) { + SDL_Rect r; + if (SDL_GetDisplayBounds(DEFAULT_DISPLAY_INDEX, &r) != 0) { + SDL_Log("SDL_GetDisplayBounds failed: %s", SDL_GetError()); + return -1; + } + width = r.w; + height = r.h; + return 0; +} + +void sys_get_desktop_modes(std::vector &dms) { + SDL_DisplayMode mode; + const int display_id = DEFAULT_DISPLAY_INDEX; + const int count = SDL_GetNumDisplayModes(display_id); + dms.clear(); + for (int i = 0; i < count; ++i) { + if (SDL_GetDisplayMode(display_id, i, &mode) != 0) { + SDL_Log("SDL_GetDisplayMode failed: %s", SDL_GetError()); + continue; + } + AGS::Engine::DisplayMode dm; + dm.Width = mode.w; + dm.Height = mode.h; + dm.ColorDepth = SDL_BITSPERPIXEL(mode.format); + dm.RefreshRate = mode.refresh_rate; + dms.push_back(dm); + } +} + + +// ---------------------------------------------------------------------------- +// WINDOW UTILS +// ---------------------------------------------------------------------------- +// TODO: support multiple windows? in case we need some for diag purposes etc +static SDL_Window *window = nullptr; + +SDL_Window *sys_window_create(const char *window_title, int w, int h, bool windowed, int ex_flags) { + if (window) { + sys_window_destroy(); + } + // TODO: support display index selection (?) + // TODO: support separate fullscreen and desktop (borderless fullscreen window) modes + // TODO: support resizable window later, might need callback for engine and/or gfx renderer + Uint32 flags = 0u/*SDL_WINDOW_RESIZABLE*/; + if (!windowed) { + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP/*SDL_WINDOW_FULLSCREEN*/; + } + flags |= ex_flags; + window = SDL_CreateWindow( + window_title, + SDL_WINDOWPOS_CENTERED_DISPLAY(DEFAULT_DISPLAY_INDEX), + SDL_WINDOWPOS_CENTERED_DISPLAY(DEFAULT_DISPLAY_INDEX), + w, + h, + flags + ); + return window; +} + +SDL_Window *get_window() { + return window; +} + +void sys_window_set_style(bool windowed) { + if (!window) return; + // TODO: support separate fullscreen and desktop (borderless fullscreen window) modes + // TODO: support resizable window later, might need callback for engine and/or gfx renderer + SDL_SetWindowFullscreen(window, windowed ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); +} + +bool sys_window_lock_mouse(bool on) { + if (!window) return false; + SDL_SetWindowGrab(window, static_cast(on)); + return on; // TODO: test if successful? +} + +void sys_window_destroy() { + if (window) { + SDL_DestroyWindow(window); + window = nullptr; + } +} + +void sys_window_set_title(const char *title) { + if (window) { + SDL_SetWindowTitle(window, title); + } +} + +void sys_window_set_icon() { + if (window) { + // TODO: actually support getting icon from resources and converting into SDL_Surface. + // - on Linux we had platform/linux/icon.xpm + // - on Windows we had standard embedded resource under ID = 101 + SDL_SetWindowIcon(window, nullptr); + } +} + +bool sys_window_set_size(int w, int h) { + if (window) { + SDL_SetWindowSize(window, w, h); + int new_w, new_h; + SDL_GetWindowSize(window, &new_w, &new_h); + return new_w == w && new_h == h; + } + return false; +} + +#if AGS_PLATFORM_OS_WINDOWS +void* sys_win_get_window() +{ + if (!window) return nullptr; + SDL_SysWMinfo wmInfo; + SDL_VERSION(&wmInfo.version); + SDL_GetWindowWMInfo(window, &wmInfo); + HWND hwnd = wmInfo.info.win.window; + return hwnd; +} +#endif diff --git a/Engine/platform/base/sys_main.h b/Engine/platform/base/sys_main.h new file mode 100644 index 00000000000..719db88e34f --- /dev/null +++ b/Engine/platform/base/sys_main.h @@ -0,0 +1,67 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +// +// The main backend interface. +// +// TODO: split up later if it gets filled with functions in all categories. +// +//============================================================================= +#include "core/platform.h" +#include +#include "gfx/gfxdefines.h" + +// Initializes main backend system; +// should be called before anything else backend related. +// Returns 0 on success, non-0 on failure. +int sys_main_init(/*config*/); +// Shutdown main backend system; +// should be called last, after everything else backend related is shutdown. +void sys_main_shutdown(); +// Sets whether the engine wants to update while the window has no focus. +// TODO: this is a placeholder at the moment, check later if we need any implementation +void sys_set_background_mode(bool on); + +// Display utilities. +// +// Queries current desktop resolution. +int sys_get_desktop_resolution(int &width, int &height); +// Queries supported desktop modes. +void sys_get_desktop_modes(std::vector &dms); + +// Window utilities. +// +struct SDL_Window; +// Create a new single game window. +SDL_Window *sys_window_create(const char *window_title, int w, int h, bool windowed, int ex_flags = 0); +// Returns current game window, if one exists, or null. +SDL_Window *get_window(); +// Sets current window style, does nothing if window was not created. +void sys_window_set_style(bool windowed); +// Locks on unlocks mouse inside the window. +// Returns new state of the mouse lock. +bool sys_window_lock_mouse(bool on); +// Destroy current game window, if one exists. +void sys_window_destroy(); +// Set window title text. +void sys_window_set_title(const char *title); +// Set window icon. +// TODO: this is a placeholder, until we figure out the best way to set icon with SDL on wanted systems. +void sys_window_set_icon(); +// Set window size. +bool sys_window_set_size(int w, int h); + +#if AGS_PLATFORM_OS_WINDOWS +// Returns game window's handle. +void* sys_win_get_window(); +#endif diff --git a/Engine/platform/linux/acpllnx.cpp b/Engine/platform/linux/acpllnx.cpp index 07297a9fdff..623cdefbea4 100644 --- a/Engine/platform/linux/acpllnx.cpp +++ b/Engine/platform/linux/acpllnx.cpp @@ -34,10 +34,6 @@ using AGS::Common::String; -// Replace the default Allegro icon. The original defintion is in the -// Allegro 4.4 source under "src/x/xwin.c". -#include "icon.xpm" -void* allegro_icon = icon_xpm; String CommonDataDirectory; String UserDataDirectory; @@ -56,11 +52,7 @@ struct AGSLinux : AGSPlatformDriver { eScriptSystemOSID GetSystemOSID() override; int InitializeCDPlayer() override; void PostAllegroExit() override; - void SetGameWindowIcon() override; void ShutdownCDPlayer() override; - bool LockMouseToWindow() override; - void UnlockMouse() override; - void GetSystemDisplayModes(std::vector &dms) override; }; @@ -170,10 +162,6 @@ void AGSLinux::PostAllegroExit() { // do nothing } -void AGSLinux::SetGameWindowIcon() { - // do nothing -} - void AGSLinux::ShutdownCDPlayer() { cd_exit(); } @@ -184,28 +172,4 @@ AGSPlatformDriver* AGSPlatformDriver::GetDriver() { return instance; } -bool AGSLinux::LockMouseToWindow() -{ - return XGrabPointer(_xwin.display, _xwin.window, False, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime) == GrabSuccess; -} - -void AGSLinux::UnlockMouse() -{ - XUngrabPointer(_xwin.display, CurrentTime); -} - -void AGSLinux::GetSystemDisplayModes(std::vector &dms) -{ - dms.clear(); - GFX_MODE_LIST *gmlist = get_gfx_mode_list(GFX_XWINDOWS_FULLSCREEN); - for (int i = 0; i < gmlist->num_modes; ++i) - { - const GFX_MODE &m = gmlist->mode[i]; - dms.push_back(Engine::DisplayMode(Engine::GraphicResolution(m.width, m.height, m.bpp))); - } - destroy_gfx_mode_list(gmlist); -} - #endif diff --git a/Engine/platform/osx/acplmac.cpp b/Engine/platform/osx/acplmac.cpp index 64c590a6517..246c9279eb7 100644 --- a/Engine/platform/osx/acplmac.cpp +++ b/Engine/platform/osx/acplmac.cpp @@ -48,7 +48,6 @@ struct AGSMac : AGSPlatformDriver { virtual eScriptSystemOSID GetSystemOSID() override; virtual int InitializeCDPlayer() override; virtual void PostAllegroExit() override; - virtual void SetGameWindowIcon() override; virtual void ShutdownCDPlayer() override; virtual const char *GetUserSavedgamesDirectory() override; @@ -107,10 +106,6 @@ void AGSMac::PostAllegroExit() { // do nothing } -void AGSMac::SetGameWindowIcon() { - // do nothing -} - void AGSMac::ShutdownCDPlayer() { //cd_exit(); } diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index 6efcfc43140..afbca81d6f3 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -33,6 +33,7 @@ #include "gfx/bitmap.h" #include "main/engine.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "platform/windows/setup/winsetup.h" #include "plugin/agsplugin.h" #include "util/file.h" @@ -118,25 +119,15 @@ struct AGSWin32 : AGSPlatformDriver { virtual void PostAllegroInit(bool windowed); virtual void PostAllegroExit(); virtual SetupReturnValue RunSetup(const ConfigTree &cfg_in, ConfigTree &cfg_out); - virtual void SetGameWindowIcon(); virtual void ShutdownCDPlayer(); virtual void WriteStdOut(const char *fmt, ...); virtual void WriteStdErr(const char *fmt, ...); - virtual void DisplaySwitchOut(); - virtual void DisplaySwitchIn(); virtual void PauseApplication(); virtual void ResumeApplication(); - virtual void GetSystemDisplayModes(std::vector &dms); - virtual bool EnterFullscreenMode(const Engine::DisplayMode &dm); - virtual bool ExitFullscreenMode(); - virtual void AdjustWindowStyleForFullscreen(); - virtual void AdjustWindowStyleForWindowed(); virtual void RegisterGameWithGameExplorer(); virtual void UnRegisterGameWithGameExplorer(); virtual int ConvertKeycodeToScanCode(int keyCode); virtual void ValidateWindowSize(int &x, int &y, bool borderless) const; - virtual bool LockMouseToWindow(); - virtual void UnlockMouse(); #ifndef AGS_NO_VIDEO_PLAYER virtual void PlayVideo(const char* name, int skip, int flags); @@ -153,10 +144,7 @@ struct AGSWin32 : AGSPlatformDriver { void register_file_extension(const char *exePath); void unregister_file_extension(); - bool SetSystemDisplayMode(const DisplayMode &dm, bool fullscreen); - bool _isDebuggerPresent; // indicates if the win app is running in the context of a debugger - DisplayMode _preFullscreenMode; // saved display mode before switching system to fullscreen bool _isAttachedToParentConsole; // indicates if the win app is attached to the parent console }; @@ -734,19 +722,6 @@ const char *AGSWin32::GetGraphicsTroubleshootingText() "Run DXDiag using the Run command (Start->Run, type \"dxdiag.exe\") and correct any problems reported there."; } -void AGSWin32::DisplaySwitchOut() -{ - // If we have explicitly set up fullscreen mode then minimize the window - if (_preFullscreenMode.IsValid()) - ShowWindow(win_get_window(), SW_MINIMIZE); -} - -void AGSWin32::DisplaySwitchIn() { - // If we have explicitly set up fullscreen mode then restore the window - if (_preFullscreenMode.IsValid()) - ShowWindow(win_get_window(), SW_RESTORE); -} - void AGSWin32::PauseApplication() { #ifndef AGS_NO_VIDEO_PLAYER @@ -761,71 +736,6 @@ void AGSWin32::ResumeApplication() #endif } -void AGSWin32::GetSystemDisplayModes(std::vector &dms) -{ - dms.clear(); - GFX_MODE_LIST *gmlist = get_gfx_mode_list(GFX_DIRECTX); - for (int i = 0; i < gmlist->num_modes; ++i) - { - const GFX_MODE &m = gmlist->mode[i]; - dms.push_back(DisplayMode(GraphicResolution(m.width, m.height, m.bpp))); - } - destroy_gfx_mode_list(gmlist); -} - -bool AGSWin32::SetSystemDisplayMode(const DisplayMode &dm, bool fullscreen) -{ - DEVMODE devmode; - memset(&devmode, 0, sizeof(devmode)); - devmode.dmSize = sizeof(devmode); - devmode.dmPelsWidth = dm.Width; - devmode.dmPelsHeight = dm.Height; - devmode.dmBitsPerPel = dm.ColorDepth; - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - return ChangeDisplaySettings(&devmode, fullscreen ? CDS_FULLSCREEN : 0) == DISP_CHANGE_SUCCESSFUL; -} - -bool AGSWin32::EnterFullscreenMode(const DisplayMode &dm) -{ - // Remember current mode - get_desktop_resolution(&_preFullscreenMode.Width, &_preFullscreenMode.Height); - _preFullscreenMode.ColorDepth = desktop_color_depth(); - - // Set requested desktop mode - return SetSystemDisplayMode(dm, true); -} - -bool AGSWin32::ExitFullscreenMode() -{ - if (!_preFullscreenMode.IsValid()) - return false; - - DisplayMode dm = _preFullscreenMode; - _preFullscreenMode = DisplayMode(); - return SetSystemDisplayMode(dm, false); -} - -void AGSWin32::AdjustWindowStyleForFullscreen() -{ - // Remove the border in full-screen mode - Size sz; - get_desktop_resolution(&sz.Width, &sz.Height); - HWND allegro_wnd = win_get_window(); - LONG winstyle = GetWindowLong(allegro_wnd, GWL_STYLE); - SetWindowLong(allegro_wnd, GWL_STYLE, (winstyle & ~WS_OVERLAPPEDWINDOW) | WS_POPUP); - SetWindowPos(allegro_wnd, HWND_TOP, 0, 0, sz.Width, sz.Height, 0); -} - -void AGSWin32::AdjustWindowStyleForWindowed() -{ - // Make a regular window with a border - HWND allegro_wnd = win_get_window(); - LONG winstyle = GetWindowLong(allegro_wnd, GWL_STYLE); - SetWindowLong(allegro_wnd, GWL_STYLE, (winstyle & ~WS_POPUP) | (WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX)); - // Make window go on top, but at the same time remove WS_EX_TOPMOST style (applied by Direct3D fullscreen mode) - SetWindowPos(allegro_wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); -} - int AGSWin32::CDPlayerCommand(int cmdd, int datt) { #if defined (AGS_HAS_CD_AUDIO) return cd_player_control(cmdd, datt); @@ -868,7 +778,7 @@ void AGSWin32::DisplayAlert(const char *text, ...) { vsprintf(displbuf, text, ap); va_end(ap); if (_guiMode) - MessageBox(win_get_window(), displbuf, "Adventure Game Studio", MB_OK | MB_ICONEXCLAMATION); + MessageBox((HWND)sys_win_get_window(), displbuf, "Adventure Game Studio", MB_OK | MB_ICONEXCLAMATION); // Always write to either stderr or stdout, even if message boxes are enabled. if (_logToStdErr) @@ -991,10 +901,6 @@ SetupReturnValue AGSWin32::RunSetup(const ConfigTree &cfg_in, ConfigTree &cfg_ou return AGS::Engine::WinSetup(cfg_in, cfg_out, usetup.data_files_dir, version_str); } -void AGSWin32::SetGameWindowIcon() { - SetWinIcon(); -} - void AGSWin32::WriteStdOut(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -1062,7 +968,7 @@ void AGSWin32::ValidateWindowSize(int &x, int &y, bool borderless) const // This is the maximal size that OS can reliably resize the window to (including any frame) const Size max_win(GetSystemMetrics(SM_CXMAXTRACK), GetSystemMetrics(SM_CYMAXTRACK)); // This is the size of window's non-client area (frame, caption, etc) - HWND allegro_wnd = win_get_window(); + HWND allegro_wnd = (HWND)sys_win_get_window(); LONG winstyle = borderless ? WS_POPUP : WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX; LONG winstyle_al = GetWindowLong(allegro_wnd, GWL_STYLE); SetRectEmpty(&nc_rc); @@ -1075,23 +981,6 @@ void AGSWin32::ValidateWindowSize(int &x, int &y, bool borderless) const y = Math::Clamp(y, 1, (int)(wa_rc.bottom - wa_rc.top)); } -bool AGSWin32::LockMouseToWindow() -{ - RECT rc; - HWND allegro_wnd = win_get_window(); - GetClientRect(allegro_wnd, &rc); - ClientToScreen(allegro_wnd, (POINT*)&rc); - ClientToScreen(allegro_wnd, (POINT*)&rc.right); - --rc.right; - --rc.bottom; - return ::ClipCursor(&rc) != 0; -} - -void AGSWin32::UnlockMouse() -{ - ::ClipCursor(NULL); -} - AGSPlatformDriver* AGSPlatformDriver::GetDriver() { if (instance == NULL) instance = new AGSWin32(); @@ -1102,7 +991,7 @@ AGSPlatformDriver* AGSPlatformDriver::GetDriver() { // *********** WINDOWS-SPECIFIC PLUGIN API FUNCTIONS ************* HWND IAGSEngine::GetWindowHandle () { - return win_get_window(); + return (HWND)sys_win_get_window(); } LPDIRECTDRAW2 IAGSEngine::GetDirectDraw2 () { if (directdraw == NULL) diff --git a/Engine/platform/windows/gfx/ali3dd3d.cpp b/Engine/platform/windows/gfx/ali3dd3d.cpp index b96a10c798b..175d8c15733 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.cpp +++ b/Engine/platform/windows/gfx/ali3dd3d.cpp @@ -33,6 +33,7 @@ #include "gfx/gfx_util.h" #include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "util/library.h" #ifndef AGS_NO_VIDEO_PLAYER @@ -460,19 +461,13 @@ void D3DGraphicsDriver::initD3DDLL(const DisplayMode &mode) throw Ali3DException(get_allegro_error()); } - _enter_critical(); - d3d_mode_to_init = mode; - // Set the display mode in the window's thread - if (wnd_call_proc(wnd_create_device)) { - _exit_critical(); + if (wnd_create_device()) { throw Ali3DException(get_allegro_error()); } availableVideoMemory = direct3ddevice->GetAvailableTextureMem(); - _exit_critical(); - // Set up a fake allegro gfx driver so that things like // the allegro mouse handler still work if (mode.Windowed) @@ -656,13 +651,9 @@ int D3DGraphicsDriver::_resetDeviceIfNecessary() int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) { - HWND allegro_wnd = win_get_window(); - - if (mode.Windowed) - platform->AdjustWindowStyleForWindowed(); - else - platform->AdjustWindowStyleForFullscreen(); + sys_window_set_style(mode.Windowed); + HWND hwnd = (HWND)sys_win_get_window(); memset( &d3dpp, 0, sizeof(d3dpp) ); d3dpp.BackBufferWidth = mode.Width; d3dpp.BackBufferHeight = mode.Height; @@ -671,7 +662,7 @@ int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; // THIS MUST BE SWAPEFFECT_COPY FOR PlayVideo TO WORK d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; //D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = allegro_wnd; + d3dpp.hDeviceWindow = hwnd; d3dpp.Windowed = mode.Windowed; d3dpp.EnableAutoDepthStencil = FALSE; d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; // we need this flag to access the backbuffer with lockrect @@ -697,7 +688,7 @@ int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) hr = ResetD3DDevice(); } else - hr = direct3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, allegro_wnd, + hr = direct3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, // multithreaded required for AVI player &d3dpp, &direct3ddevice); if (hr != D3D_OK) @@ -711,7 +702,7 @@ int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) if (mode.Windowed) { - if (adjust_window(mode.Width, mode.Height) != 0) + if (!sys_window_set_size(mode.Width, mode.Height)) { direct3ddevice->Release(); direct3ddevice = NULL; @@ -720,8 +711,6 @@ int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) } } - win_grab_input(); - if (first_time_init) { int ft_res = FirstTimeInit(); @@ -923,8 +912,6 @@ void D3DGraphicsDriver::CreateVirtualScreen() // create initial stage screen for plugin raw drawing _stageVirtualScreen = CreateStageScreen(0, _srcRect.GetSize()); - // we must set Allegro's screen pointer to **something** - screen = (BITMAP*)_stageVirtualScreen->GetAllegroBitmap(); } HRESULT D3DGraphicsDriver::ResetD3DDevice() @@ -1136,7 +1123,7 @@ void D3DGraphicsDriver::Render() void D3DGraphicsDriver::Render(int /*xoff*/, int /*yoff*/, GlobalFlipType /*flip*/) { - if (wnd_call_proc(wnd_reset_device)) + if (wnd_reset_device()) { throw Ali3DFullscreenLostException(); } diff --git a/Engine/platform/windows/media/video/acwavi.cpp b/Engine/platform/windows/media/video/acwavi.cpp index de682a80400..220695dfa09 100644 --- a/Engine/platform/windows/media/video/acwavi.cpp +++ b/Engine/platform/windows/media/video/acwavi.cpp @@ -36,6 +36,7 @@ #include "gfx/graphicsdriver.h" #include "main/game_run.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" using namespace AGS::Common; using namespace AGS::Engine; @@ -319,7 +320,7 @@ int dxmedia_play_video(const char* filename, bool pUseSound, int canskip, int st HRESULT hr; useSound = pUseSound; - ghWnd = win_get_window(); + ghWnd = (HWND)sys_win_get_window(); CoInitialize(NULL); diff --git a/Engine/platform/windows/media/video/acwavi3d.cpp b/Engine/platform/windows/media/video/acwavi3d.cpp index 79adf85b463..93ece2d7ed6 100644 --- a/Engine/platform/windows/media/video/acwavi3d.cpp +++ b/Engine/platform/windows/media/video/acwavi3d.cpp @@ -36,8 +36,7 @@ typedef float D3DVALUE, *LPD3DVALUE; #include "ac/common.h" #include "main/game_run.h" #include "media/video/VMR9Graph.h" -#include "platform/base/agsplatformdriver.h" -//#include +#include "platform/base/sys_main.h" #include "media/audio/audio_system.h" #define USES_CONVERSION int _convert = 0; _convert; UINT _acp = CP_ACP; _acp; LPCWSTR _lpw = NULL; _lpw; LPCSTR _lpa = NULL; _lpa @@ -82,7 +81,7 @@ void dxmedia_shutdown_3d() int dxmedia_play_video_3d(const char* filename, IDirect3DDevice9 *device, bool useAVISound, int canskip, int stretch) { - HWND gameWindow = win_get_window(); + HWND gameWindow = (HWND)sys_win_get_window(); if (graph == NULL) { @@ -635,7 +634,7 @@ BOOL CVMR9Graph::SetMediaFile(const char* pszFileName, bool withSound, int nLaye UseAVISound = withSound; m_pszFileName = pszFileName; - if (!wnd_call_proc(wndproc_build_filter_graph)) + if (!wndproc_build_filter_graph()) return FALSE; diff --git a/Engine/platform/windows/setup/winsetup.cpp b/Engine/platform/windows/setup/winsetup.cpp index e834fa93896..4b70a242793 100644 --- a/Engine/platform/windows/setup/winsetup.cpp +++ b/Engine/platform/windows/setup/winsetup.cpp @@ -36,6 +36,7 @@ #include "main/config.h" #include "main/graphics_mode.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "resource/resource.h" #include "util/file.h" #include "util/string_utils.h" @@ -52,11 +53,6 @@ #define MIDI_NONE 0 #define MIDI_WIN32MAPPER AL_ID('W','3','2','M') -extern "C" -{ - HWND win_get_window(); -} - namespace AGS { namespace Engine @@ -533,7 +529,7 @@ SetupReturnValue WinSetupDialog::ShowModal(const ConfigTree &cfg_in, ConfigTree const String &data_dir, const String &version_str) { _dlg = new WinSetupDialog(cfg_in, cfg_out, data_dir, version_str); - INT_PTR dlg_res = DialogBoxParam(GetModuleHandle(NULL), (LPCTSTR)IDD_SETUP, win_get_window(), + INT_PTR dlg_res = DialogBoxParam(GetModuleHandle(NULL), (LPCTSTR)IDD_SETUP, (HWND)sys_win_get_window(), (DLGPROC)WinSetupDialog::DialogProc, 0L); delete _dlg; _dlg = NULL; @@ -607,7 +603,7 @@ INT_PTR WinSetupDialog::OnInitDialog(HWND hwnd) _winCfg.GameResolution = ResolutionTypeToSize(_winCfg.GameResType, _winCfg.LetterboxByDesign); SetText(_hwnd, _winCfg.Title); - SetText(win_get_window(), _winCfg.Title); + SetText((HWND)sys_win_get_window(), _winCfg.Title); SetText(_hGameResolutionText, String::FromFormat("Native game resolution: %d x %d x %d", _winCfg.GameResolution.Width, _winCfg.GameResolution.Height, _winCfg.GameColourDepth)); @@ -1210,7 +1206,7 @@ void WinSetupDialog::UpdateMouseSpeedText() //============================================================================= void SetWinIcon() { - SetClassLong(win_get_window(),GCL_HICON, + SetClassLong((HWND)sys_win_get_window(), GCL_HICON, (LONG) LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON))); } diff --git a/Engine/platform/windows/win_ex_handling.cpp b/Engine/platform/windows/win_ex_handling.cpp index 27d56c67fe0..b521b831b4e 100644 --- a/Engine/platform/windows/win_ex_handling.cpp +++ b/Engine/platform/windows/win_ex_handling.cpp @@ -15,13 +15,13 @@ #if AGS_PLATFORM_OS_WINDOWS #include -#include -#include +#include #include "ac/common.h" #include "ac/common_defines.h" #include "debug/debugger.h" #include "debug/out.h" #include "main/main.h" +#include "platform/base/sys_main.h" #include "util/ini_util.h" #if !AGS_PLATFORM_DEBUG @@ -54,7 +54,7 @@ static void DisplayException() excinfo.ExceptionCode, (intptr_t)excinfo.ExceptionAddress, our_eip, EngineVersion.LongString.GetCStr(), eip_guinum, eip_guiobj, script_callstack.GetCStr(), (miniDumpResultCode == 0) ? "An error file CrashInfo.dmp has been created. You may be asked to upload this file when reporting this problem on the AGS Forums." : "Unable to create an error dump file.", miniDumpResultCode); - MessageBoxA(win_get_window(), printfworkingspace, "Illegal exception", MB_ICONSTOP | MB_OK); + MessageBoxA((HWND)sys_win_get_window(), printfworkingspace, "Illegal exception", MB_ICONSTOP | MB_OK); } int initialize_engine_with_exception_handling( diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index ab5e4b511ae..149f36411bc 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -443,6 +443,7 @@ + @@ -731,6 +732,7 @@ + diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index f22c271d4d3..eefd2d8eed2 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -867,6 +867,9 @@ Source Files\main + + Source Files\platform\base + @@ -1739,6 +1742,9 @@ Header Files + + Header Files\platform\base + From a659581579c79c2593890705f2a44e1512589df7 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 15:23:18 +0300 Subject: [PATCH 11/41] Disabled allegro system drivers and added SDL events polling Unfortunately, game processing is not fit for a single event poll, as game thread may be looping in a certain state for a while before returning to the main loop (such as running a dialog script, waiting for a blocking action to complete, etc). Fixing this is a task for another time. At the moment we are adding event polls into each sub-state. --- Engine/ac/dialog.cpp | 3 +++ Engine/ac/display.cpp | 2 ++ Engine/ac/invwindow.cpp | 3 +++ Engine/gui/cscidialog.cpp | 2 ++ Engine/main/engine.cpp | 14 +------------- Engine/main/game_run.cpp | 7 +++++++ 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Engine/ac/dialog.cpp b/Engine/ac/dialog.cpp index edd1f7d5f89..faf17054a84 100644 --- a/Engine/ac/dialog.cpp +++ b/Engine/ac/dialog.cpp @@ -849,6 +849,9 @@ void DialogOptions::Redraw() bool DialogOptions::Run() { + // Run() can be called in a loop, so keep events going. + sys_evt_process_pending(); + const bool new_custom_render = usingCustomRendering && game.options[OPT_DIALOGOPTIONSAPI] >= 0; if (runGameLoopsInBackground) diff --git a/Engine/ac/display.cpp b/Engine/ac/display.cpp index a0a32d9e4ae..2db2867b649 100644 --- a/Engine/ac/display.cpp +++ b/Engine/ac/display.cpp @@ -269,6 +269,8 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int int skip_setting = user_to_internal_skip_speech((SkipSpeechStyle)play.skip_display); // Loop until skipped while (true) { + sys_evt_process_pending(); + update_audio_system_on_game_loop(); render_graphics(); int mbut, mwheelz; diff --git a/Engine/ac/invwindow.cpp b/Engine/ac/invwindow.cpp index faffb294e01..f3bfbdc8f75 100644 --- a/Engine/ac/invwindow.cpp +++ b/Engine/ac/invwindow.cpp @@ -351,6 +351,9 @@ void InventoryScreen::RedrawOverItem(Bitmap *ds, int isonitem) bool InventoryScreen::Run() { + // Run() can be called in a loop, so keep events going. + sys_evt_process_pending(); + int kgn; if (run_service_key_controls(kgn) && !play.IsIgnoringInput()) { diff --git a/Engine/gui/cscidialog.cpp b/Engine/gui/cscidialog.cpp index c190bf3257e..98ec144c7b5 100644 --- a/Engine/gui/cscidialog.cpp +++ b/Engine/gui/cscidialog.cpp @@ -149,6 +149,8 @@ int CSCIWaitMessage(CSCIMessage * cscim) prepare_gui_screen(win_x, win_y, win_width, win_height, true); while (1) { + sys_evt_process_pending(); + update_audio_system_on_game_loop(); refresh_gui_screen(); diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index 4fe8b43d3f0..bdf76f800cb 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -114,7 +114,7 @@ bool engine_init_allegro() our_eip = -199; // Initialize allegro set_uformat(U_ASCII); - if (install_allegro(SYSTEM_AUTODETECT, &errno, atexit)) + if (install_allegro(SYSTEM_NONE, &errno, atexit)) { const char *al_err = get_allegro_error(); const char *user_hint = platform->GetAllegroFailUserHint(); @@ -128,14 +128,6 @@ bool engine_init_allegro() return true; } -void engine_setup_allegro() -{ - // Setup allegro using constructed config string - const char *al_config_data = "[mouse]\n" - "mouse_accel_factor = 0\n"; - override_config_data(al_config_data, ustrsize(al_config_data)); -} - void winclosehook() { want_exit = 1; abort_engine = 1; @@ -1284,7 +1276,6 @@ int initialize_engine(const ConfigTree &startup_opts) } // Set up game options from user config engine_set_config(cfg); - engine_setup_allegro(); engine_force_window(); our_eip = -190; @@ -1303,9 +1294,6 @@ int initialize_engine(const ConfigTree &startup_opts) our_eip = -193; - // Assign custom find resource callback for limited Allegro operations - system_driver->find_resource = al_find_resource; - //----------------------------------------------------- // Begin setting up systems engine_setup_window(); diff --git a/Engine/main/game_run.cpp b/Engine/main/game_run.cpp index ed2eb114eaf..24c838ef8a7 100644 --- a/Engine/main/game_run.cpp +++ b/Engine/main/game_run.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "ac/common.h" #include "ac/characterextras.h" #include "ac/characterinfo.h" @@ -550,6 +551,8 @@ static void check_keyboard_controls() static void check_controls() { our_eip = 1007; + sys_evt_process_pending(); + check_mouse_controls(); check_keyboard_controls(); } @@ -748,6 +751,8 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int int res; + sys_evt_process_pending(); + numEventsAtStartOfFunction = numevents; if (want_exit) { @@ -1030,6 +1035,8 @@ void RunGameUntilAborted() void update_polled_stuff_if_runtime() { + SDL_PumpEvents(); + if (want_exit) { want_exit = 0; quit("||exit!"); From 19317b75b2bd57b4beaf184c124880d44a746dad Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 15:30:26 +0300 Subject: [PATCH 12/41] Create and destroy SDL window in gfx driver class Based on the work of @sonneveld (Nick Sonneveld). Plans for the future refactoring: make gfx driver *return* SDL_Window it creates from SetDisplayMode(), and let engine save it as current render window. --- Common/game/main_game_file.cpp | 3 + Engine/gfx/ali3dogl.cpp | 64 +++--------- Engine/main/engine.cpp | 15 +-- Engine/platform/base/sys_main.cpp | 7 +- Engine/platform/base/sys_main.h | 6 +- Engine/platform/windows/gfx/ali3dd3d.cpp | 119 +++-------------------- 6 files changed, 41 insertions(+), 173 deletions(-) diff --git a/Common/game/main_game_file.cpp b/Common/game/main_game_file.cpp index 4dc54bf9941..8de219054d7 100644 --- a/Common/game/main_game_file.cpp +++ b/Common/game/main_game_file.cpp @@ -22,6 +22,7 @@ #include "ac/dynobj/scriptaudioclip.h" #include "core/asset.h" #include "core/assetmanager.h" +#include "debug/out.h" #include "game/main_game_file.h" #include "gui/guimain.h" #include "script/cc_error.h" @@ -714,6 +715,8 @@ HGameFileError ReadGameData(LoadedGameEntities &ents, Stream *in, GameDataVersio game.GameSetupStructBase::ReadFromFile(&align_s); } + Debug::Printf(kDbgMsg_Info, "Game title: '%s'", game.gamename); + if (game.GetGameRes().IsNull()) return new MainGameFileError(kMGFErr_InvalidNativeResolution); diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index e333d3f3b2a..d7c29521fdb 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -17,6 +17,7 @@ #if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_LINUX #include +#include #include "gfx/ali3dexception.h" #include "gfx/ali3dogl.h" #include "gfx/gfxfilter_ogl.h" @@ -121,48 +122,6 @@ namespace OGL using namespace AGS::Common; -void ogl_dummy_vsync() { } - -#define GFX_OPENGL AL_ID('O','G','L',' ') - -GFX_DRIVER gfx_opengl = -{ - GFX_OPENGL, - empty_string, - empty_string, - "OpenGL", - nullptr, // init - nullptr, // exit - nullptr, // AL_METHOD(int, scroll, (int x, int y)); - ogl_dummy_vsync, // vsync - nullptr, // setpalette - nullptr, // AL_METHOD(int, request_scroll, (int x, int y)); - nullptr, // AL_METHOD(int, poll_scroll, (void)); - nullptr, // AL_METHOD(void, enable_triple_buffer, (void)); - nullptr, //create_video_bitmap - nullptr, //destroy_video_bitmap - nullptr, //show_video_bitmap - nullptr, - nullptr, //gfx_directx_create_system_bitmap, - nullptr, //gfx_directx_destroy_system_bitmap, - nullptr, //gfx_directx_set_mouse_sprite, - nullptr, //gfx_directx_show_mouse, - nullptr, //gfx_directx_hide_mouse, - nullptr, //gfx_directx_move_mouse, - nullptr, // AL_METHOD(void, drawing_mode, (void)); - nullptr, // AL_METHOD(void, save_video_state, (void*)); - nullptr, // AL_METHOD(void, restore_video_state, (void*)); - nullptr, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); - nullptr, // AL_METHOD(int, fetch_mode_list, (void)); - 0, 0, // int w, h; - FALSE, // int linear; - 0, // long bank_size; - 0, // long bank_gran; - 0, // long vid_mem; - 0, // long vid_phys_base; - TRUE // int windowed; -}; - void OGLBitmap::Dispose() { if (_tiles != nullptr) @@ -366,13 +325,16 @@ bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) ios_create_screen(); ios_select_buffer(); #elif AGS_PLATFORM_OS_WINDOWS - sys_window_set_style(mode.Windowed); - - // NOTE: adjust_window may leave task bar visible, so we do not use it for fullscreen mode - if (mode.Windowed && !sys_window_set_size(mode.Width, mode.Height)) + SDL_Window* window = sys_get_window(); + if (window == nullptr || (SDL_GetWindowFlags(window) & SDL_WINDOW_OPENGL) == 0) { - set_allegro_error("Window size not supported"); - return false; + sys_window_create("", mode.Width, mode.Height, mode.Windowed, SDL_WINDOW_OPENGL); + } + else + { + sys_window_set_style(mode.Windowed); + if (mode.Windowed) + sys_window_set_size(mode.Width, mode.Height, true); } _hWnd = sys_win_get_window(); @@ -502,8 +464,6 @@ bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) CreateDesktopScreen(mode.Width, mode.Height, mode.ColorDepth); #endif - - gfx_driver = &gfx_opengl; return true; } @@ -1034,8 +994,6 @@ void OGLGraphicsDriver::ReleaseDisplayMode() DestroyFxPool(); DestroyAllStageScreens(); - gfx_driver = nullptr; - sys_window_set_style(false); } @@ -1052,6 +1010,8 @@ void OGLGraphicsDriver::UnInit() DeleteShaderProgram(_tintShader); DeleteShaderProgram(_lightShader); + + sys_window_destroy(); } OGLGraphicsDriver::~OGLGraphicsDriver() diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index bdf76f800cb..f2ed6230ae2 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -139,7 +139,7 @@ void engine_setup_window() Debug::Printf(kDbgMsg_Info, "Setting up window"); our_eip = -198; - sys_window_create("Adventure Game Studio", 320, 200, true); + sys_window_set_title(game.gamename); sys_window_set_icon(); sys_evt_set_quit_callback(winclosehook); our_eip = -197; @@ -531,13 +531,6 @@ int engine_check_register_game() return 0; } -void engine_init_title() -{ - our_eip=-91; - sys_window_set_title(game.gamename); - Debug::Printf(kDbgMsg_Info, "Game title: '%s'", game.gamename); -} - void engine_init_directories() { Debug::Printf(kDbgMsg_Info, "Data directory: %s", usetup.data_files_dir.GetCStr()); @@ -1296,7 +1289,6 @@ int initialize_engine(const ConfigTree &startup_opts) //----------------------------------------------------- // Begin setting up systems - engine_setup_window(); our_eip = -194; @@ -1343,8 +1335,6 @@ int initialize_engine(const ConfigTree &startup_opts) if (res != 0) return res; - engine_init_title(); - our_eip = -189; res = engine_check_disk_space(); @@ -1366,6 +1356,9 @@ int initialize_engine(const ConfigTree &startup_opts) if (!engine_try_set_gfxmode_any(usetup.Screen)) return EXIT_ERROR; + // Configure game window after renderer was initialized + engine_setup_window(); + SetMultitasking(0); // [ER] 2014-03-13 diff --git a/Engine/platform/base/sys_main.cpp b/Engine/platform/base/sys_main.cpp index 340afc3dc40..f12d5611f3c 100644 --- a/Engine/platform/base/sys_main.cpp +++ b/Engine/platform/base/sys_main.cpp @@ -14,6 +14,7 @@ #include "platform/base/sys_main.h" #include #include +#include "util/geometry.h" #include "util/string.h" namespace ags = AGS::Common; @@ -108,7 +109,7 @@ SDL_Window *sys_window_create(const char *window_title, int w, int h, bool windo return window; } -SDL_Window *get_window() { +SDL_Window *sys_get_window() { return window; } @@ -147,9 +148,11 @@ void sys_window_set_icon() { } } -bool sys_window_set_size(int w, int h) { +bool sys_window_set_size(int w, int h, bool center) { if (window) { SDL_SetWindowSize(window, w, h); + if (center) + SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); int new_w, new_h; SDL_GetWindowSize(window, &new_w, &new_h); return new_w == w && new_h == h; diff --git a/Engine/platform/base/sys_main.h b/Engine/platform/base/sys_main.h index 719db88e34f..644eac82bee 100644 --- a/Engine/platform/base/sys_main.h +++ b/Engine/platform/base/sys_main.h @@ -45,9 +45,11 @@ struct SDL_Window; // Create a new single game window. SDL_Window *sys_window_create(const char *window_title, int w, int h, bool windowed, int ex_flags = 0); // Returns current game window, if one exists, or null. -SDL_Window *get_window(); +SDL_Window *sys_get_window(); // Sets current window style, does nothing if window was not created. void sys_window_set_style(bool windowed); +// Set new window size; optionally center new window on screen +bool sys_window_set_size(int w, int h, bool center); // Locks on unlocks mouse inside the window. // Returns new state of the mouse lock. bool sys_window_lock_mouse(bool on); @@ -58,8 +60,6 @@ void sys_window_set_title(const char *title); // Set window icon. // TODO: this is a placeholder, until we figure out the best way to set icon with SDL on wanted systems. void sys_window_set_icon(); -// Set window size. -bool sys_window_set_size(int w, int h); #if AGS_PLATFORM_OS_WINDOWS // Returns game window's handle. diff --git a/Engine/platform/windows/gfx/ali3dd3d.cpp b/Engine/platform/windows/gfx/ali3dd3d.cpp index 175d8c15733..20cd26754be 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.cpp +++ b/Engine/platform/windows/gfx/ali3dd3d.cpp @@ -21,9 +21,7 @@ #if AGS_PLATFORM_OS_WINDOWS #include "platform/windows/gfx/ali3dd3d.h" - -#include -#include +#include #include "ac/timer.h" #include "debug/assert.h" #include "debug/out.h" @@ -169,88 +167,6 @@ bool D3DGfxModeList::GetMode(int index, DisplayMode &mode) const return false; } - -void dummy_vsync() { } - -#define GFX_DIRECT3D_WIN AL_ID('D','X','3','W') -#define GFX_DIRECT3D_FULL AL_ID('D','X','3','D') - -GFX_DRIVER gfx_direct3d_win = -{ - GFX_DIRECT3D_WIN, - empty_string, - empty_string, - "Direct3D windowed", - NULL, // init - NULL, // exit - NULL, // AL_METHOD(int, scroll, (int x, int y)); - dummy_vsync, // vsync - NULL, // setpalette - NULL, // AL_METHOD(int, request_scroll, (int x, int y)); - NULL, // AL_METHOD(int, poll_scroll, (void)); - NULL, // AL_METHOD(void, enable_triple_buffer, (void)); - NULL, //create_video_bitmap - NULL, //destroy_video_bitmap - NULL, //show_video_bitmap - NULL, - NULL, //gfx_directx_create_system_bitmap, - NULL, //gfx_directx_destroy_system_bitmap, - NULL, //gfx_directx_set_mouse_sprite, - NULL, //gfx_directx_show_mouse, - NULL, //gfx_directx_hide_mouse, - NULL, //gfx_directx_move_mouse, - NULL, // AL_METHOD(void, drawing_mode, (void)); - NULL, // AL_METHOD(void, save_video_state, (void*)); - NULL, // AL_METHOD(void, restore_video_state, (void*)); - NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); - NULL, // AL_METHOD(int, fetch_mode_list, (void)); - 0, 0, // int w, h; - FALSE, // int linear; - 0, // long bank_size; - 0, // long bank_gran; - 0, // long vid_mem; - 0, // long vid_phys_base; - TRUE // int windowed; -}; - -GFX_DRIVER gfx_direct3d_full = -{ - GFX_DIRECT3D_FULL, - empty_string, - empty_string, - "Direct3D fullscreen", - NULL, // init - NULL, // exit - NULL, // AL_METHOD(int, scroll, (int x, int y)); - dummy_vsync, // sync - NULL, // setpalette - NULL, // AL_METHOD(int, request_scroll, (int x, int y)); - NULL, // AL_METHOD(int, poll_scroll, (void)); - NULL, // AL_METHOD(void, enable_triple_buffer, (void)); - NULL, //create_video_bitmap - NULL, //destroy_video_bitmap - NULL, //show_video_bitmap - NULL, - NULL, //gfx_directx_create_system_bitmap, - NULL, //gfx_directx_destroy_system_bitmap, - NULL, //gfx_directx_set_mouse_sprite, - NULL, //gfx_directx_show_mouse, - NULL, //gfx_directx_hide_mouse, - NULL, //gfx_directx_move_mouse, - NULL, // AL_METHOD(void, drawing_mode, (void)); - NULL, // AL_METHOD(void, save_video_state, (void*)); - NULL, // AL_METHOD(void, restore_video_state, (void*)); - NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); - NULL, // AL_METHOD(int, fetch_mode_list, (void)); - 0, 0, // int w, h; - FALSE, // int linear; - 0, // long bank_size; - 0, // long bank_gran; - 0, // long vid_mem; - 0, // long vid_phys_base; - FALSE // int windowed; -}; - // The custom FVF, which describes the custom vertex structure. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) @@ -357,7 +273,7 @@ void D3DGraphicsDriver::ReleaseDisplayMode() DestroyFxPool(); DestroyAllStageScreens(); - gfx_driver = NULL; + sys_window_set_style(false); } int D3DGraphicsDriver::FirstTimeInit() @@ -468,13 +384,6 @@ void D3DGraphicsDriver::initD3DDLL(const DisplayMode &mode) availableVideoMemory = direct3ddevice->GetAvailableTextureMem(); - // Set up a fake allegro gfx driver so that things like - // the allegro mouse handler still work - if (mode.Windowed) - gfx_driver = &gfx_direct3d_win; - else - gfx_driver = &gfx_direct3d_full; - return; } @@ -651,7 +560,16 @@ int D3DGraphicsDriver::_resetDeviceIfNecessary() int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) { - sys_window_set_style(mode.Windowed); + if (sys_get_window() == nullptr) + { + sys_window_create("", mode.Width, mode.Height, mode.Windowed); + } + else + { + sys_window_set_style(mode.Windowed); + if (mode.Windowed) + sys_window_set_size(mode.Width, mode.Height, true); + } HWND hwnd = (HWND)sys_win_get_window(); memset( &d3dpp, 0, sizeof(d3dpp) ); @@ -700,17 +618,6 @@ int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) return -1; } - if (mode.Windowed) - { - if (!sys_window_set_size(mode.Width, mode.Height)) - { - direct3ddevice->Release(); - direct3ddevice = NULL; - set_allegro_error("Window size not supported"); - return -1; - } - } - if (first_time_init) { int ft_res = FirstTimeInit(); @@ -1006,6 +913,8 @@ void D3DGraphicsDriver::UnInit() direct3ddevice->Release(); direct3ddevice = NULL; } + + sys_window_destroy(); } D3DGraphicsDriver::~D3DGraphicsDriver() From 3148472ac94327fd9d617cb018413d0c33972e51 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:25:42 +0300 Subject: [PATCH 13/41] OGL, D3D: poll events during the looping fade-in/out effect --- Engine/gfx/ali3dogl.cpp | 2 ++ Engine/platform/windows/gfx/ali3dd3d.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index d7c29521fdb..192a2ec3625 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -1838,6 +1838,7 @@ void OGLGraphicsDriver::do_fade(bool fadingOut, int speed, int targetColourRed, d3db->SetTransparency(fadingOut ? a : (255 - a)); this->_render(false); + sys_evt_process_pending(); if (_pollingCallback) _pollingCallback(); WaitForNextFrame(); @@ -1918,6 +1919,7 @@ void OGLGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int delay) this->_render(false); + sys_evt_process_pending(); if (_pollingCallback) _pollingCallback(); platform->Delay(delay); diff --git a/Engine/platform/windows/gfx/ali3dd3d.cpp b/Engine/platform/windows/gfx/ali3dd3d.cpp index 20cd26754be..2c97fd74d6c 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.cpp +++ b/Engine/platform/windows/gfx/ali3dd3d.cpp @@ -22,13 +22,12 @@ #include "platform/windows/gfx/ali3dd3d.h" #include +#include "ac/sys_events.h" #include "ac/timer.h" -#include "debug/assert.h" #include "debug/out.h" #include "gfx/ali3dexception.h" #include "gfx/gfxfilter_d3d.h" #include "gfx/gfxfilter_aad3d.h" -#include "gfx/gfx_util.h" #include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" @@ -1744,6 +1743,7 @@ void D3DGraphicsDriver::do_fade(bool fadingOut, int speed, int targetColourRed, d3db->SetTransparency(fadingOut ? a : (255 - a)); this->_renderAndPresent(false); + sys_evt_process_pending(); if (_pollingCallback) _pollingCallback(); WaitForNextFrame(); @@ -1824,6 +1824,7 @@ void D3DGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int delay) this->_renderAndPresent(false); + sys_evt_process_pending(); if (_pollingCallback) _pollingCallback(); platform->Delay(delay); From 251c9347c268f429556d5c0465fb370062b266f2 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:26:18 +0300 Subject: [PATCH 14/41] OpenGL: use SDL GL functions for uniform desktop code Based on the work of @sonneveld (Nick Sonneveld). This simplifies the code and makes it uniform for Linux, Windows and MacOSX altogether. --- Engine/gfx/ali3dogl.cpp | 322 +++++++-------------------------------- Engine/gfx/ali3dogl.h | 19 +-- Engine/gfx/ogl_headers.h | 23 +-- 3 files changed, 73 insertions(+), 291 deletions(-) diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index 192a2ec3625..f609dc7d4c4 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -11,23 +11,21 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= +#include "gfx/ogl_headers.h" -#include "core/platform.h" - -#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_LINUX - +#if AGS_OPENGL_DRIVER +#include "gfx/ali3dogl.h" #include #include +#include "ac/sys_events.h" +#include "ac/timer.h" +#include "debug/out.h" #include "gfx/ali3dexception.h" -#include "gfx/ali3dogl.h" #include "gfx/gfxfilter_ogl.h" #include "gfx/gfxfilter_aaogl.h" -#include "gfx/gfx_util.h" #include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" -#include "util/math.h" -#include "ac/timer.h" #if AGS_PLATFORM_OS_ANDROID @@ -147,17 +145,8 @@ OGLGraphicsDriver::ShaderProgram::ShaderProgram() : Program(0), SamplerVar(0), C OGLGraphicsDriver::OGLGraphicsDriver() { #if AGS_PLATFORM_OS_WINDOWS - _hDC = NULL; - _hRC = NULL; - _hWnd = NULL; - _hInstance = NULL; - device_screen_physical_width = 0; - device_screen_physical_height = 0; -#elif AGS_PLATFORM_OS_LINUX device_screen_physical_width = 0; device_screen_physical_height = 0; - _glxContext = nullptr; - _have_window = false; #elif AGS_PLATFORM_OS_ANDROID device_screen_physical_width = android_screen_physical_width; device_screen_physical_height = android_screen_physical_height; @@ -209,12 +198,13 @@ void OGLGraphicsDriver::SetupDefaultVertices() defaultVertices[3].tv=1.0; } -#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX +#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_OS_MACOS -void OGLGraphicsDriver::CreateDesktopScreen(int width, int height, int depth) +void OGLGraphicsDriver::CreateDesktopScreen() { - device_screen_physical_width = width; - device_screen_physical_height = height; + SDL_GL_GetDrawableSize(_sdlWindow, &device_screen_physical_width, &device_screen_physical_height); + _mode.Width = device_screen_physical_width; + _mode.Height = device_screen_physical_height; } #elif AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS @@ -305,18 +295,6 @@ void OGLGraphicsDriver::FirstTimeInit() _firstTimeInit = true; } -#if AGS_PLATFORM_OS_LINUX -Atom get_x_atom (const char *atom_name) -{ - Atom atom = XInternAtom(_xwin.display, atom_name, False); - if (atom == None) - { - Debug::Printf(kDbgMsg_Error, "ERROR: X11 atom \"%s\" not found.\n", atom_name); - } - return atom; -} -#endif - bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) { #if AGS_PLATFORM_OS_ANDROID @@ -324,11 +302,12 @@ bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) #elif AGS_PLATFORM_OS_IOS ios_create_screen(); ios_select_buffer(); -#elif AGS_PLATFORM_OS_WINDOWS +#else SDL_Window* window = sys_get_window(); if (window == nullptr || (SDL_GetWindowFlags(window) & SDL_WINDOW_OPENGL) == 0) { - sys_window_create("", mode.Width, mode.Height, mode.Windowed, SDL_WINDOW_OPENGL); + if (!CreateWindowAndGlContext(mode)) + return false; } else { @@ -337,132 +316,7 @@ bool OGLGraphicsDriver::InitGlScreen(const DisplayMode &mode) sys_window_set_size(mode.Width, mode.Height, true); } - _hWnd = sys_win_get_window(); - if (!(_hDC = GetDC(_hWnd))) - return false; - - // First check if we need to recreate GL context, this will only be - // required if different color depth is requested. - if (_hRC) - { - GLuint pixel_fmt = GetPixelFormat(_hDC); - PIXELFORMATDESCRIPTOR pfd; - DescribePixelFormat(_hDC, pixel_fmt, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - if (pfd.cColorBits != mode.ColorDepth) - { - DeleteGlContext(); - } - } - - if (!_hRC) - { - if (!CreateGlContext(mode)) - return false; - } - - if (!gladLoadWGL(_hDC)) { - Debug::Printf(kDbgMsg_Error, "Failed to load WGL."); - return false; - } - - if (!gladLoadGL()) { - Debug::Printf(kDbgMsg_Error, "Failed to load GL."); - return false; - } - - CreateDesktopScreen(mode.Width, mode.Height, mode.ColorDepth); -#elif AGS_PLATFORM_OS_LINUX - if (!_have_window) - { - // Use Allegro to create our window. We don't care what size Allegro uses - // here, we will set that ourselves below by manipulating members of - // Allegro's_xwin structure. We need to use the Allegro routine here (rather - // than create our own X window) to remain compatible with Allegro's mouse & - // keyboard handling. - // - // Note that although _xwin contains a special "fullscreen" Window member - // (_xwin.fs_window), we do not use it for going fullscreen. Instead we ask - // the window manager to take the "managed" Window (_xwin.wm_window) - // fullscreen for us. All drawing goes to the "real" Window (_xwin.window). - if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 0, 0, 0, 0) != 0) - return false; - _have_window = true; - } - - if (!gladLoadGLX(_xwin.display, DefaultScreen(_xwin.display))) { - Debug::Printf(kDbgMsg_Error, "Failed to load GLX."); - return false; - } - - if (!_glxContext && !CreateGlContext(mode)) - return false; - - if(!gladLoadGL()) { - Debug::Printf(kDbgMsg_Error, "Failed to load GL."); - return false; - } - - { - // Set the size of our "managed" window. - XSizeHints *hints = XAllocSizeHints(); - - if (hints) - { - if (mode.Windowed) - { - // Set a fixed-size window. This is copied from Allegro 4's - // _xwin_private_create_screen(). - hints->flags = PMinSize | PMaxSize | PBaseSize; - hints->min_width = hints->max_width = hints->base_width = mode.Width; - hints->min_height = hints->max_height = hints->base_height = mode.Height; - } - else - { - // Clear any previously set demand for a fixed-size window, otherwise - // the window manager will ignore our request to go full-screen. - hints->flags = 0; - } - - XSetWMNormalHints(_xwin.display, _xwin.wm_window, hints); - } - - XFree(hints); - } - - // Set the window we are actually drawing into to the desired size. - XResizeWindow(_xwin.display, _xwin.window, mode.Width, mode.Height); - - // Make Allegro aware of the new window size, otherwise the mouse cursor - // movement may be erratic. - _xwin.window_width = mode.Width; - _xwin.window_height = mode.Height; - - { - // Ask the window manager to add (or remove) the "fullscreen" property on - // our top-level window. - const Atom wm_state = get_x_atom("_NET_WM_STATE"); - const Atom fullscreen = get_x_atom("_NET_WM_STATE_FULLSCREEN"); - const long remove_property = 0; - const long add_property = 1; - - XEvent xev; - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.xclient.window = _xwin.wm_window; - xev.xclient.message_type = wm_state; - xev.xclient.format = 32; - xev.xclient.data.l[0] = mode.Windowed ? remove_property : add_property; - xev.xclient.data.l[1] = fullscreen; - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 1; // Message source is a regular application. - Status status = XSendEvent(_xwin.display, DefaultRootWindow(_xwin.display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - if (status == 0) - { - Debug::Printf(kDbgMsg_Error, "ERROR: Failed to encode window state message.\n"); - } - } - - CreateDesktopScreen(mode.Width, mode.Height, mode.ColorDepth); + CreateDesktopScreen(); #endif return true; } @@ -496,31 +350,9 @@ void OGLGraphicsDriver::InitGlParams(const DisplayMode &mode) glEnableClientState(GL_TEXTURE_COORD_ARRAY); auto interval = mode.Vsync ? 1 : 0; - bool vsyncEnabled = false; - -#if AGS_PLATFORM_OS_WINDOWS - if (GLAD_WGL_EXT_swap_control) { - vsyncEnabled = wglSwapIntervalEXT(interval) != FALSE; - } -#endif - -#if AGS_PLATFORM_OS_LINUX - if (GLAD_GLX_EXT_swap_control) { - glXSwapIntervalEXT(_xwin.display, _xwin.window, interval); - // glx requires hooking into XSetErrorHandler to test for BadWindow or BadValue - vsyncEnabled = true; - } else if (GLAD_GLX_MESA_swap_control) { - vsyncEnabled = glXSwapIntervalMESA(interval) == 0; - } else if (GLAD_GLX_SGI_swap_control) { - vsyncEnabled = glXSwapIntervalSGI(interval) == 0; - } -#endif - - // TODO: find out how to implement SwapInterval on other platforms, and how to check if it's supported - - if (mode.Vsync && !vsyncEnabled) { + bool vsyncEnabled = SDL_GL_SetSwapInterval(mode.Vsync ? 1 : 0) == 0; + if (mode.Vsync && !vsyncEnabled) Debug::Printf(kDbgMsg_Warn, "WARNING: Vertical sync could not be enabled. Setting will be kept at driver default."); - } #if AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS // Setup library mouse to have 1:1 coordinate transformation. @@ -531,88 +363,59 @@ void OGLGraphicsDriver::InitGlParams(const DisplayMode &mode) #endif } -bool OGLGraphicsDriver::CreateGlContext(const DisplayMode &mode) +bool OGLGraphicsDriver::CreateWindowAndGlContext(const DisplayMode &mode) { -#if AGS_PLATFORM_OS_WINDOWS - PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), - 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, - (BYTE)mode.ColorDepth, - 0, 0, 0, 0, 0, 0, - 0, - 0, - 0, - 0, 0, 0, 0, - 0, - 0, - 0, - PFD_MAIN_PLANE, - 0, - 0, 0, 0 - }; - - _oldPixelFormat = GetPixelFormat(_hDC); - DescribePixelFormat(_hDC, _oldPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &_oldPixelFormatDesc); - - GLuint pixel_fmt; - if (!(pixel_fmt = ChoosePixelFormat(_hDC, &pfd))) - return false; + // First setup GL attributes before creating SDL GL window + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) != 0) + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Error occured setting attribute SDL_GL_CONTEXT_PROFILE_MASK: %s", SDL_GetError()); + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2) != 0) + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Error occured setting attribute SDL_GL_CONTEXT_MAJOR_VERSION: %s", SDL_GetError()); + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1) != 0) + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Error occured setting attribute SDL_GL_CONTEXT_MINOR_VERSION: %s", SDL_GetError()); + if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0) + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Error occured setting attribute SDL_GL_DOUBLEBUFFER: %s", SDL_GetError()); - if (!SetPixelFormat(_hDC, pixel_fmt, &pfd)) - return false; - - if (!(_hRC = wglCreateContext(_hDC))) + SDL_Window *sdl_window = sys_window_create("", mode.Width, mode.Height, mode.Windowed, SDL_WINDOW_OPENGL); + if (!sdl_window) + { + Debug::Printf(kDbgMsg_Error, "Error opening window for OpenGL: %s", SDL_GetError()); return false; + } - if(!wglMakeCurrent(_hDC, _hRC)) - return false; -#endif // AGS_PLATFORM_OS_WINDOWS -#if AGS_PLATFORM_OS_LINUX - int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; - XVisualInfo *vi = glXChooseVisual(_xwin.display, DefaultScreen(_xwin.display), attrib); - if (!vi) - { - Debug::Printf(kDbgMsg_Error, "ERROR: glXChooseVisual() failed.\n"); + SDL_GLContext sdlgl_ctx = SDL_GL_CreateContext(sdl_window); + if (sdlgl_ctx == NULL) { + Debug::Printf(kDbgMsg_Error, "Error creating OpenGL context: %s", SDL_GetError()); + sys_window_destroy(); return false; } - if (!(_glxContext = glXCreateContext(_xwin.display, vi, None, True))) - { - Debug::Printf(kDbgMsg_Error, "ERROR: glXCreateContext() failed.\n"); + if (SDL_GL_MakeCurrent(sdl_window, sdlgl_ctx) != 0) { + Debug::Printf(kDbgMsg_Error, "Error setting current OpenGL context: %s", SDL_GetError()); + SDL_GL_DeleteContext(sdlgl_ctx); + sys_window_destroy(); return false; } - if (!glXMakeCurrent(_xwin.display, _xwin.window, _glxContext)) - { - Debug::Printf(kDbgMsg_Error, "ERROR: glXMakeCurrent() failed.\n"); + if (!gladLoadGL()) { + Debug::Printf(kDbgMsg_Error, "Failed to load GL."); return false; } -#endif + + _sdlWindow = sdl_window; + _sdlGlContext = sdlgl_ctx; return true; } -void OGLGraphicsDriver::DeleteGlContext() +void OGLGraphicsDriver::DeleteWindowAndGlContext() { -#if AGS_PLATFORM_OS_WINDOWS - if (_hRC) - { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(_hRC); - _hRC = NULL; - } - - if (_oldPixelFormat > 0) - SetPixelFormat(_hDC, _oldPixelFormat, &_oldPixelFormatDesc); -#elif AGS_PLATFORM_OS_LINUX - if (_glxContext) - { - glXMakeCurrent(_xwin.display, None, nullptr); - glXDestroyContext(_xwin.display, _glxContext); - _glxContext = nullptr; +#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_OS_MACOS + SDL_GL_MakeCurrent(nullptr, nullptr); + if (_sdlGlContext) { + SDL_GL_DeleteContext(_sdlGlContext); } + _sdlGlContext = nullptr; + sys_window_destroy(); + _sdlWindow = nullptr; #endif } @@ -1002,15 +805,10 @@ void OGLGraphicsDriver::UnInit() OnUnInit(); ReleaseDisplayMode(); - DeleteGlContext(); -#if AGS_PLATFORM_OS_WINDOWS - _hWnd = NULL; - _hDC = NULL; -#endif - DeleteShaderProgram(_tintShader); DeleteShaderProgram(_lightShader); + DeleteWindowAndGlContext(); sys_window_destroy(); } @@ -1052,7 +850,7 @@ bool OGLGraphicsDriver::GetCopyOfScreenIntoBitmap(Bitmap *destination, bool at_n { #if AGS_PLATFORM_OS_IOS ios_select_buffer(); -#elif AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX +#else glReadBuffer(GL_FRONT); #endif retr_rect = _dstRect; @@ -1361,12 +1159,10 @@ void OGLGraphicsDriver::_render(bool clearDrawListAfterwards) glFinish(); -#if AGS_PLATFORM_OS_WINDOWS - SwapBuffers(_hDC); -#elif AGS_PLATFORM_OS_LINUX - glXSwapBuffers(_xwin.display, _xwin.window); -#elif AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS +#if AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS device_swap_buffers(); +#else + SDL_GL_SwapWindow(_sdlWindow); #endif if (clearDrawListAfterwards) @@ -2007,4 +1803,4 @@ OGLGfxFilter *OGLGraphicsFactory::CreateFilter(const String &id) } // namespace Engine } // namespace AGS -#endif // only on Windows, Android and iOS +#endif // AGS_OPENGL_DRIVER diff --git a/Engine/gfx/ali3dogl.h b/Engine/gfx/ali3dogl.h index 019073df14c..55cfff460e4 100644 --- a/Engine/gfx/ali3dogl.h +++ b/Engine/gfx/ali3dogl.h @@ -218,25 +218,18 @@ class OGLGraphicsDriver : public VideoMemoryGraphicsDriver POGLFilter _filter; #if AGS_PLATFORM_OS_WINDOWS - HDC _hDC; - HGLRC _hRC; - HWND _hWnd; - HINSTANCE _hInstance; - GLuint _oldPixelFormat; - PIXELFORMATDESCRIPTOR _oldPixelFormatDesc; #endif #if AGS_PLATFORM_OS_LINUX - bool _have_window; - GLXContext _glxContext; #endif bool _firstTimeInit; + SDL_Window *_sdlWindow = nullptr; + SDL_GLContext _sdlGlContext = nullptr; // Position of backbuffer texture in world space GLfloat _backbuffer_vertices[8]; // Relative position of source image on the backbuffer texture, // in local coordinates GLfloat _backbuffer_texture_coordinates[8]; OGLCUSTOMVERTEX defaultVertices[4]; - String previousError; bool _smoothScaling; bool _legacyPixelShader; // Shader program and its variable references; @@ -288,8 +281,8 @@ class OGLGraphicsDriver : public VideoMemoryGraphicsDriver void FirstTimeInit(); // Initializes Gl rendering context bool InitGlScreen(const DisplayMode &mode); - bool CreateGlContext(const DisplayMode &mode); - void DeleteGlContext(); + bool CreateWindowAndGlContext(const DisplayMode &mode); + void DeleteWindowAndGlContext(); // Sets up general rendering parameters void InitGlParams(const DisplayMode &mode); void SetupDefaultVertices(); @@ -308,8 +301,8 @@ class OGLGraphicsDriver : public VideoMemoryGraphicsDriver // Configure backbuffer texture, that is used in render-to-texture mode void SetupBackbufferTexture(); void DeleteBackbufferTexture(); -#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX - void CreateDesktopScreen(int width, int height, int depth); +#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_OS_MACOS + void CreateDesktopScreen(); #elif AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS void UpdateDeviceScreen(); #endif diff --git a/Engine/gfx/ogl_headers.h b/Engine/gfx/ogl_headers.h index 0e480acb1f4..47d3e0bdfec 100644 --- a/Engine/gfx/ogl_headers.h +++ b/Engine/gfx/ogl_headers.h @@ -18,22 +18,25 @@ #include "core/platform.h" +#define AGS_OPENGL_DRIVER (AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_OS_MACOS) + #if AGS_PLATFORM_OS_WINDOWS +#include #include #include -#include - #include "glad/glad.h" #include "glad/glad_wgl.h" #elif AGS_PLATFORM_OS_LINUX +#include #include -#include -#include - #include "glad/glad.h" #include "glad/glad_glx.h" +#elif AGS_PLATFORM_OS_MACOS +#include "SDL.h" +#include "glad/glad.h" + #elif AGS_PLATFORM_OS_ANDROID #include @@ -46,11 +49,6 @@ // TODO: we probably should not use GLExt since we use GLES2 #include -#define HDC void* -#define HGLRC void* -#define HWND void* -#define HINSTANCE void* - #elif AGS_PLATFORM_OS_IOS #include @@ -61,11 +59,6 @@ #include -#define HDC void* -#define HGLRC void* -#define HWND void* -#define HINSTANCE void* - #else #error "opengl: unsupported platform" From 0fddd6f927f860eab2f4c337924e7acd80489ba4 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:26:43 +0300 Subject: [PATCH 15/41] Rewrote Software renderer using SDL_Renderer Based on the work of @sonneveld (Nick Sonneveld). --- Engine/gfx/ali3dogl.cpp | 8 +- Engine/gfx/ali3dsw.cpp | 582 +++++++++--------- Engine/gfx/ali3dsw.h | 116 ++-- Engine/gfx/gfxdriverfactory.cpp | 4 +- Engine/gfx/gfxfilter_allegro.cpp | 172 ------ Engine/gfx/gfxfilter_allegro.h | 71 --- Engine/gfx/gfxfilter_hqx.cpp | 92 --- .../{hq2x3x.h => gfxfilter_sdl_renderer.cpp} | 28 +- ...xfilter_hqx.h => gfxfilter_sdl_renderer.h} | 32 +- Engine/main/graphics_mode.cpp | 4 - Solutions/Engine.App/Engine.App.vcxproj | 7 +- .../Engine.App/Engine.App.vcxproj.filters | 27 +- 12 files changed, 376 insertions(+), 767 deletions(-) delete mode 100644 Engine/gfx/gfxfilter_allegro.cpp delete mode 100644 Engine/gfx/gfxfilter_allegro.h delete mode 100644 Engine/gfx/gfxfilter_hqx.cpp rename Engine/gfx/{hq2x3x.h => gfxfilter_sdl_renderer.cpp} (53%) rename Engine/gfx/{gfxfilter_hqx.h => gfxfilter_sdl_renderer.h} (52%) diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index f609dc7d4c4..dc4b338646b 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -249,9 +249,13 @@ void OGLGraphicsDriver::RenderSpritesAtScreenResolution(bool enabled, int supers bool OGLGraphicsDriver::IsModeSupported(const DisplayMode &mode) { - if (mode.Width <= 0 || mode.Height <= 0 || mode.ColorDepth <= 0) + if (mode.Width <= 0 || mode.Height <= 0) { - set_allegro_error("Invalid resolution parameters: %d x %d x %d", mode.Width, mode.Height, mode.ColorDepth); + set_allegro_error("Invalid resolution parameters: %d x %d", mode.Width, mode.Height); + return false; + } + if (mode.ColorDepth != 32) { + set_allegro_error("Display colour depth not supported: %d", mode.ColorDepth); return false; } return true; diff --git a/Engine/gfx/ali3dsw.cpp b/Engine/gfx/ali3dsw.cpp index ddc09b3342b..49ee51aa8b7 100644 --- a/Engine/gfx/ali3dsw.cpp +++ b/Engine/gfx/ali3dsw.cpp @@ -11,37 +11,17 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= -// -// Allegro Interface for 3D; Software mode Allegro driver -// -//============================================================================= - #include "gfx/ali3dsw.h" - -#include "core/platform.h" +#include +#include "ac/sys_events.h" #include "gfx/ali3dexception.h" -#include "gfx/gfxfilter_allegro.h" -#include "gfx/gfxfilter_hqx.h" +#include "gfx/gfxfilter_sdl_renderer.h" #include "gfx/gfx_util.h" #include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" +#include "platform/base/sys_main.h" #include "ac/timer.h" -#if AGS_DDRAW_GAMMA_CONTROL -// NOTE: this struct and variables are defined internally in Allegro -typedef struct DDRAW_SURFACE { - LPDIRECTDRAWSURFACE2 id; - int flags; - int lock_nesting; - BITMAP *parent_bmp; - struct DDRAW_SURFACE *next; - struct DDRAW_SURFACE *prev; -} DDRAW_SURFACE; - -extern "C" extern LPDIRECTDRAW2 directdraw; -extern "C" DDRAW_SURFACE *gfx_directx_primary_surface; -#endif // AGS_DDRAW_GAMMA_CONTROL - #ifndef AGS_NO_VIDEO_PLAYER extern int dxmedia_play_video (const char*, bool, int, int); #endif @@ -55,82 +35,54 @@ namespace ALSW using namespace Common; -bool ALSoftwareGfxModeList::GetMode(int index, DisplayMode &mode) const -{ - if (_gfxModeList && index >= 0 && index < _gfxModeList->num_modes) - { - mode.Width = _gfxModeList->mode[index].width; - mode.Height = _gfxModeList->mode[index].height; - mode.ColorDepth = _gfxModeList->mode[index].bpp; - return true; - } - return false; -} - unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned long n); RGB faded_out_palette[256]; -ALSoftwareGraphicsDriver::ALSoftwareGraphicsDriver() +// ---------------------------------------------------------------------------- +// SDLRendererGraphicsDriver +// ---------------------------------------------------------------------------- + +#if SDL_VERSION_ATLEAST(2, 0, 5) +// used to add alpha back to rendered screen. +static auto fix_alpha_blender = SDL_ComposeCustomBlendMode( + SDL_BLENDFACTOR_ZERO, + SDL_BLENDFACTOR_ONE, + SDL_BLENDOPERATION_ADD, + SDL_BLENDFACTOR_ONE, + SDL_BLENDFACTOR_ZERO, + SDL_BLENDOPERATION_ADD +); +#endif + +SDLRendererGraphicsDriver::SDLRendererGraphicsDriver() { _tint_red = 0; _tint_green = 0; _tint_blue = 0; - _autoVsync = false; - //_spareTintingScreen = nullptr; - _gfxModeList = nullptr; -#if AGS_DDRAW_GAMMA_CONTROL - dxGammaControl = nullptr; -#endif - _allegroScreenWrapper = nullptr; _origVirtualScreen = nullptr; virtualScreen = nullptr; _stageVirtualScreen = nullptr; // Initialize default sprite batch, it will be used when no other batch was activated - ALSoftwareGraphicsDriver::InitSpriteBatch(0, _spriteBatchDesc[0]); + SDLRendererGraphicsDriver::InitSpriteBatch(0, _spriteBatchDesc[0]); } -bool ALSoftwareGraphicsDriver::IsModeSupported(const DisplayMode &mode) +bool SDLRendererGraphicsDriver::IsModeSupported(const DisplayMode &mode) { - if (mode.Width <= 0 || mode.Height <= 0 || mode.ColorDepth <= 0) + if (mode.Width <= 0 || mode.Height <= 0) { - set_allegro_error("Invalid resolution parameters: %d x %d x %d", mode.Width, mode.Height, mode.ColorDepth); + set_allegro_error("Invalid resolution parameters: %d x %d", mode.Width, mode.Height); return false; } -#if AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_MACOS - // Everything is drawn to a virtual screen, so all resolutions are supported. - return true; -#endif - - if (mode.Windowed) - { - return true; - } - if (_gfxModeList == nullptr) - { - _gfxModeList = get_gfx_mode_list(GetAllegroGfxDriverID(mode.Windowed)); - } - if (_gfxModeList != nullptr) - { - // if a list is available, check if the mode exists. This prevents the screen flicking - // between loads of unsupported resolutions - for (int i = 0; i < _gfxModeList->num_modes; i++) - { - if ((_gfxModeList->mode[i].width == mode.Width) && - (_gfxModeList->mode[i].height == mode.Height) && - (_gfxModeList->mode[i].bpp == mode.ColorDepth)) - { - return true; - } - } - set_allegro_error("This graphics mode is not supported"); + if (mode.ColorDepth != 32) { + set_allegro_error("Display colour depth not supported: %d", mode.ColorDepth); return false; } return true; } -int ALSoftwareGraphicsDriver::GetDisplayDepthForNativeDepth(int native_color_depth) const +int SDLRendererGraphicsDriver::GetDisplayDepthForNativeDepth(int native_color_depth) const { // TODO: check for device caps to know which depth is supported? if (native_color_depth > 8) @@ -138,157 +90,144 @@ int ALSoftwareGraphicsDriver::GetDisplayDepthForNativeDepth(int native_color_dep return native_color_depth; } -IGfxModeList *ALSoftwareGraphicsDriver::GetSupportedModeList(int color_depth) +IGfxModeList *SDLRendererGraphicsDriver::GetSupportedModeList(int color_depth) { - if (_gfxModeList == nullptr) - { - _gfxModeList = get_gfx_mode_list(GetAllegroGfxDriverID(false)); - } - if (_gfxModeList == nullptr) - { - return nullptr; - } - return new ALSoftwareGfxModeList(_gfxModeList); + std::vector modes; + sys_get_desktop_modes(modes); + return new SDLRendererGfxModeList(modes); } -PGfxFilter ALSoftwareGraphicsDriver::GetGraphicsFilter() const +PGfxFilter SDLRendererGraphicsDriver::GetGraphicsFilter() const { return _filter; } -int ALSoftwareGraphicsDriver::GetAllegroGfxDriverID(bool windowed) -{ -#if AGS_PLATFORM_OS_WINDOWS - if (windowed) - return GFX_DIRECTX_WIN; - return GFX_DIRECTX; -#elif AGS_PLATFORM_OS_LINUX && (!defined (ALLEGRO_MAGIC_DRV)) - if (windowed) - return GFX_XWINDOWS; - return GFX_XWINDOWS_FULLSCREEN; -#elif AGS_PLATFORM_OS_MACOS - if (windowed) { - return GFX_COCOAGL_WINDOW; - } - return GFX_COCOAGL_FULLSCREEN; -#else - if (windowed) - return GFX_AUTODETECT_WINDOWED; - return GFX_AUTODETECT_FULLSCREEN; -#endif -} - -void ALSoftwareGraphicsDriver::SetGraphicsFilter(PALSWFilter filter) +void SDLRendererGraphicsDriver::SetGraphicsFilter(PSDLRenderFilter filter) { _filter = filter; OnSetFilter(); + // TODO: support separate nearest and linear filters, initialize hint by calls to filter object + // e.g like D3D and OGL filters act + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother. + // If we already have a gfx mode set, then use the new filter to update virtual screen immediately CreateVirtualScreen(); } -void ALSoftwareGraphicsDriver::SetTintMethod(TintMethod method) +void SDLRendererGraphicsDriver::SetTintMethod(TintMethod method) { // TODO: support new D3D-style tint method } -bool ALSoftwareGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *loopTimer) +bool SDLRendererGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *loopTimer) { ReleaseDisplayMode(); - const int driver = GetAllegroGfxDriverID(mode.Windowed); - set_color_depth(mode.ColorDepth); if (_initGfxCallback != nullptr) _initGfxCallback(nullptr); - if (!IsModeSupported(mode) || set_gfx_mode(driver, mode.Width, mode.Height, 0, 0) != 0) + if (!IsModeSupported(mode)) return false; - OnInit(loopTimer); - OnModeSet(mode); - // set_gfx_mode is an allegro function that creates screen bitmap; - // following code assumes the screen is already created, therefore we should - // ensure global bitmap wraps over existing allegro screen bitmap. - _allegroScreenWrapper = BitmapHelper::CreateRawBitmapWrapper(screen); - _allegroScreenWrapper->Clear(); - - // If we already have a gfx filter, then use it to update virtual screen immediately - CreateVirtualScreen(); - -#if AGS_DDRAW_GAMMA_CONTROL - if (!mode.Windowed) + if (sys_get_window() == nullptr) { - memset(&ddrawCaps, 0, sizeof(ddrawCaps)); - ddrawCaps.dwSize = sizeof(ddrawCaps); - IDirectDraw2_GetCaps(directdraw, &ddrawCaps, NULL); + SDL_Window *window = sys_window_create("", mode.Width, mode.Height, mode.Windowed); - if ((ddrawCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA) == 0) { } - else if (IDirectDrawSurface2_QueryInterface(gfx_directx_primary_surface->id, IID_IDirectDrawGammaControl, (void **)&dxGammaControl) == 0) - { - dxGammaControl->GetGammaRamp(0, &defaultGammaRamp); + _hasGamma = SDL_GetWindowGammaRamp(window, _defaultGammaRed, _defaultGammaGreen, _defaultGammaBlue) == 0; + + Uint32 rendererFlags = SDL_RENDERER_ACCELERATED; + if (mode.Vsync) { + rendererFlags |= SDL_RENDERER_PRESENTVSYNC; + } + _renderer = SDL_CreateRenderer(window, -1, rendererFlags); + + SDL_RendererInfo rinfo{}; + if (SDL_GetRendererInfo(_renderer, &rinfo) == 0) { + Debug::Printf("Created Renderer: %s", rinfo.name); + Debug::Printf("Available texture formats:"); + for (int i = 0; i < rinfo.num_texture_formats; i++) { + Debug::Printf("\t- %s", SDL_GetPixelFormatName(rinfo.texture_formats[i])); + } } } -#endif + else + { + sys_window_set_style(mode.Windowed); + if (mode.Windowed) + sys_window_set_size(mode.Width, mode.Height, true); + } + OnInit(loopTimer); + OnModeSet(mode); + // If we already have a gfx filter, then use it to update virtual screen immediately + CreateVirtualScreen(); return true; } -void ALSoftwareGraphicsDriver::CreateVirtualScreen() +void SDLRendererGraphicsDriver::CreateVirtualScreen() { if (!IsModeSet() || !IsRenderFrameValid() || !IsNativeSizeValid() || !_filter) return; DestroyVirtualScreen(); - // Adjust clipping so nothing gets drawn outside the game frame - _allegroScreenWrapper->SetClip(_dstRect); - // Initialize scaling filter and receive virtual screen pointer - // (which may or not be the same as real screen) - _origVirtualScreen = _filter->InitVirtualScreen(_allegroScreenWrapper, _srcRect.GetSize(), _dstRect); - // Apparently we must still create a virtual screen even if its same size and color depth, - // because drawing sprites directly on real screen bitmap causes blinking (unless I missed something here...) - if (_origVirtualScreen == _allegroScreenWrapper) - { - _origVirtualScreen = BitmapHelper::CreateBitmap(_srcRect.GetWidth(), _srcRect.GetHeight(), _mode.ColorDepth); - } - virtualScreen = _origVirtualScreen; + // Initialize virtual screen; size is equal to native resolution + const int vscreen_w = _srcRect.GetWidth(); + const int vscreen_h = _srcRect.GetHeight(); + _origVirtualScreen.reset(new Bitmap(vscreen_w, vscreen_h)); + virtualScreen = _origVirtualScreen.get(); _stageVirtualScreen = virtualScreen; - // Set Allegro's screen pointer to what may be the real or virtual screen - screen = (BITMAP*)_origVirtualScreen->GetAllegroBitmap(); -} -void ALSoftwareGraphicsDriver::DestroyVirtualScreen() -{ - if (_filter && _origVirtualScreen) - { - screen = (BITMAP*)_filter->ShutdownAndReturnRealScreen()->GetAllegroBitmap(); - } - _origVirtualScreen = nullptr; + _screenTex = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, vscreen_w, vscreen_h); + + // Fake bitmap that will wrap over texture pixels for simplier conversion + _fakeTexBitmap = reinterpret_cast(new char[sizeof(BITMAP) + (sizeof(char *) * vscreen_h)]); + _fakeTexBitmap->w = vscreen_w; + _fakeTexBitmap->cr = vscreen_w; + _fakeTexBitmap->h = vscreen_h; + _fakeTexBitmap->cb = vscreen_h; + _fakeTexBitmap->clip = true; + _fakeTexBitmap->cl = 0; + _fakeTexBitmap->ct = 0; + _fakeTexBitmap->id = 0; + _fakeTexBitmap->extra = nullptr; + _fakeTexBitmap->x_ofs = 0; + _fakeTexBitmap->y_ofs = 0; + _fakeTexBitmap->dat = nullptr; + + auto tmpbitmap = create_bitmap_ex(32, 1, 1); + _fakeTexBitmap->vtable = tmpbitmap->vtable; + _fakeTexBitmap->write_bank = tmpbitmap->write_bank; + _fakeTexBitmap->read_bank = tmpbitmap->read_bank; + destroy_bitmap(tmpbitmap); + + _lastTexPixels = nullptr; + _lastTexPitch = -1; +} + +void SDLRendererGraphicsDriver::DestroyVirtualScreen() +{ + delete[] _fakeTexBitmap; // don't use destroy_bitmap(), because it's a fake structure + _fakeTexBitmap = nullptr; + SDL_DestroyTexture(_screenTex); + _screenTex = nullptr; + + _origVirtualScreen.reset(); virtualScreen = nullptr; _stageVirtualScreen = nullptr; } -void ALSoftwareGraphicsDriver::ReleaseDisplayMode() +void SDLRendererGraphicsDriver::ReleaseDisplayMode() { OnModeReleased(); ClearDrawLists(); -#if AGS_DDRAW_GAMMA_CONTROL - if (dxGammaControl != NULL) - { - dxGammaControl->Release(); - dxGammaControl = NULL; - } -#endif - DestroyVirtualScreen(); - - // Note this does not destroy the underlying allegro screen bitmap, only wrapper. - delete _allegroScreenWrapper; - _allegroScreenWrapper = nullptr; } -bool ALSoftwareGraphicsDriver::SetNativeSize(const Size &src_size) +bool SDLRendererGraphicsDriver::SetNativeSize(const Size &src_size) { OnSetNativeSize(src_size); // If we already have a gfx mode and gfx filter set, then use it to update virtual screen immediately @@ -296,7 +235,7 @@ bool ALSoftwareGraphicsDriver::SetNativeSize(const Size &src_size) return !_srcRect.IsEmpty(); } -bool ALSoftwareGraphicsDriver::SetRenderFrame(const Rect &dst_rect) +bool SDLRendererGraphicsDriver::SetRenderFrame(const Rect &dst_rect) { OnSetRenderFrame(dst_rect); // If we already have a gfx mode and gfx filter set, then use it to update virtual screen immediately @@ -304,87 +243,71 @@ bool ALSoftwareGraphicsDriver::SetRenderFrame(const Rect &dst_rect) return !_dstRect.IsEmpty(); } -void ALSoftwareGraphicsDriver::ClearRectangle(int x1, int y1, int x2, int y2, RGB *colorToUse) +void SDLRendererGraphicsDriver::ClearRectangle(int x1, int y1, int x2, int y2, RGB *colorToUse) { - if (!_filter) return; - int color = 0; - if (colorToUse != nullptr) - color = makecol_depth(_mode.ColorDepth, colorToUse->r, colorToUse->g, colorToUse->b); - // NOTE: filter will do coordinate scaling for us - _filter->ClearRect(x1, y1, x2, y2, color); + // TODO: but maybe is not necessary, as we use SDL_Renderer with accelerated gfx here? + // See SDL_RenderDrawRect } -ALSoftwareGraphicsDriver::~ALSoftwareGraphicsDriver() +SDLRendererGraphicsDriver::~SDLRendererGraphicsDriver() { - ALSoftwareGraphicsDriver::UnInit(); + SDLRendererGraphicsDriver::UnInit(); } -void ALSoftwareGraphicsDriver::UnInit() +void SDLRendererGraphicsDriver::UnInit() { OnUnInit(); ReleaseDisplayMode(); - if (_gfxModeList != nullptr) - { - destroy_gfx_mode_list(_gfxModeList); - _gfxModeList = nullptr; - } + sys_window_destroy(); } -bool ALSoftwareGraphicsDriver::SupportsGammaControl() +bool SDLRendererGraphicsDriver::SupportsGammaControl() { -#if AGS_DDRAW_GAMMA_CONTROL - - if (dxGammaControl != NULL) - { - return 1; - } - -#endif - - return 0; + return _hasGamma; } -void ALSoftwareGraphicsDriver::SetGamma(int newGamma) +void SDLRendererGraphicsDriver::SetGamma(int newGamma) { -#if AGS_DDRAW_GAMMA_CONTROL + if (!_hasGamma) { return; } + + Uint16 gamma_red[256]; + Uint16 gamma_green[256]; + Uint16 gamma_blue[256]; + for (int i = 0; i < 256; i++) { - int newValue = ((int)defaultGammaRamp.red[i] * newGamma) / 100; - if (newValue >= 65535) - newValue = 65535; - gammaRamp.red[i] = newValue; - gammaRamp.green[i] = newValue; - gammaRamp.blue[i] = newValue; + gamma_red[i] = std::min(((int)_defaultGammaRed[i] * newGamma) / 100, 0xffff); + gamma_green[i] = std::min(((int)_defaultGammaGreen[i] * newGamma) / 100, 0xffff); + gamma_blue[i] = std::min(((int)_defaultGammaBlue[i] * newGamma) / 100, 0xffff); } - dxGammaControl->SetGammaRamp(0, &gammaRamp); -#endif + SDL_SetWindowGammaRamp(sys_get_window(), gamma_red, gamma_green, gamma_blue); } -int ALSoftwareGraphicsDriver::GetCompatibleBitmapFormat(int color_depth) +int SDLRendererGraphicsDriver::GetCompatibleBitmapFormat(int color_depth) { return color_depth; } -IDriverDependantBitmap* ALSoftwareGraphicsDriver::CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque) +IDriverDependantBitmap* SDLRendererGraphicsDriver::CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque) { ALSoftwareBitmap* newBitmap = new ALSoftwareBitmap(bitmap, opaque, hasAlpha); return newBitmap; } -void ALSoftwareGraphicsDriver::UpdateDDBFromBitmap(IDriverDependantBitmap* bitmapToUpdate, Bitmap *bitmap, bool hasAlpha) +void SDLRendererGraphicsDriver::UpdateDDBFromBitmap(IDriverDependantBitmap* bitmapToUpdate, Bitmap *bitmap, bool hasAlpha) { ALSoftwareBitmap* alSwBmp = (ALSoftwareBitmap*)bitmapToUpdate; alSwBmp->_bmp = bitmap; alSwBmp->_hasAlpha = hasAlpha; } -void ALSoftwareGraphicsDriver::DestroyDDB(IDriverDependantBitmap* bitmap) +void SDLRendererGraphicsDriver::DestroyDDB(IDriverDependantBitmap* bitmap) { delete bitmap; } -void ALSoftwareGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) +void SDLRendererGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) { if (_spriteBatches.size() <= index) _spriteBatches.resize(index + 1); @@ -427,23 +350,24 @@ void ALSoftwareGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBatchDe } } -void ALSoftwareGraphicsDriver::ResetAllBatches() +void SDLRendererGraphicsDriver::ResetAllBatches() { for (ALSpriteBatches::iterator it = _spriteBatches.begin(); it != _spriteBatches.end(); ++it) it->List.clear(); } -void ALSoftwareGraphicsDriver::DrawSprite(int x, int y, IDriverDependantBitmap* bitmap) +void SDLRendererGraphicsDriver::DrawSprite(int x, int y, IDriverDependantBitmap* bitmap) { _spriteBatches[_actSpriteBatch].List.push_back(ALDrawListEntry((ALSoftwareBitmap*)bitmap, x, y)); } -void ALSoftwareGraphicsDriver::SetScreenFade(int red, int green, int blue) +void SDLRendererGraphicsDriver::SetScreenFade(int red, int green, int blue) { // TODO: was not necessary atm + // TODO: checkme later } -void ALSoftwareGraphicsDriver::SetScreenTint(int red, int green, int blue) +void SDLRendererGraphicsDriver::SetScreenTint(int red, int green, int blue) { _tint_red = red; _tint_green = green; _tint_blue = blue; if (((_tint_red > 0) || (_tint_green > 0) || (_tint_blue > 0)) && (_mode.ColorDepth > 8)) @@ -452,7 +376,7 @@ void ALSoftwareGraphicsDriver::SetScreenTint(int red, int green, int blue) } } -void ALSoftwareGraphicsDriver::RenderToBackBuffer() +void SDLRendererGraphicsDriver::RenderToBackBuffer() { // Render all the sprite batches with necessary transformations // @@ -494,7 +418,7 @@ void ALSoftwareGraphicsDriver::RenderToBackBuffer() ClearDrawLists(); } -void ALSoftwareGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &batch, Common::Bitmap *surface, int surf_offx, int surf_offy) +void SDLRendererGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &batch, Common::Bitmap *surface, int surf_offx, int surf_offy) { const std::vector &drawlist = batch.List; for (size_t i = 0; i < drawlist.size(); i++) @@ -546,51 +470,84 @@ void ALSoftwareGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &batch, Com bitmap->_transparency ? bitmap->_transparency : 255); } } - // NOTE: following is experimental tint code (currently unused) -/* This alternate method gives the correct (D3D-style) result, but is just too slow! - if ((_spareTintingScreen != NULL) && - ((_spareTintingScreen->GetWidth() != surface->GetWidth()) || (_spareTintingScreen->GetHeight() != surface->GetHeight()))) - { - destroy_bitmap(_spareTintingScreen); - _spareTintingScreen = NULL; - } - if (_spareTintingScreen == NULL) - { - _spareTintingScreen = BitmapHelper::CreateBitmap_(GetColorDepth(surface), surface->GetWidth(), surface->GetHeight()); +} + +void SDLRendererGraphicsDriver::BlitToTexture() +{ + void *pixels = nullptr; + int pitch = 0; + auto res = SDL_LockTexture(_screenTex, NULL, &pixels, &pitch); + if (res != 0) { return; } + + // Because the virtual screen may be of any color depth, + // we wrap texture pixels in a fake bitmap here and call + // standard blit operation, for simplicity sake. + const int vwidth = virtualScreen->GetWidth(); + const int vheight = virtualScreen->GetHeight(); + if ((_lastTexPixels != pixels) || (_lastTexPitch != pitch)) { + _fakeTexBitmap->dat = pixels; + auto p = (unsigned char *)pixels; + for (int i = 0; i < vheight; i++) { + _fakeTexBitmap->line[i] = p; + p += pitch; + } + _lastTexPixels = (unsigned char *)pixels; + _lastTexPitch = pitch; } - tint_image(surface, _spareTintingScreen, _tint_red, _tint_green, _tint_blue, 100, 255); - Blit(_spareTintingScreen, surface, 0, 0, 0, 0, _spareTintingScreen->GetWidth(), _spareTintingScreen->GetHeight());*/ + + blit(virtualScreen->GetAllegroBitmap(), _fakeTexBitmap, 0, 0, 0, 0, vwidth, vheight); + + SDL_UnlockTexture(_screenTex); } -void ALSoftwareGraphicsDriver::Render(int xoff, int yoff, GlobalFlipType flip) +void SDLRendererGraphicsDriver::Present() { - RenderToBackBuffer(); + if (!_renderer) { return; } - if (_autoVsync) - this->Vsync(); + BlitToTexture(); - if (flip == kFlip_None) - _filter->RenderScreen(virtualScreen, xoff, yoff); - else - _filter->RenderScreenFlipped(virtualScreen, xoff, yoff, flip); + SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + SDL_RenderFillRect(_renderer, nullptr); + + SDL_Rect dst; + dst.x = _dstRect.Left; + dst.y = _dstRect.Top; + dst.w = _dstRect.GetWidth(); + dst.h = _dstRect.GetHeight(); + SDL_RenderCopyEx(_renderer, _screenTex, nullptr, &dst, 0.0, nullptr, _renderFlip); + + SDL_RenderPresent(_renderer); +} + +void SDLRendererGraphicsDriver::Render(int /*xoff*/, int /*yoff*/, GlobalFlipType flip) +{ + switch (flip) { + case kFlip_Both: _renderFlip = (SDL_RendererFlip)(SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL); break; + case kFlip_Horizontal: _renderFlip = SDL_FLIP_HORIZONTAL; break; + case kFlip_Vertical: _renderFlip = SDL_FLIP_VERTICAL; break; + default: _renderFlip = SDL_FLIP_NONE; break; + } + + RenderToBackBuffer(); + Present(); } -void ALSoftwareGraphicsDriver::Render() +void SDLRendererGraphicsDriver::Render() { Render(0, 0, kFlip_None); } -void ALSoftwareGraphicsDriver::Vsync() +void SDLRendererGraphicsDriver::Vsync() { - vsync(); } -Bitmap *ALSoftwareGraphicsDriver::GetMemoryBackBuffer() +Bitmap *SDLRendererGraphicsDriver::GetMemoryBackBuffer() { return virtualScreen; } -void ALSoftwareGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) +void SDLRendererGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) { if (backBuffer) { @@ -598,7 +555,7 @@ void ALSoftwareGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) } else { - virtualScreen = _origVirtualScreen; + virtualScreen = _origVirtualScreen.get(); } _stageVirtualScreen = virtualScreen; @@ -610,12 +567,12 @@ void ALSoftwareGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) } } -Bitmap *ALSoftwareGraphicsDriver::GetStageBackBuffer() +Bitmap *SDLRendererGraphicsDriver::GetStageBackBuffer() { return _stageVirtualScreen; } -bool ALSoftwareGraphicsDriver::GetCopyOfScreenIntoBitmap(Bitmap *destination, bool at_native_res, GraphicResolution *want_fmt) +bool SDLRendererGraphicsDriver::GetCopyOfScreenIntoBitmap(Bitmap *destination, bool at_native_res, GraphicResolution *want_fmt) { (void)at_native_res; // software driver always renders at native resolution at the moment // software filter is taught to copy to any size @@ -625,7 +582,17 @@ bool ALSoftwareGraphicsDriver::GetCopyOfScreenIntoBitmap(Bitmap *destination, bo *want_fmt = GraphicResolution(destination->GetWidth(), destination->GetHeight(), _mode.ColorDepth); return false; } - _filter->GetCopyOfScreenIntoBitmap(destination); + + if (destination->GetSize() == virtualScreen->GetSize()) + { + destination->Blit(virtualScreen, 0, 0, 0, 0, virtualScreen->GetWidth(), virtualScreen->GetHeight()); + } + else + { + destination->StretchBlt(virtualScreen, + RectWH(0, 0, virtualScreen->GetWidth(), virtualScreen->GetHeight()), + RectWH(0, 0, destination->GetWidth(), destination->GetHeight())); + } return true; } @@ -636,7 +603,7 @@ bool ALSoftwareGraphicsDriver::GetCopyOfScreenIntoBitmap(Bitmap *destination, bo Author: Matthew Leverton **/ -void ALSoftwareGraphicsDriver::highcolor_fade_in(Bitmap *vs, void(*draw_callback)(), int offx, int offy, int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) +void SDLRendererGraphicsDriver::highcolor_fade_in(Bitmap *vs, void(*draw_callback)(), int offx, int offy, int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) { Bitmap *bmp_orig = vs; const int col_depth = bmp_orig->GetColorDepth(); @@ -650,29 +617,28 @@ void ALSoftwareGraphicsDriver::highcolor_fade_in(Bitmap *vs, void(*draw_callback bmp_buff->Fill(clearColor); set_trans_blender(0,0,0,a); bmp_buff->TransBlendBlt(bmp_orig, 0, 0); + if (draw_callback) - { draw_callback(); - RenderToBackBuffer(); - } - this->Vsync(); - _filter->RenderScreen(bmp_buff, offx, offy); + RenderToBackBuffer(); + Present(); + + sys_evt_process_pending(); if (_pollingCallback) - _pollingCallback(); + _pollingCallback(); + WaitForNextFrame(); } delete bmp_buff; SetMemoryBackBuffer(vs); if (draw_callback) - { draw_callback(); - RenderToBackBuffer(); - } - _filter->RenderScreen(vs, offx, offy); + RenderToBackBuffer(); + Present(); } -void ALSoftwareGraphicsDriver::highcolor_fade_out(Bitmap *vs, void(*draw_callback)(), int offx, int offy, int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) +void SDLRendererGraphicsDriver::highcolor_fade_out(Bitmap *vs, void(*draw_callback)(), int offx, int offy, int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) { Bitmap *bmp_orig = vs; const int col_depth = vs->GetColorDepth(); @@ -686,15 +652,16 @@ void ALSoftwareGraphicsDriver::highcolor_fade_out(Bitmap *vs, void(*draw_callbac bmp_buff->Fill(clearColor); set_trans_blender(0, 0, 0, a); bmp_buff->TransBlendBlt(bmp_orig, 0, 0); + if (draw_callback) - { draw_callback(); - RenderToBackBuffer(); - } - this->Vsync(); - _filter->RenderScreen(bmp_buff, offx, offy); + RenderToBackBuffer(); + Present(); + + sys_evt_process_pending(); if (_pollingCallback) - _pollingCallback(); + _pollingCallback(); + WaitForNextFrame(); } delete bmp_buff; @@ -702,11 +669,9 @@ void ALSoftwareGraphicsDriver::highcolor_fade_out(Bitmap *vs, void(*draw_callbac SetMemoryBackBuffer(vs); vs->Clear(clearColor); if (draw_callback) - { draw_callback(); - RenderToBackBuffer(); - } - _filter->RenderScreen(vs, offx, offy); + RenderToBackBuffer(); + Present(); } /** END FADE.C **/ @@ -721,7 +686,7 @@ void initialize_fade_256(int r, int g, int b) { } } -void ALSoftwareGraphicsDriver::__fade_from_range(PALETTE source, PALETTE dest, int speed, int from, int to) +void SDLRendererGraphicsDriver::__fade_from_range(PALETTE source, PALETTE dest, int speed, int from, int to) { PALETTE temp; int c; @@ -732,14 +697,19 @@ void ALSoftwareGraphicsDriver::__fade_from_range(PALETTE source, PALETTE dest, i for (c=0; c<64; c+=speed) { fade_interpolate(source, dest, temp, c, from, to); set_palette_range(temp, from, to, TRUE); - if (_pollingCallback) _pollingCallback(); - set_palette_range(temp, from, to, TRUE); + + RenderToBackBuffer(); + Present(); + + sys_evt_process_pending(); + if (_pollingCallback) + _pollingCallback(); } set_palette_range(dest, from, to, TRUE); } -void ALSoftwareGraphicsDriver::__fade_out_range(int speed, int from, int to, int targetColourRed, int targetColourGreen, int targetColourBlue) +void SDLRendererGraphicsDriver::__fade_out_range(int speed, int from, int to, int targetColourRed, int targetColourGreen, int targetColourBlue) { PALETTE temp; @@ -748,7 +718,7 @@ void ALSoftwareGraphicsDriver::__fade_out_range(int speed, int from, int to, int __fade_from_range(temp, faded_out_palette, speed, from, to); } -void ALSoftwareGraphicsDriver::FadeOut(int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) { +void SDLRendererGraphicsDriver::FadeOut(int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) { if (_mode.ColorDepth > 8) { highcolor_fade_out(virtualScreen, _drawPostScreenCallback, 0, 0, speed * 4, targetColourRed, targetColourGreen, targetColourBlue); @@ -759,7 +729,7 @@ void ALSoftwareGraphicsDriver::FadeOut(int speed, int targetColourRed, int targe } } -void ALSoftwareGraphicsDriver::FadeIn(int speed, PALETTE p, int targetColourRed, int targetColourGreen, int targetColourBlue) { +void SDLRendererGraphicsDriver::FadeIn(int speed, PALETTE p, int targetColourRed, int targetColourGreen, int targetColourBlue) { if (_drawScreenCallback) { _drawScreenCallback(); @@ -776,7 +746,7 @@ void ALSoftwareGraphicsDriver::FadeIn(int speed, PALETTE p, int targetColourRed, } } -void ALSoftwareGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int delay) +void SDLRendererGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int delay) { if (blackingOut) { @@ -794,16 +764,15 @@ void ALSoftwareGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int del _srcRect.GetWidth() / 2 + boxwid / 2, vcentre + boxhit / 2), 0); bmp_buff->Fill(0); bmp_buff->Blit(bmp_orig); + if (_drawPostScreenCallback) - { _drawPostScreenCallback(); - RenderToBackBuffer(); - } - this->Vsync(); - _filter->RenderScreen(bmp_buff, 0, 0); - + RenderToBackBuffer(); + Present(); + + sys_evt_process_pending(); if (_pollingCallback) - _pollingCallback(); + _pollingCallback(); platform->Delay(delay); } @@ -819,7 +788,7 @@ void ALSoftwareGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int del #ifndef AGS_NO_VIDEO_PLAYER -bool ALSoftwareGraphicsDriver::PlayVideo(const char *filename, bool useAVISound, VideoSkipType skipType, bool stretchToFullScreen) +bool SDLRendererGraphicsDriver::PlayVideo(const char *filename, bool useAVISound, VideoSkipType skipType, bool stretchToFullScreen) { #if AGS_PLATFORM_OS_WINDOWS int result = dxmedia_play_video(filename, useAVISound, skipType, stretchToFullScreen ? 1 : 0); @@ -832,7 +801,8 @@ bool ALSoftwareGraphicsDriver::PlayVideo(const char *filename, bool useAVISound, #endif // add the alpha values together, used for compositing alpha images -unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned long n) +// TODO: why is this here, move to gfx/blender? check if there's already similar function there +static unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned long n) { unsigned long res, g; @@ -853,56 +823,52 @@ unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned } -ALSWGraphicsFactory *ALSWGraphicsFactory::_factory = nullptr; +SDLRendererGraphicsFactory *SDLRendererGraphicsFactory::_factory = nullptr; -ALSWGraphicsFactory::~ALSWGraphicsFactory() +SDLRendererGraphicsFactory::~SDLRendererGraphicsFactory() { _factory = nullptr; } -size_t ALSWGraphicsFactory::GetFilterCount() const +size_t SDLRendererGraphicsFactory::GetFilterCount() const { - return 2; + return 1; } -const GfxFilterInfo *ALSWGraphicsFactory::GetFilterInfo(size_t index) const +const GfxFilterInfo *SDLRendererGraphicsFactory::GetFilterInfo(size_t index) const { switch (index) { case 0: - return &AllegroGfxFilter::FilterInfo; - case 1: - return &HqxGfxFilter::FilterInfo; + return &SDLRendererGfxFilter::FilterInfo; default: return nullptr; } } -String ALSWGraphicsFactory::GetDefaultFilterID() const +String SDLRendererGraphicsFactory::GetDefaultFilterID() const { - return AllegroGfxFilter::FilterInfo.Id; + return SDLRendererGfxFilter::FilterInfo.Id; } -/* static */ ALSWGraphicsFactory *ALSWGraphicsFactory::GetFactory() +/* static */ SDLRendererGraphicsFactory *SDLRendererGraphicsFactory::GetFactory() { if (!_factory) - _factory = new ALSWGraphicsFactory(); + _factory = new SDLRendererGraphicsFactory(); return _factory; } -ALSoftwareGraphicsDriver *ALSWGraphicsFactory::EnsureDriverCreated() +SDLRendererGraphicsDriver *SDLRendererGraphicsFactory::EnsureDriverCreated() { if (!_driver) - _driver = new ALSoftwareGraphicsDriver(); + _driver = new SDLRendererGraphicsDriver(); return _driver; } -AllegroGfxFilter *ALSWGraphicsFactory::CreateFilter(const String &id) +SDLRendererGfxFilter *SDLRendererGraphicsFactory::CreateFilter(const String &id) { - if (AllegroGfxFilter::FilterInfo.Id.CompareNoCase(id) == 0) - return new AllegroGfxFilter(); - else if (HqxGfxFilter::FilterInfo.Id.CompareNoCase(id) == 0) - return new HqxGfxFilter(); + if (SDLRendererGfxFilter::FilterInfo.Id.CompareNoCase(id) == 0) + return new SDLRendererGfxFilter(); return nullptr; } diff --git a/Engine/gfx/ali3dsw.h b/Engine/gfx/ali3dsw.h index 8cb4f0fb9e0..d988ca0f8c8 100644 --- a/Engine/gfx/ali3dsw.h +++ b/Engine/gfx/ali3dsw.h @@ -12,25 +12,20 @@ // //============================================================================= // -// Software graphics factory, based on Allegro +// Software graphics factory, draws raw bitmaps onto a virtual screen, +// converts to SDL_Texture and finally presents with SDL_Renderer. +// +// TODO: replace nearest-neighbour software filter with SDL's own accelerated +// scaling, maybe add more filter types if SDL renderer supports them. +// Only keep Hqx filter as a software option (might need to change how the +// filter code works). // //============================================================================= - #ifndef __AGS_EE_GFX__ALI3DSW_H #define __AGS_EE_GFX__ALI3DSW_H - #include - +#include #include "core/platform.h" -#define AGS_DDRAW_GAMMA_CONTROL (AGS_PLATFORM_OS_WINDOWS) - -#include - -#if AGS_DDRAW_GAMMA_CONTROL -#include -#include -#endif - #include "gfx/bitmap.h" #include "gfx/ddb.h" #include "gfx/gfxdriverfactorybase.h" @@ -43,7 +38,7 @@ namespace Engine namespace ALSW { -class AllegroGfxFilter; +class SDLRendererGfxFilter; using AGS::Common::Bitmap; class ALSoftwareBitmap : public IDriverDependantBitmap @@ -103,23 +98,31 @@ class ALSoftwareBitmap : public IDriverDependantBitmap }; -class ALSoftwareGfxModeList : public IGfxModeList +class SDLRendererGfxModeList : public IGfxModeList { public: - ALSoftwareGfxModeList(GFX_MODE_LIST *alsw_gfx_mode_list) - : _gfxModeList(alsw_gfx_mode_list) + SDLRendererGfxModeList(const std::vector &modes) + : _modes(modes) { } int GetModeCount() const override { - return _gfxModeList ? _gfxModeList->num_modes : 0; + return _modes.size(); } - bool GetMode(int index, DisplayMode &mode) const override; + bool GetMode(int index, DisplayMode &mode) const override + { + if (index >= 0 && (size_t)index < _modes.size()) + { + mode = _modes[index]; + return true; + } + return false; + } private: - GFX_MODE_LIST *_gfxModeList; + std::vector _modes; }; @@ -139,12 +142,12 @@ struct ALSpriteBatch typedef std::vector ALSpriteBatches; -class ALSoftwareGraphicsDriver : public GraphicsDriverBase +class SDLRendererGraphicsDriver : public GraphicsDriverBase { public: - ALSoftwareGraphicsDriver(); + SDLRendererGraphicsDriver(); - const char*GetDriverName() override { return "Software renderer"; } + const char*GetDriverName() override { return "SDL 2D Software renderer"; } const char*GetDriverID() override { return "Software"; } void SetTintMethod(TintMethod method) override; bool SetDisplayMode(const DisplayMode &mode, volatile int *loopTimer) override; @@ -179,7 +182,7 @@ class ALSoftwareGraphicsDriver : public GraphicsDriverBase bool SupportsGammaControl() override ; void SetGamma(int newGamma) override; void UseSmoothScaling(bool enabled) override { } - void EnableVsyncBeforeRender(bool enabled) override { _autoVsync = enabled; } + void EnableVsyncBeforeRender(bool enabled) override { } void Vsync() override; void RenderSpritesAtScreenResolution(bool enabled, int supersampling) override { } bool RequiresFullRedrawEachFrame() override { return false; } @@ -188,43 +191,41 @@ class ALSoftwareGraphicsDriver : public GraphicsDriverBase Bitmap *GetMemoryBackBuffer() override; void SetMemoryBackBuffer(Bitmap *backBuffer) override; Bitmap *GetStageBackBuffer() override; - ~ALSoftwareGraphicsDriver() override; + ~SDLRendererGraphicsDriver() override; - typedef std::shared_ptr PALSWFilter; + typedef std::shared_ptr PSDLRenderFilter; - void SetGraphicsFilter(PALSWFilter filter); + void SetGraphicsFilter(PSDLRenderFilter filter); private: - PALSWFilter _filter; - - bool _autoVsync; - Bitmap *_allegroScreenWrapper; - // Virtual screen bitmap is either a wrapper over Allegro's real screen - // bitmap, or bitmap provided by the graphics filter. It should not be - // disposed by the renderer: it is up to filter object to manage it. - Bitmap *_origVirtualScreen; - // Current virtual screen bitmap; may be provided either by graphics - // filter or by external user. It should not be disposed by the renderer. + PSDLRenderFilter _filter; + + bool _hasGamma = false; + Uint16 _defaultGammaRed[256]{}; + Uint16 _defaultGammaGreen[256]{}; + Uint16 _defaultGammaBlue[256]{}; + + SDL_RendererFlip _renderFlip = SDL_FLIP_NONE; + SDL_Renderer *_renderer = nullptr; + SDL_Texture *_screenTex = nullptr; + // BITMAP struct for wrapping screen texture locked pixels, so that we may use blit() + BITMAP *_fakeTexBitmap = nullptr; + unsigned char *_lastTexPixels = nullptr; + int _lastTexPitch = -1; + + // Original virtual screen created and managed by the renderer. + std::unique_ptr _origVirtualScreen; + // Current virtual screen bitmap; may be either pointing to _origVirtualScreen, + // or provided by external user (for example - plugin). + // Its pixels are copied to the video texture to be presented by SDL_Renderer. Bitmap *virtualScreen; // Stage screen meant for particular rendering stages, may be referencing // actual virtual screen or separate bitmap of different size that is // blitted to virtual screen at the stage finalization. Bitmap *_stageVirtualScreen; - //Bitmap *_spareTintingScreen; int _tint_red, _tint_green, _tint_blue; ALSpriteBatches _spriteBatches; - GFX_MODE_LIST *_gfxModeList; - -#if AGS_DDRAW_GAMMA_CONTROL - IDirectDrawGammaControl* dxGammaControl; - // The gamma ramp is a lookup table for each possible R, G and B value - // in 32-bit colour (from 0-255) it maps them to a brightness value - // from 0-65535. The default gamma ramp just multiplies each value by 256 - DDGAMMARAMP gammaRamp; - DDGAMMARAMP defaultGammaRamp; - DDCAPS ddrawCaps; -#endif void InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) override; void ResetAllBatches() override; @@ -241,26 +242,29 @@ class ALSoftwareGraphicsDriver : public GraphicsDriverBase void highcolor_fade_out(Bitmap *vs, void(*draw_callback)(), int offx, int offy, int speed, int targetColourRed, int targetColourGreen, int targetColourBlue); void __fade_from_range(PALETTE source, PALETTE dest, int speed, int from, int to) ; void __fade_out_range(int speed, int from, int to, int targetColourRed, int targetColourGreen, int targetColourBlue) ; - int GetAllegroGfxDriverID(bool windowed); + // Copy raw screen bitmap pixels to the SDL texture + void BlitToTexture(); + // Render SDL texture on screen + void Present(); }; -class ALSWGraphicsFactory : public GfxDriverFactoryBase +class SDLRendererGraphicsFactory : public GfxDriverFactoryBase { public: - ~ALSWGraphicsFactory() override; + ~SDLRendererGraphicsFactory() override; size_t GetFilterCount() const override; const GfxFilterInfo *GetFilterInfo(size_t index) const override; String GetDefaultFilterID() const override; - static ALSWGraphicsFactory *GetFactory(); + static SDLRendererGraphicsFactory *GetFactory(); private: - ALSoftwareGraphicsDriver *EnsureDriverCreated() override; - AllegroGfxFilter *CreateFilter(const String &id) override; + SDLRendererGraphicsDriver *EnsureDriverCreated() override; + SDLRendererGfxFilter *CreateFilter(const String &id) override; - static ALSWGraphicsFactory *_factory; + static SDLRendererGraphicsFactory *_factory; }; } // namespace ALSW diff --git a/Engine/gfx/gfxdriverfactory.cpp b/Engine/gfx/gfxdriverfactory.cpp index 8dc58b92764..b8e886544ed 100644 --- a/Engine/gfx/gfxdriverfactory.cpp +++ b/Engine/gfx/gfxdriverfactory.cpp @@ -20,7 +20,7 @@ #define AGS_HAS_OPENGL (AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_LINUX) #include "gfx/ali3dsw.h" -#include "gfx/gfxfilter_allegro.h" +#include "gfx/gfxfilter_sdl_renderer.h" #if AGS_HAS_OPENGL #include "gfx/ali3dogl.h" @@ -61,7 +61,7 @@ IGfxDriverFactory *GetGfxDriverFactory(const String id) return OGL::OGLGraphicsFactory::GetFactory(); #endif if (id.CompareNoCase("Software") == 0) - return ALSW::ALSWGraphicsFactory::GetFactory(); + return ALSW::SDLRendererGraphicsFactory::GetFactory(); set_allegro_error("No graphics factory with such id: %s", id.GetCStr()); return nullptr; } diff --git a/Engine/gfx/gfxfilter_allegro.cpp b/Engine/gfx/gfxfilter_allegro.cpp deleted file mode 100644 index 274163c1e8c..00000000000 --- a/Engine/gfx/gfxfilter_allegro.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "gfx/gfxfilter_allegro.h" - -namespace AGS -{ -namespace Engine -{ -namespace ALSW -{ - -using namespace Common; - -const GfxFilterInfo AllegroGfxFilter::FilterInfo = GfxFilterInfo("StdScale", "Nearest-neighbour"); - -AllegroGfxFilter::AllegroGfxFilter() - : realScreen(nullptr) - , virtualScreen(nullptr) - , realScreenSizedBuffer(nullptr) - , lastBlitFrom(nullptr) - , lastBlitX(0) - , lastBlitY(0) -{ -} - -const GfxFilterInfo &AllegroGfxFilter::GetInfo() const -{ - return FilterInfo; -} - -Bitmap* AllegroGfxFilter::InitVirtualScreen(Bitmap *screen, const Size src_size, const Rect dst_rect) -{ - ShutdownAndReturnRealScreen(); - - realScreen = screen; - SetTranslation(src_size, dst_rect); - - if (src_size == dst_rect.GetSize() && dst_rect.Top == 0 && dst_rect.Left == 0) - { - // Speed up software rendering if no scaling is performed - realScreenSizedBuffer = nullptr; - virtualScreen = realScreen; - } - else - { - realScreenSizedBuffer = BitmapHelper::CreateBitmap(screen->GetWidth(), screen->GetHeight(), screen->GetColorDepth()); - virtualScreen = BitmapHelper::CreateBitmap(src_size.Width, src_size.Height, screen->GetColorDepth()); - } - return virtualScreen; -} - -Bitmap *AllegroGfxFilter::ShutdownAndReturnRealScreen() -{ - if (virtualScreen != realScreen) - delete virtualScreen; - delete realScreenSizedBuffer; - virtualScreen = nullptr; - realScreenSizedBuffer = nullptr; - Bitmap *real_scr = realScreen; - realScreen = nullptr; - return real_scr; -} - -void AllegroGfxFilter::RenderScreen(Bitmap *toRender, int x, int y) { - - if (toRender != realScreen) - { - x = _scaling.X.ScalePt(x); - y = _scaling.Y.ScalePt(y); - const int width = _scaling.X.ScaleDistance(toRender->GetWidth()); - const int height = _scaling.Y.ScaleDistance(toRender->GetHeight()); - Bitmap *render_src = PreRenderPass(toRender); - if (render_src->GetSize() == _dstRect.GetSize()) - realScreen->Blit(render_src, 0, 0, x, y, width, height); - else - { - realScreen->StretchBlt(render_src, RectWH(x, y, width, height)); - } - } - lastBlitFrom = toRender; - lastBlitX = x; - lastBlitY = y; -} - -void AllegroGfxFilter::RenderScreenFlipped(Bitmap *toRender, int x, int y, GlobalFlipType flipType) { - - if (toRender == virtualScreen) - return; - - switch (flipType) - { - case kFlip_Horizontal: - virtualScreen->FlipBlt(toRender, 0, 0, Common::kBitmap_HFlip); - break; - case kFlip_Vertical: - virtualScreen->FlipBlt(toRender, 0, 0, Common::kBitmap_VFlip); - break; - case kFlip_Both: - virtualScreen->FlipBlt(toRender, 0, 0, Common::kBitmap_HVFlip); - break; - default: - virtualScreen->Blit(toRender, 0, 0); - break; - } - - RenderScreen(virtualScreen, x, y); -} - -void AllegroGfxFilter::ClearRect(int x1, int y1, int x2, int y2, int color) -{ - if (!realScreen) return; - Rect r = _scaling.ScaleRange(Rect(x1, y1, x2, y2)); - realScreen->FillRect(r, color); -} - -void AllegroGfxFilter::GetCopyOfScreenIntoBitmap(Bitmap *copyBitmap) -{ - GetCopyOfScreenIntoBitmap(copyBitmap, true); -} - -void AllegroGfxFilter::GetCopyOfScreenIntoBitmap(Bitmap *copyBitmap, bool copy_with_yoffset) -{ - if (copyBitmap == realScreen) - return; - - if (!copy_with_yoffset) - { - if (copyBitmap->GetSize() == _dstRect.GetSize()) - copyBitmap->Blit(realScreen, _dstRect.Left, _dstRect.Top, 0, 0, _dstRect.GetWidth(), _dstRect.GetHeight()); - else - { - // Can't stretch_blit from Video Memory to normal memory, - // so copy the screen to a buffer first. - realScreenSizedBuffer->Blit(realScreen, 0, 0); - copyBitmap->StretchBlt(realScreenSizedBuffer, - _dstRect, - RectWH(0, 0, copyBitmap->GetWidth(), copyBitmap->GetHeight())); - } - } - else if (!lastBlitFrom) - copyBitmap->Fill(0); - else if (copyBitmap->GetSize() == _dstRect.GetSize()) - copyBitmap->Blit(realScreen, lastBlitX, lastBlitY, 0, 0, copyBitmap->GetWidth(), copyBitmap->GetHeight()); - else - { - copyBitmap->StretchBlt(lastBlitFrom, - RectWH(0, 0, lastBlitFrom->GetWidth(), lastBlitFrom->GetHeight()), - RectWH(0, 0, copyBitmap->GetWidth(), copyBitmap->GetHeight())); - } -} - -Bitmap *AllegroGfxFilter::PreRenderPass(Bitmap *toRender) -{ - // do nothing by default - return toRender; -} - -} // namespace ALSW -} // namespace Engine -} // namespace AGS diff --git a/Engine/gfx/gfxfilter_allegro.h b/Engine/gfx/gfxfilter_allegro.h deleted file mode 100644 index 53f52c4faed..00000000000 --- a/Engine/gfx/gfxfilter_allegro.h +++ /dev/null @@ -1,71 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= -// -// Standard software scaling filter -// -//============================================================================= - -#ifndef __AGS_EE_GFX__ALLEGROGFXFILTER_H -#define __AGS_EE_GFX__ALLEGROGFXFILTER_H - -#include "gfx/bitmap.h" -#include "gfx/gfxfilter_scaling.h" -#include "gfx/gfxdefines.h" - -namespace AGS -{ -namespace Engine -{ -namespace ALSW -{ - -using Common::Bitmap; - -class AllegroGfxFilter : public ScalingGfxFilter -{ -public: - AllegroGfxFilter(); - - const GfxFilterInfo &GetInfo() const override; - - virtual Bitmap *InitVirtualScreen(Bitmap *screen, const Size src_size, const Rect dst_rect); - virtual Bitmap *ShutdownAndReturnRealScreen(); - virtual void RenderScreen(Bitmap *toRender, int x, int y); - virtual void RenderScreenFlipped(Bitmap *toRender, int x, int y, GlobalFlipType flipType); - virtual void ClearRect(int x1, int y1, int x2, int y2, int color); - virtual void GetCopyOfScreenIntoBitmap(Bitmap *copyBitmap); - virtual void GetCopyOfScreenIntoBitmap(Bitmap *copyBitmap, bool copy_with_yoffset); - - static const GfxFilterInfo FilterInfo; - -protected: - virtual Bitmap *PreRenderPass(Bitmap *toRender); - - // pointer to real screen bitmap - Bitmap *realScreen; - // bitmap the size of game resolution - Bitmap *virtualScreen; - // buffer for making a copy of video memory before stretching - // for screen capture - Bitmap *realScreenSizedBuffer; - Bitmap *lastBlitFrom; - int lastBlitX; - int lastBlitY; -}; - -} // namespace ALSW -} // namespace Engine -} // namespace AGS - -#endif // __AGS_EE_GFX__ALLEGROGFXFILTER_H diff --git a/Engine/gfx/gfxfilter_hqx.cpp b/Engine/gfx/gfxfilter_hqx.cpp deleted file mode 100644 index 6b7f843ba66..00000000000 --- a/Engine/gfx/gfxfilter_hqx.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#include "gfx/bitmap.h" -#include "gfx/gfxfilter_hqx.h" -#include "gfx/hq2x3x.h" - -namespace AGS -{ -namespace Engine -{ -namespace ALSW -{ - -using namespace Common; - -const GfxFilterInfo HqxGfxFilter::FilterInfo = GfxFilterInfo("Hqx", "Hqx (High Quality)", 2, 3); - -HqxGfxFilter::HqxGfxFilter() - : _pfnHqx(nullptr) - , _hqxScalingBuffer(nullptr) -{ -} - -HqxGfxFilter::~HqxGfxFilter() -{ - delete _hqxScalingBuffer; -} - -const GfxFilterInfo &HqxGfxFilter::GetInfo() const -{ - return FilterInfo; -} - -bool HqxGfxFilter::Initialize(const int color_depth, String &err_str) -{ - if (color_depth < 32) - { - err_str = "Only supports 32-bit colour games"; - return false; - } - return AllegroGfxFilter::Initialize(color_depth, err_str); -} - -Bitmap* HqxGfxFilter::InitVirtualScreen(Bitmap *screen, const Size src_size, const Rect dst_rect) -{ - Bitmap *virtual_screen = AllegroGfxFilter::InitVirtualScreen(screen, src_size, dst_rect); - - // Choose used algorithm depending on minimal required integer scaling - int min_scaling = Math::Min(dst_rect.GetWidth() / src_size.Width, dst_rect.GetHeight() / src_size.Height); - min_scaling = Math::Clamp(min_scaling, 2, 3); - if (min_scaling == 2) - _pfnHqx = hq2x_32; - else - _pfnHqx = hq3x_32; - _hqxScalingBuffer = BitmapHelper::CreateBitmap(src_size.Width * min_scaling, src_size.Height * min_scaling); - - InitLUTs(); - return virtual_screen; -} - -Bitmap *HqxGfxFilter::ShutdownAndReturnRealScreen() -{ - Bitmap *real_screen = AllegroGfxFilter::ShutdownAndReturnRealScreen(); - delete _hqxScalingBuffer; - _hqxScalingBuffer = nullptr; - return real_screen; -} - -Bitmap *HqxGfxFilter::PreRenderPass(Bitmap *toRender) -{ - _hqxScalingBuffer->Acquire(); - _pfnHqx(toRender->GetDataForWriting(), _hqxScalingBuffer->GetDataForWriting(), - toRender->GetWidth(), toRender->GetHeight(), _hqxScalingBuffer->GetLineLength()); - _hqxScalingBuffer->Release(); - return _hqxScalingBuffer; -} - -} // namespace ALSW -} // namespace Engine -} // namespace AGS diff --git a/Engine/gfx/hq2x3x.h b/Engine/gfx/gfxfilter_sdl_renderer.cpp similarity index 53% rename from Engine/gfx/hq2x3x.h rename to Engine/gfx/gfxfilter_sdl_renderer.cpp index 3560d168910..c45e93664f8 100644 --- a/Engine/gfx/hq2x3x.h +++ b/Engine/gfx/gfxfilter_sdl_renderer.cpp @@ -11,20 +11,22 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= +#include "gfx/gfxfilter_sdl_renderer.h" -#ifndef __AC_HQ2X3X_H -#define __AC_HQ2X3X_H +namespace AGS +{ +namespace Engine +{ +namespace ALSW +{ -#include "core/platform.h" +const GfxFilterInfo SDLRendererGfxFilter::FilterInfo = GfxFilterInfo("StdScale", "Nearest-neighbour"); -#if AGS_PLATFORM_OS_ANDROID -void InitLUTs(){} -void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ){} -void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ){} -#else -void InitLUTs(); -void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ); -void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ); -#endif +const GfxFilterInfo &SDLRendererGfxFilter::GetInfo() const +{ + return FilterInfo; +} -#endif // __AC_HQ2X3X_H \ No newline at end of file +} // namespace ALSW +} // namespace Engine +} // namespace AGS diff --git a/Engine/gfx/gfxfilter_hqx.h b/Engine/gfx/gfxfilter_sdl_renderer.h similarity index 52% rename from Engine/gfx/gfxfilter_hqx.h rename to Engine/gfx/gfxfilter_sdl_renderer.h index d4a0f0de61a..a6276eef62e 100644 --- a/Engine/gfx/gfxfilter_hqx.h +++ b/Engine/gfx/gfxfilter_sdl_renderer.h @@ -12,14 +12,13 @@ // //============================================================================= // -// High quality x2 scaling filter +// SDL software renderer filter. Technically a non-op, as SDL_Renderer +// does the job. // //============================================================================= - -#ifndef __AGS_EE_GFX__HQ2XGFXFILTER_H -#define __AGS_EE_GFX__HQ2XGFXFILTER_H - -#include "gfx/gfxfilter_allegro.h" +#ifndef __AGS_EE_GFX__SDLRENDERERFILTER_H +#define __AGS_EE_GFX__SDLRENDERERFILTER_H +#include "gfx/gfxfilter_scaling.h" namespace AGS { @@ -28,31 +27,16 @@ namespace Engine namespace ALSW { -class HqxGfxFilter : public AllegroGfxFilter +class SDLRendererGfxFilter : public ScalingGfxFilter { public: - HqxGfxFilter(); - ~HqxGfxFilter() override; - - const GfxFilterInfo &GetInfo() const override; - - bool Initialize(const int color_depth, String &err_str) override; - Bitmap *InitVirtualScreen(Bitmap *screen, const Size src_size, const Rect dst_rect) override; - Bitmap *ShutdownAndReturnRealScreen() override; + virtual const GfxFilterInfo &GetInfo() const; static const GfxFilterInfo FilterInfo; - -protected: - Bitmap *PreRenderPass(Bitmap *toRender) override; - - typedef void (*PfnHqx)(unsigned char *in, unsigned char *out, int src_w, int src_h, int bpl); - - PfnHqx _pfnHqx; - Bitmap *_hqxScalingBuffer; }; } // namespace ALSW } // namespace Engine } // namespace AGS -#endif // __AGS_EE_GFX__HQ2XGFXFILTER_H +#endif // __AGS_EE_GFX__SDLRENDERERFILTER_H diff --git a/Engine/main/graphics_mode.cpp b/Engine/main/graphics_mode.cpp index 5e551dc7f82..4b311844b56 100644 --- a/Engine/main/graphics_mode.cpp +++ b/Engine/main/graphics_mode.cpp @@ -571,10 +571,6 @@ bool graphics_mode_set_dm(const DisplayMode &dm) // Tell Allegro new default bitmap color depth (must be done before set_gfx_mode) // TODO: this is also done inside ALSoftwareGraphicsDriver implementation; can remove one? set_color_depth(dm.ColorDepth); - // TODO: this is remains of the old code; find out what it means and do we - // need this if we are not using allegro software driver? - if (dm.RefreshRate >= 50) - request_refresh_rate(dm.RefreshRate); if (!gfxDriver->SetDisplayMode(dm, nullptr)) { diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 149f36411bc..a66442291a2 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -391,11 +391,10 @@ - - + @@ -681,15 +680,13 @@ - - + - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index eefd2d8eed2..08207e2734c 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -564,15 +564,9 @@ Source Files\gfx - - Source Files\gfx - Source Files\gfx - - Source Files\gfx - Source Files\gfx @@ -801,9 +795,6 @@ Library Sources\libcda - - Header Files\gfx - Source Files\game @@ -870,6 +861,12 @@ Source Files\platform\base + + Source Files\gfx + + + Source Files\gfx + @@ -1331,15 +1328,9 @@ Header Files\gfx - - Header Files\gfx - Header Files\gfx - - Header Files\gfx - Header Files\gfx @@ -1352,9 +1343,6 @@ Header Files\gfx - - Header Files\gfx - Header Files\script @@ -1745,6 +1733,9 @@ Header Files\platform\base + + Header Files\gfx + From f57767ece23aac1b089ca3ec5c31d6c7bc965ccd Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:26:56 +0300 Subject: [PATCH 16/41] Replaced few bare key codes with constants --- {Engine => Common}/ac/keycode.cpp | 0 {Engine => Common}/ac/keycode.h | 3 --- Common/gui/guitextbox.cpp | 7 +++---- Engine/ac/dialog.cpp | 4 ++-- Engine/ac/game.cpp | 2 +- Engine/ac/sys_events.cpp | 2 +- Engine/gui/cscidialog.cpp | 8 ++++---- Engine/gui/mylistbox.cpp | 9 +++++---- Engine/gui/mytextbox.cpp | 4 ++-- Engine/media/video/video.cpp | 3 ++- Engine/platform/windows/media/video/acwavi.cpp | 3 ++- Engine/platform/windows/media/video/acwavi3d.cpp | 3 ++- Solutions/Common.Lib/Common.Lib.vcxproj | 2 ++ Solutions/Common.Lib/Common.Lib.vcxproj.filters | 6 ++++++ Solutions/Engine.App/Engine.App.vcxproj | 2 -- Solutions/Engine.App/Engine.App.vcxproj.filters | 6 ------ 16 files changed, 32 insertions(+), 32 deletions(-) rename {Engine => Common}/ac/keycode.cpp (100%) rename {Engine => Common}/ac/keycode.h (97%) diff --git a/Engine/ac/keycode.cpp b/Common/ac/keycode.cpp similarity index 100% rename from Engine/ac/keycode.cpp rename to Common/ac/keycode.cpp diff --git a/Engine/ac/keycode.h b/Common/ac/keycode.h similarity index 97% rename from Engine/ac/keycode.h rename to Common/ac/keycode.h index f2df0ac3b02..834696cc0e7 100644 --- a/Engine/ac/keycode.h +++ b/Common/ac/keycode.h @@ -160,9 +160,6 @@ enum eAGSKeyCode eAGSKeyCodeAltX = 324 }; -#define AGS_KEYCODE_INSERT (eAGSKeyCodeInsert) -#define AGS_KEYCODE_DELETE (eAGSKeyCodeDelete) -#define AGS_KEYCODE_ALT_TAB (eAGSKeyCodeAltTab) #define READKEY_CODE_ALT_TAB 0x4000 // Gets a key code for "on_key_press" script callback diff --git a/Common/gui/guitextbox.cpp b/Common/gui/guitextbox.cpp index 5e05e289d6a..d18155b4e22 100644 --- a/Common/gui/guitextbox.cpp +++ b/Common/gui/guitextbox.cpp @@ -11,7 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - +#include "ac/keycode.h" #include "font/fonts.h" #include "gui/guimain.h" #include "gui/guitextbox.h" @@ -63,9 +63,8 @@ void GUITextBox::Draw(Bitmap *ds) void GUITextBox::OnKeyPress(int keycode) { guis_need_update = 1; - // TODO: use keycode constants // backspace, remove character - if (keycode == 8) + if (keycode == eAGSKeyCodeBackspace) { Text.ClipRight(1); return; @@ -74,7 +73,7 @@ void GUITextBox::OnKeyPress(int keycode) if ((keycode >= 128) && (!font_supports_extended_characters(Font))) return; // return/enter - if (keycode == 13) + if (keycode == eAGSKeyCodeReturn) { IsActivated = true; return; diff --git a/Engine/ac/dialog.cpp b/Engine/ac/dialog.cpp index faf17054a84..2d8a9bb9726 100644 --- a/Engine/ac/dialog.cpp +++ b/Engine/ac/dialog.cpp @@ -877,7 +877,7 @@ bool DialogOptions::Run() if (parserInput) { wantRefresh = true; // type into the parser - if ((gkey == 361) || ((gkey == ' ') && (strlen(parserInput->Text) == 0))) { + if ((gkey == eAGSKeyCodeF3) || ((gkey == eAGSKeyCodeSpace) && (strlen(parserInput->Text) == 0))) { // write previous contents into textbox (F3 or Space when box is empty) for (unsigned int i = strlen(parserInput->Text); i < strlen(play.lastParserEntry); i++) { parserInput->OnKeyPress(play.lastParserEntry[i]); @@ -886,7 +886,7 @@ bool DialogOptions::Run() Redraw(); return true; // continue running loop } - else if ((gkey >= 32) || (gkey == 13) || (gkey == 8)) { + else if ((gkey >= eAGSKeyCodeSpace) || (gkey == eAGSKeyCodeReturn) || (gkey == eAGSKeyCodeBackspace)) { parserInput->OnKeyPress(gkey); if (!parserInput->IsActivated) { //ags_domouse(DOMOUSE_DISABLE); diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index 91cbea7cff7..e38b4ae6704 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -1794,7 +1794,7 @@ bool check_skip_cutscene_keypress (int kgn) { CutsceneSkipStyle skip = get_cutscene_skipstyle(); if (skip == eSkipSceneAnyKey || skip == eSkipSceneKeyMouse || - (kgn == 27 && (skip == eSkipSceneEscOnly || skip == eSkipSceneEscOrRMB))) + (kgn == eAGSKeyCodeEscape && (skip == eSkipSceneEscOnly || skip == eSkipSceneEscOrRMB))) { start_skipping_cutscene(); return true; diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index 98e50cc216d..8231cc29f48 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -115,7 +115,7 @@ int ags_getch() { if (gott == READKEY_CODE_ALT_TAB) { // Alt+Tab, it gets stuck down unless we do this - gott = AGS_KEYCODE_ALT_TAB; + gott = eAGSKeyCodeAltTab; } #if AGS_PLATFORM_OS_MACOS else if (scancode == __allegro_KEY_BACKSPACE) diff --git a/Engine/gui/cscidialog.cpp b/Engine/gui/cscidialog.cpp index 98ec144c7b5..63753018bdc 100644 --- a/Engine/gui/cscidialog.cpp +++ b/Engine/gui/cscidialog.cpp @@ -159,14 +159,14 @@ int CSCIWaitMessage(CSCIMessage * cscim) smcode = 0; int keywas; if (run_service_key_controls(keywas) && !play.IsIgnoringInput()) { - if (keywas == 13) { + if (keywas == eAGSKeyCodeReturn) { cscim->id = finddefaultcontrol(CNF_DEFAULT); cscim->code = CM_COMMAND; - } else if (keywas == 27) { + } else if (keywas == eAGSKeyCodeEscape) { cscim->id = finddefaultcontrol(CNF_CANCEL); cscim->code = CM_COMMAND; - } else if ((keywas < 32) && (keywas != 8)) ; - else if ((keywas >= 372) & (keywas <= 381) & (finddefaultcontrol(CNT_LISTBOX) >= 0)) + } else if ((keywas < eAGSKeyCodeSpace) && (keywas != eAGSKeyCodeBackspace)) ; + else if ((keywas >= eAGSKeyCodeUpArrow) & (keywas <= eAGSKeyCodePageDown) & (finddefaultcontrol(CNT_LISTBOX) >= 0)) vobjs[finddefaultcontrol(CNT_LISTBOX)]->processmessage(CTB_KEYPRESS, keywas, 0); else if (finddefaultcontrol(CNT_TEXTBOX) >= 0) vobjs[finddefaultcontrol(CNT_TEXTBOX)]->processmessage(CTB_KEYPRESS, keywas, 0); diff --git a/Engine/gui/mylistbox.cpp b/Engine/gui/mylistbox.cpp index 66bba59d663..633ade75530 100644 --- a/Engine/gui/mylistbox.cpp +++ b/Engine/gui/mylistbox.cpp @@ -16,6 +16,7 @@ #include "util/wgt2allg.h" #include "ac/common.h" #include "ac/gamesetup.h" +#include "ac/keycode.h" #include "font/fonts.h" #include "gfx/bitmap.h" #include "gui/guidialog.h" @@ -165,16 +166,16 @@ extern int smcode; strcpy(itemnames[wParam], newstri); } else if (mcode == CTB_KEYPRESS) { - if ((wParam == 380) && (selected < items - 1)) + if ((wParam == eAGSKeyCodeDownArrow) && (selected < items - 1)) selected++; - if ((wParam == 372) && (selected > 0)) + if ((wParam == eAGSKeyCodeUpArrow) && (selected > 0)) selected--; - if (wParam == 373) + if (wParam == eAGSKeyCodePageUp) selected -= (numonscreen - 1); - if (wParam == 381) + if (wParam == eAGSKeyCodePageDown) selected += (numonscreen - 1); if ((selected < 0) && (items > 0)) diff --git a/Engine/gui/mytextbox.cpp b/Engine/gui/mytextbox.cpp index e6a5ee30b46..6c199f1bf2d 100644 --- a/Engine/gui/mytextbox.cpp +++ b/Engine/gui/mytextbox.cpp @@ -11,9 +11,9 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include #include "util/wgt2allg.h" +#include "ac/keycode.h" #include "font/fonts.h" #include "gui/mytextbox.h" #include "gui/guidialoginternaldefs.h" @@ -65,7 +65,7 @@ int MyTextBox::processmessage(int mcode, int wParam, long lParam) } else if (mcode == CTB_GETTEXT) strcpy((char *)lParam, text); else if (mcode == CTB_KEYPRESS) { - if (wParam == 8) { + if (wParam == eAGSKeyCodeBackspace) { if (text[0] != 0) text[strlen(text) - 1] = 0; diff --git a/Engine/media/video/video.cpp b/Engine/media/video/video.cpp index e2e1ebfc62c..00935b01205 100644 --- a/Engine/media/video/video.cpp +++ b/Engine/media/video/video.cpp @@ -30,6 +30,7 @@ #include "ac/gamesetupstruct.h" #include "ac/gamestate.h" #include "ac/global_display.h" +#include "ac/keycode.h" #include "ac/mouse.h" #include "ac/sys_events.h" #include "ac/runtime_defines.h" @@ -71,7 +72,7 @@ int check_if_user_input_should_cancel_video() { int key, mbut, mwheelz; if (run_service_key_controls(key)) { - if ((key==27) && (canabort==1)) + if ((key==eAGSKeyCodeEscape) && (canabort==1)) return 1; if (canabort >= 2) return 1; // skip on any key diff --git a/Engine/platform/windows/media/video/acwavi.cpp b/Engine/platform/windows/media/video/acwavi.cpp index 220695dfa09..8e8dc3240ad 100644 --- a/Engine/platform/windows/media/video/acwavi.cpp +++ b/Engine/platform/windows/media/video/acwavi.cpp @@ -32,6 +32,7 @@ #include // DirectDraw multimedia stream interfaces #include // Defines DEFINE_GUID macro and enables GUID initialization #include "ac/draw.h" +#include "ac/keycode.h" #include "gfx/bitmap.h" #include "gfx/graphicsdriver.h" #include "main/game_run.h" @@ -394,7 +395,7 @@ int dxmedia_play_video(const char* filename, bool pUseSound, int canskip, int st //Sleep(0); int key, mbut, mwheelz; if (run_service_key_controls(key)) { - if ((canskip == 1) && (key == 27)) + if ((canskip == 1) && (key == eAGSKeyCodeEscape)) break; if (canskip >= 2) break; diff --git a/Engine/platform/windows/media/video/acwavi3d.cpp b/Engine/platform/windows/media/video/acwavi3d.cpp index 93ece2d7ed6..64cba190195 100644 --- a/Engine/platform/windows/media/video/acwavi3d.cpp +++ b/Engine/platform/windows/media/video/acwavi3d.cpp @@ -34,6 +34,7 @@ #define _STRSAFE_H_INCLUDED_ typedef float D3DVALUE, *LPD3DVALUE; #include "ac/common.h" +#include "ac/keycode.h" #include "main/game_run.h" #include "media/video/VMR9Graph.h" #include "platform/base/sys_main.h" @@ -120,7 +121,7 @@ int dxmedia_play_video_3d(const char* filename, IDirect3DDevice9 *device, bool u int key, mbut, mwheelz; if (run_service_key_controls(key)) { - if ((canskip == 1) && (key == 27)) + if ((canskip == 1) && (key == eAGSKeyCodeEscape)) break; if (canskip >= 2) break; diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj b/Solutions/Common.Lib/Common.Lib.vcxproj index b9898f00a95..ee98ba3ef6a 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj +++ b/Solutions/Common.Lib/Common.Lib.vcxproj @@ -276,6 +276,7 @@ + @@ -373,6 +374,7 @@ + diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj.filters b/Solutions/Common.Lib/Common.Lib.vcxproj.filters index 68705a641d9..0f54eb4a586 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj.filters +++ b/Solutions/Common.Lib/Common.Lib.vcxproj.filters @@ -356,6 +356,9 @@ Library Sources\freetype + + Source Files\ac + @@ -619,5 +622,8 @@ Header Files\util + + Header Files\ac + \ No newline at end of file diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index a66442291a2..14f58145a7a 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -334,7 +334,6 @@ - @@ -612,7 +611,6 @@ - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index 08207e2734c..47a9a44f638 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -834,9 +834,6 @@ Source Files\platform\windows - - Source Files\ac - Source Files\ac @@ -1055,9 +1052,6 @@ Header Files\ac - - Header Files\ac - Header Files\ac From 7f385b301095dd4bd302dbbed562d517dcafa969 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:27:05 +0300 Subject: [PATCH 17/41] Replaced obscure mouse buttons constants with enum --- Engine/ac/dialog.cpp | 2 +- Engine/ac/game.cpp | 2 +- Engine/ac/invwindow.cpp | 6 +++--- Engine/ac/mouse.h | 5 ----- Engine/ac/sys_events.cpp | 6 +++--- Engine/ac/sys_events.h | 14 ++++++++++++++ Engine/device/mousew32.cpp | 15 ++++++--------- Engine/gui/mypushbutton.cpp | 6 ++---- Engine/main/game_run.cpp | 5 ++--- Engine/media/video/video.cpp | 2 +- Engine/plugin/global_plugin.cpp | 4 ++-- 11 files changed, 35 insertions(+), 32 deletions(-) diff --git a/Engine/ac/dialog.cpp b/Engine/ac/dialog.cpp index 2d8a9bb9726..02205725e45 100644 --- a/Engine/ac/dialog.cpp +++ b/Engine/ac/dialog.cpp @@ -957,7 +957,7 @@ bool DialogOptions::Run() parserActivated = 1; } - int mouseButtonPressed = NONE; + int mouseButtonPressed = MouseNone; int mouseWheelTurn = 0; if (run_service_mb_controls(mouseButtonPressed, mouseWheelTurn) && mouseButtonPressed >= 0 && !play.IsIgnoringInput()) diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index e38b4ae6704..570b2913e5d 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -1806,7 +1806,7 @@ bool check_skip_cutscene_mclick(int mbut) { CutsceneSkipStyle skip = get_cutscene_skipstyle(); if (skip == eSkipSceneMouse || skip == eSkipSceneKeyMouse || - (mbut == RIGHT && skip == eSkipSceneEscOrRMB)) + (mbut == MouseRight && skip == eSkipSceneEscOrRMB)) { start_skipping_cutscene(); return true; diff --git a/Engine/ac/invwindow.cpp b/Engine/ac/invwindow.cpp index f3bfbdc8f75..27c6be38519 100644 --- a/Engine/ac/invwindow.cpp +++ b/Engine/ac/invwindow.cpp @@ -375,10 +375,10 @@ bool InventoryScreen::Run() int mclick, mwheelz; if (!run_service_mb_controls(mclick, mwheelz) || play.IsIgnoringInput()) { - mclick = NONE; + mclick = MouseNone; } - if (mclick == LEFT) { + if (mclick == MouseLeft) { if ((mousey<0) | (mousey>windowhit) | (mousex<0) | (mousex>windowwid)) return true; // continue inventory screen loop if (mousey NONE) { + if (pluginSimulatedClick > MouseNone) { result = pluginSimulatedClick; - pluginSimulatedClick = NONE; + pluginSimulatedClick = MouseNone; } else { result = mgetbutton(); @@ -194,7 +194,7 @@ int ags_getch() { void ags_clear_input_buffer() { while (ags_kbhit()) ags_getch(); - while (mgetbutton() != NONE); + while (mgetbutton() != MouseNone); } void ags_wait_until_keypress() diff --git a/Engine/ac/sys_events.h b/Engine/ac/sys_events.h index b05bddc3592..ef7de0af254 100644 --- a/Engine/ac/sys_events.h +++ b/Engine/ac/sys_events.h @@ -18,6 +18,20 @@ #ifndef __AGS_EE_AC__SYS_EVENTS_H #define __AGS_EE_AC__SYS_EVENTS_H +// AGS own mouse button codes +// TODO: these were internal button codes, but AGS script uses different ones, +// which start with Left=1, and make more sense (0 is easier to use as "no value"). +// Must research if there are any dependencies to these internal values, and if not, +// then just replace these matching script ones! +// UPD: even plugin API seem to match script codes and require remap to internals. +enum eAGSMouseButton +{ + MouseNone = -1, + MouseLeft = 0, + MouseRight = 1, + MouseMiddle = 2 +}; + // Input handling // int ags_getch (); diff --git a/Engine/device/mousew32.cpp b/Engine/device/mousew32.cpp index 40305f5f897..c7d2688aec0 100644 --- a/Engine/device/mousew32.cpp +++ b/Engine/device/mousew32.cpp @@ -47,9 +47,7 @@ #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" #include "util/math.h" -#if AGS_SIMULATE_RIGHT_CLICK #include "ac/sys_events.h" // j for ags_iskeypressed -#endif using namespace AGS::Common; using namespace AGS::Engine; @@ -58,7 +56,6 @@ using namespace AGS::Engine; extern char lib_file_name[13]; const char *mouselibcopyr = "MouseLib32 (c) 1994, 1998 Chris Jones"; -const int NONE = -1, LEFT = 0, RIGHT = 1, MIDDLE = 2; char currentcursor = 0; // virtual mouse cursor coordinates int mousex = 0, mousey = 0, numcurso = -1, hotx = 0, hoty = 0; @@ -252,28 +249,28 @@ void mloadwcursor(char *namm) int butwas = 0; int mgetbutton() { - int toret = NONE; + int toret = MouseNone; poll_mouse(); int butis = mouse_b; if ((butis > 0) & (butwas > 0)) - return NONE; // don't allow holding button down + return MouseNone; // don't allow holding button down if (butis & 1) { - toret = LEFT; + toret = MouseLeft; #if AGS_SIMULATE_RIGHT_CLICK // j Ctrl-left click should be right-click if (ags_iskeypressed(__allegro_KEY_LCONTROL) || ags_iskeypressed(__allegro_KEY_RCONTROL)) { - toret = RIGHT; + toret = MouseRight; } #endif } else if (butis & 2) - toret = RIGHT; + toret = MouseRight; else if (butis & 4) - toret = MIDDLE; + toret = MouseMiddle; butwas = butis; return toret; diff --git a/Engine/gui/mypushbutton.cpp b/Engine/gui/mypushbutton.cpp index 449c6ac8a8b..f23a0f3702e 100644 --- a/Engine/gui/mypushbutton.cpp +++ b/Engine/gui/mypushbutton.cpp @@ -15,7 +15,7 @@ #include #include "util/wgt2allg.h" #include "ac/common.h" -#include "ac/mouse.h" +#include "ac/sys_events.h" #include "font/fonts.h" #include "gui/mypushbutton.h" #include "gui/guidialog.h" @@ -69,12 +69,10 @@ void MyPushButton::draw(Bitmap *ds) ds->DrawRect(Rect(x - 1, y - 1, x + wid + 1, y + hit + 1), draw_color); } -//extern const int LEFT; // in mousew32 - int MyPushButton::pressedon(int mousex, int mousey) { int wasstat; - while (mbutrelease(LEFT) == 0) { + while (mbutrelease(MouseLeft) == 0) { wasstat = state; state = mouseisinarea(mousex, mousey); diff --git a/Engine/main/game_run.cpp b/Engine/main/game_run.cpp index 24c838ef8a7..479eb3ab317 100644 --- a/Engine/main/game_run.cpp +++ b/Engine/main/game_run.cpp @@ -239,7 +239,7 @@ static void check_mouse_controls() wasbutdown=0; } - int mbut = NONE; + int mbut = MouseNone; int mwheelz = 0; if (run_service_mb_controls(mbut, mwheelz) && mbut >= 0) { @@ -369,7 +369,7 @@ bool run_service_mb_controls(int &mbut, int &mwheelz) { int mb = ags_mgetbutton(); int mz = ags_check_mouse_wheel(); - if (mb == NONE && mz == 0) + if (mb == MouseNone && mz == 0) return false; lock_mouse_on_click(); // do not claim mbut = mb; @@ -807,7 +807,6 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int our_eip=7; - // if (ags_mgetbutton()>NONE) break; update_polled_stuff_if_runtime(); game_loop_update_background_animation(); diff --git a/Engine/media/video/video.cpp b/Engine/media/video/video.cpp index 00935b01205..752a2e3e5bd 100644 --- a/Engine/media/video/video.cpp +++ b/Engine/media/video/video.cpp @@ -223,7 +223,7 @@ void play_flc_file(int numb,int playflags) { delete hicol_buf; hicol_buf=nullptr; // SetVirtualScreen(screen); wputblock(0,0,backbuffer,0); - while (ags_mgetbutton()!=NONE) { } // clear any queued mouse events. + while (ags_mgetbutton()!= MouseNone) { } // clear any queued mouse events. invalidate_screen(); } diff --git a/Engine/plugin/global_plugin.cpp b/Engine/plugin/global_plugin.cpp index 001841fe2d4..0ed32608292 100644 --- a/Engine/plugin/global_plugin.cpp +++ b/Engine/plugin/global_plugin.cpp @@ -18,10 +18,10 @@ #include #include "ac/global_plugin.h" -#include "ac/mouse.h" +#include "ac/sys_events.h" #include "util/string_compat.h" -int pluginSimulatedClick = NONE; +int pluginSimulatedClick = MouseNone; void PluginSimulateMouseClick(int pluginButtonID) { pluginSimulatedClick = pluginButtonID - 1; From d0550875213c7a546694fe09b9958ac16f4561cd Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:27:18 +0300 Subject: [PATCH 18/41] SDL-based mouse input Based on the work of @sonneveld (Nick Sonneveld). --- Engine/ac/mouse.cpp | 4 +- Engine/ac/room.cpp | 2 +- Engine/ac/sys_events.cpp | 214 +++++++++++++++++++++++------ Engine/ac/sys_events.h | 17 ++- Engine/device/mousew32.cpp | 138 ++++--------------- Engine/device/mousew32.h | 7 - Engine/gui/guidialoginternaldefs.h | 1 - Engine/platform/base/sys_main.cpp | 5 + Engine/platform/base/sys_main.h | 2 + 9 files changed, 220 insertions(+), 170 deletions(-) diff --git a/Engine/ac/mouse.cpp b/Engine/ac/mouse.cpp index eceb5e680ce..b5fcd8dbf56 100644 --- a/Engine/ac/mouse.cpp +++ b/Engine/ac/mouse.cpp @@ -24,6 +24,7 @@ #include "ac/global_mouse.h" #include "ac/global_plugin.h" #include "ac/global_screen.h" +#include "ac/sys_events.h" #include "ac/system.h" #include "ac/viewframe.h" #include "debug/debug_log.h" @@ -46,7 +47,6 @@ extern CharacterInfo*playerchar; extern IGraphicsDriver *gfxDriver; extern void ags_domouse(int str); -extern int misbuttondown(int buno); ScriptMouse scmouse; int cur_mode,cur_cursor; @@ -307,7 +307,7 @@ int GetCursorMode() { int IsButtonDown(int which) { if ((which < 1) || (which > 3)) quit("!IsButtonDown: only works with eMouseLeft, eMouseRight, eMouseMiddle"); - if (misbuttondown(which-1)) + if (ags_misbuttondown(which-1)) return 1; return 0; } diff --git a/Engine/ac/room.cpp b/Engine/ac/room.cpp index a073057249a..05553b4fc86 100644 --- a/Engine/ac/room.cpp +++ b/Engine/ac/room.cpp @@ -969,7 +969,7 @@ int find_highest_room_entered() { void first_room_initialization() { starting_room = displayed_room; set_loop_counter(0); - mouse_z_was = mouse_z; + mouse_z_was = sys_mouse_z; } void check_new_room() { diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index 13c04a54b33..f9ec7c71197 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -29,16 +29,9 @@ using namespace AGS::Engine; extern GameSetupStruct game; extern GameState play; -extern volatile unsigned long globalTimerCounter; -extern int pluginSimulatedClick; extern int displayed_room; extern char check_dynamic_sprites_at_exit; -extern void domouse(int str); -extern int mgetbutton(); -extern int misbuttondown(int buno); - -int mouse_z_was = 0; int ags_kbhit () { return keypressed(); @@ -52,43 +45,6 @@ int ags_iskeypressed (int keycode) { return 0; } -int ags_misbuttondown (int but) { - return misbuttondown(but); -} - -int ags_mgetbutton() { - int result; - - if (pluginSimulatedClick > MouseNone) { - result = pluginSimulatedClick; - pluginSimulatedClick = MouseNone; - } - else { - result = mgetbutton(); - } - return result; -} - -void ags_domouse (int what) { - // do mouse is "update the mouse x,y and also the cursor position", unless DOMOUSE_NOCURSOR is set. - if (what == DOMOUSE_NOCURSOR) - mgetgraphpos(); - else - domouse(what); -} - -int ags_check_mouse_wheel () { - int result = 0; - if ((mouse_z != mouse_z_was) && (game.options[OPT_MOUSEWHEEL] != 0)) { - if (mouse_z > mouse_z_was) - result = 1; - else - result = -1; - mouse_z_was = mouse_z; - } - return result; -} - int ags_getch() { const int read_key_value = readkey(); int gott = read_key_value; @@ -191,10 +147,167 @@ int ags_getch() { return gott; } + +// ---------------------------------------------------------------------------- +// MOUSE INPUT +// ---------------------------------------------------------------------------- +volatile int sys_mouse_x = 0; // mouse x position +volatile int sys_mouse_y = 0; // mouse y position +volatile int sys_mouse_z = 0; // mouse wheel position + + +// TODO: check later, if this may be useful in other places (then move to header) +enum eAGSMouseButtonMask +{ + MouseBitLeft = 0x01, + MouseBitRight = 0x02, + MouseBitMiddle = 0x04, + MouseBitX1 = 0x08, + MouseBitX2 = 0x10 +}; + +static int sdl_button_to_mask(int button) +{ + switch (button) { + case SDL_BUTTON_LEFT: return MouseBitLeft; + case SDL_BUTTON_RIGHT: return MouseBitRight; + case SDL_BUTTON_MIDDLE: return MouseBitMiddle; + case SDL_BUTTON_X1: return MouseBitX1; + case SDL_BUTTON_X2: return MouseBitX2; + } + return 0; +} + +/* [sonneveld] +Button tracking: +On OSX, some tap to click up/down events happen too quickly to be detected on the polled mouse_b global variable. +Instead we accumulate button presses over a couple of timer loops. +// TODO: check again when/if we replace polling with different event handling. +*/ +static int mouse_button_state = 0; +static int mouse_accum_button_state = 0; +static auto mouse_clear_at_time = AGS_Clock::now(); + +// Returns accumulated mouse button state and clears internal cache by timer +static int mouse_button_poll() +{ + auto now = AGS_Clock::now(); + int result = mouse_button_state | mouse_accum_button_state; + if (now >= mouse_clear_at_time) { + mouse_accum_button_state = 0; + mouse_clear_at_time = now + std::chrono::milliseconds(50); + } + return result; +} + +static void on_sdl_mouse_motion(const SDL_MouseMotionEvent &event) { + sys_mouse_x = event.x; + sys_mouse_y = event.y; +} + +static void on_sdl_mouse_button(const SDL_MouseButtonEvent &event) +{ + sys_mouse_x = event.x; + sys_mouse_y = event.y; + + if (event.type == SDL_MOUSEBUTTONDOWN) { + mouse_button_state |= sdl_button_to_mask(event.button); + mouse_accum_button_state |= sdl_button_to_mask(event.button); + } + else { + mouse_button_state &= ~sdl_button_to_mask(event.button); + } +} + +static void on_sdl_mouse_wheel(const SDL_MouseWheelEvent &event) +{ + sys_mouse_z += event.y; +} + +int butwas = 0; +int mgetbutton() +{ + int toret = MouseNone; + int butis = mouse_button_poll(); + + if ((butis > 0) & (butwas > 0)) + return MouseNone; // don't allow holding button down + + if (butis & MouseBitLeft) + toret = MouseLeft; + else if (butis & MouseBitRight) + toret = MouseRight; + else if (butis & MouseMiddle) + toret = MouseMiddle; + + butwas = butis; + return toret; + + // TODO: presumably this was a hack for 1-button Mac mouse; + // is this still necessary? + // find an elegant way to reimplement this; e.g. allow to configure key->mouse mappings?! +#define AGS_SIMULATE_RIGHT_CLICK (AGS_PLATFORM_OS_MACOS) +#if AGS_SIMULATE_RIGHT_CLICK__FIXME + // j Ctrl-left click should be right-click + if (ags_iskeypressed(__allegro_KEY_LCONTROL) || ags_iskeypressed(__allegro_KEY_RCONTROL)) + { + toret = RIGHT; + } +#endif +} + +extern int pluginSimulatedClick; +extern void domouse(int str); +int mouse_z_was = 0; +const int MB_ARRAY[3] = { MouseBitLeft, MouseBitRight, MouseBitMiddle }; + +bool ags_misbuttondown(int but) +{ + return mouse_button_poll() & MB_ARRAY[but]; +} + +int ags_mgetbutton() { + int result; + + if (pluginSimulatedClick > MouseNone) { + result = pluginSimulatedClick; + pluginSimulatedClick = MouseNone; + } + else { + result = mgetbutton(); + } + return result; +} + +void ags_domouse(int what) { + // do mouse is "update the mouse x,y and also the cursor position", unless DOMOUSE_NOCURSOR is set. + if (what == DOMOUSE_NOCURSOR) + mgetgraphpos(); + else + domouse(what); +} + +int ags_check_mouse_wheel() { + if (game.options[OPT_MOUSEWHEEL] == 0) { return 0; } + if (sys_mouse_z == mouse_z_was) { return 0; } + + int result = 0; + if (sys_mouse_z > mouse_z_was) + result = 1; // eMouseWheelNorth + else + result = -1; // eMouseWheelSouth + mouse_z_was = sys_mouse_z; + return result; +} + + + void ags_clear_input_buffer() { while (ags_kbhit()) ags_getch(); - while (mgetbutton() != MouseNone); + mouse_button_state = 0; + mouse_accum_button_state = 0; + mouse_clear_at_time = AGS_Clock::now() + std::chrono::milliseconds(50); } void ags_wait_until_keypress() @@ -246,6 +359,17 @@ void sys_evt_process_one(const SDL_Event &event) { break; } break; + // INPUT + case SDL_MOUSEMOTION: + on_sdl_mouse_motion(event.motion); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + on_sdl_mouse_button(event.button); + break; + case SDL_MOUSEWHEEL: + on_sdl_mouse_wheel(event.wheel); + break; } } diff --git a/Engine/ac/sys_events.h b/Engine/ac/sys_events.h index ef7de0af254..c0302e8a9dc 100644 --- a/Engine/ac/sys_events.h +++ b/Engine/ac/sys_events.h @@ -38,10 +38,21 @@ int ags_getch (); int ags_kbhit (); int ags_iskeypressed (int keycode); -int ags_misbuttondown (int but); +// Tells if the mouse button is currently down +bool ags_misbuttondown(int but); +// Returns mouse button code int ags_mgetbutton(); -void ags_domouse (int what); -int ags_check_mouse_wheel (); +// Updates mouse cursor position in game +void ags_domouse(int what); +// Returns -1 for wheel down and +1 for wheel up +// TODO: introduce constants for this +int ags_check_mouse_wheel(); + +// TODO: hide these later after refactoring mousew32.cpp +extern volatile int sys_mouse_x; // mouse x position +extern volatile int sys_mouse_y; // mouse y position +extern volatile int sys_mouse_z; // mouse wheel position + // Clears buffered keypresses and mouse clicks, if any void ags_clear_input_buffer(); diff --git a/Engine/device/mousew32.cpp b/Engine/device/mousew32.cpp index c7d2688aec0..d60f4d34c2c 100644 --- a/Engine/device/mousew32.cpp +++ b/Engine/device/mousew32.cpp @@ -22,23 +22,9 @@ //============================================================================= #include "core/platform.h" - -#define AGS_SIMULATE_RIGHT_CLICK (AGS_PLATFORM_OS_MACOS) - -#if AGS_PLATFORM_OS_WINDOWS -#include -#include -#include -#endif - #include "util/wgt2allg.h" - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - #include "ac/gamestate.h" +#include "ac/sys_events.h" #include "debug/out.h" #include "device/mousew32.h" #include "gfx/bitmap.h" @@ -47,22 +33,18 @@ #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" #include "util/math.h" -#include "ac/sys_events.h" // j for ags_iskeypressed using namespace AGS::Common; using namespace AGS::Engine; -extern char lib_file_name[13]; - -const char *mouselibcopyr = "MouseLib32 (c) 1994, 1998 Chris Jones"; char currentcursor = 0; // virtual mouse cursor coordinates int mousex = 0, mousey = 0, numcurso = -1, hotx = 0, hoty = 0; // real mouse coordinates and bounds -int real_mouse_x = 0, real_mouse_y = 0; -int boundx1 = 0, boundx2 = 99999, boundy1 = 0, boundy2 = 99999; -int disable_mgetgraphpos = 0; +static int real_mouse_x = 0, real_mouse_y = 0; +static int boundx1 = 0, boundx2 = 99999, boundy1 = 0, boundy2 = 99999; +static int disable_mgetgraphpos = 0; char ignore_bounds = 0; extern char alpha_blend_cursor ; Bitmap *mousecurs[MAXCURSORS]; @@ -91,18 +73,16 @@ namespace Mouse void AdjustPosition(int &x, int &y); } -void mgraphconfine(int x1, int y1, int x2, int y2) -{ - Mouse::ControlRect = Rect(x1, y1, x2, y2); - set_mouse_range(Mouse::ControlRect.Left, Mouse::ControlRect.Top, Mouse::ControlRect.Right, Mouse::ControlRect.Bottom); - Debug::Printf("Mouse confined: (%d,%d)-(%d,%d) (%dx%d)", - Mouse::ControlRect.Left, Mouse::ControlRect.Top, Mouse::ControlRect.Right, Mouse::ControlRect.Bottom, - Mouse::ControlRect.GetWidth(), Mouse::ControlRect.GetHeight()); -} - void mgetgraphpos() { - poll_mouse(); + // TODO: review and possibly rewrite whole thing; + // research what disable_mgetgraphpos does, and is this still necessary? + // disable or update mouse speed control to sdl + // (does sdl support mouse cursor speed? is it even necessary anymore?); + + // TODO: [sonneveld] find out where mgetgraphpos is needed, are events polled before that? + sys_evt_process_pending(); + if (disable_mgetgraphpos) { // The cursor coordinates are provided from alternate source; @@ -137,7 +117,7 @@ void mgetgraphpos() { real_mouse_x += dx; real_mouse_y += dy; - position_mouse(real_mouse_x, real_mouse_y); + sys_window_set_mouse(real_mouse_x, real_mouse_y); } // Otherwise, if real cursor was moved outside the control rect, yet we // are required to confine cursor inside one, then adjust cursor position @@ -146,7 +126,7 @@ void mgetgraphpos() { real_mouse_x = Math::Clamp(real_mouse_x + dx, Mouse::ControlRect.Left, Mouse::ControlRect.Right); real_mouse_y = Math::Clamp(real_mouse_y + dy, Mouse::ControlRect.Top, Mouse::ControlRect.Bottom); - position_mouse(real_mouse_x, real_mouse_y); + sys_window_set_mouse(real_mouse_x, real_mouse_y); } // Lastly, if the real cursor is out of the control rect, simply add // actual movement to keep up with the system cursor coordinates. @@ -163,8 +143,8 @@ void mgetgraphpos() else { // Save real cursor coordinates provided by system - real_mouse_x = mouse_x; - real_mouse_y = mouse_y; + real_mouse_x = sys_mouse_x; + real_mouse_y = sys_mouse_y; } // Set new in-game cursor position @@ -191,19 +171,17 @@ void msetcursorlimit(int x1, int y1, int x2, int y2) boundy2 = y2; } -int hotxwas = 0, hotywas = 0; +static int hotxwas = 0, hotywas = 0; void domouse(int str) { - /* - TO USE THIS ROUTINE YOU MUST LOAD A MOUSE CURSOR USING mloadcursor. - YOU MUST ALSO REMEMBER TO CALL mfreemem AT THE END OF THE PROGRAM. - */ int poow = mousecurs[currentcursor]->GetWidth(); int pooh = mousecurs[currentcursor]->GetHeight(); int smx = mousex - hotxwas, smy = mousey - hotywas; const Rect &viewport = play.GetMainViewport(); mgetgraphpos(); + + // temporarily adjust mousex/y. Original values returned at end of func. mousex -= hotx; mousey -= hoty; @@ -219,77 +197,11 @@ void domouse(int str) hotywas = hoty; } -int ismouseinbox(int lf, int tp, int rt, int bt) -{ - if ((mousex >= lf) & (mousex <= rt) & (mousey >= tp) & (mousey <= bt)) - return TRUE; - else - return FALSE; -} - -void mfreemem() -{ - for (int re = 0; re < numcurso; re++) { - delete mousecurs[re]; - } -} - - - - -void mloadwcursor(char *namm) -{ - color dummypal[256]; - if (wloadsprites(&dummypal[0], namm, mousecurs, 0, MAXCURSORS)) { - //printf("C_Load_wCursor: Error reading mouse cursor file\n"); - exit(1); - } -} - -int butwas = 0; -int mgetbutton() -{ - int toret = MouseNone; - poll_mouse(); - int butis = mouse_b; - - if ((butis > 0) & (butwas > 0)) - return MouseNone; // don't allow holding button down - - if (butis & 1) - { - toret = MouseLeft; -#if AGS_SIMULATE_RIGHT_CLICK - // j Ctrl-left click should be right-click - if (ags_iskeypressed(__allegro_KEY_LCONTROL) || ags_iskeypressed(__allegro_KEY_RCONTROL)) - { - toret = MouseRight; - } -#endif - } - else if (butis & 2) - toret = MouseRight; - else if (butis & 4) - toret = MouseMiddle; - - butwas = butis; - return toret; -} - -const int MB_ARRAY[3] = { 1, 2, 4 }; -int misbuttondown(int buno) -{ - poll_mouse(); - if (mouse_b & MB_ARRAY[buno]) - return TRUE; - return FALSE; -} - void msetgraphpos(int xa, int ya) { real_mouse_x = xa; real_mouse_y = ya; - position_mouse(real_mouse_x, real_mouse_y); + sys_window_set_mouse(real_mouse_x, real_mouse_y); } void msethotspot(int xx, int yy) @@ -300,7 +212,9 @@ void msethotspot(int xx, int yy) int minstalled() { - return install_mouse(); + // TODO: can SDL tell number of available/supported buttons at all, or whether mouse is present? + // this is not that critical, but maybe some game devs would like to detect if player has or not a mouse. + return 3; // SDL *theoretically* support 3 mouse buttons, but that does not mean they are physically present... } void Mouse::AdjustPosition(int &x, int &y) @@ -311,8 +225,10 @@ void Mouse::AdjustPosition(int &x, int &y) void Mouse::SetGraphicArea() { - Rect dst_r = GameScaling.ScaleRange(play.GetMainViewport()); - mgraphconfine(dst_r.Left, dst_r.Top, dst_r.Right, dst_r.Bottom); + Mouse::ControlRect = GameScaling.ScaleRange(play.GetMainViewport()); + Debug::Printf("Mouse cursor graphic area: (%d,%d)-(%d,%d) (%dx%d)", + Mouse::ControlRect.Left, Mouse::ControlRect.Top, Mouse::ControlRect.Right, Mouse::ControlRect.Bottom, + Mouse::ControlRect.GetWidth(), Mouse::ControlRect.GetHeight()); } void Mouse::SetMoveLimit(const Rect &r) diff --git a/Engine/device/mousew32.h b/Engine/device/mousew32.h index 165dfd80db2..de9bbe8005c 100644 --- a/Engine/device/mousew32.h +++ b/Engine/device/mousew32.h @@ -25,21 +25,15 @@ #define MAXCURSORS 20 -#include "util/geometry.h" namespace AGS { namespace Common { class Bitmap; } } using namespace AGS; // FIXME later void msetgraphpos(int,int); -// Sets the area of the screen within which the mouse can move -void mgraphconfine(int x1, int y1, int x2, int y2); void mgetgraphpos(); // Sets the area of the game frame (zero-based coordinates) where the mouse cursor is allowed to move; // this function was meant to be used to achieve gameplay effect void msetcursorlimit(int x1, int y1, int x2, int y2); -int ismouseinbox(int lf, int tp, int rt, int bt); -void mfreemem(); -void mloadwcursor(char *namm); void msetgraphpos(int xa, int ya); void msethotspot(int xx, int yy); int minstalled(); @@ -84,7 +78,6 @@ namespace Mouse extern int mousex, mousey; extern int hotx, hoty; -extern int disable_mgetgraphpos; extern char currentcursor; extern Common::Bitmap *mousecurs[MAXCURSORS]; diff --git a/Engine/gui/guidialoginternaldefs.h b/Engine/gui/guidialoginternaldefs.h index 53755d139a1..473dfa2f213 100644 --- a/Engine/gui/guidialoginternaldefs.h +++ b/Engine/gui/guidialoginternaldefs.h @@ -25,7 +25,6 @@ #undef WINAPI #endif #define WINAPI -extern int ags_misbuttondown (int but); #define mbutrelease(X) (!ags_misbuttondown(X)) #define TEXT_HT usetup.textheight diff --git a/Engine/platform/base/sys_main.cpp b/Engine/platform/base/sys_main.cpp index f12d5611f3c..a18449ad6a4 100644 --- a/Engine/platform/base/sys_main.cpp +++ b/Engine/platform/base/sys_main.cpp @@ -126,6 +126,11 @@ bool sys_window_lock_mouse(bool on) { return on; // TODO: test if successful? } +void sys_window_set_mouse(int x, int y) { + if (!window) return; + SDL_WarpMouseInWindow(window, x, y); +} + void sys_window_destroy() { if (window) { SDL_DestroyWindow(window); diff --git a/Engine/platform/base/sys_main.h b/Engine/platform/base/sys_main.h index 644eac82bee..2e6b7613bb2 100644 --- a/Engine/platform/base/sys_main.h +++ b/Engine/platform/base/sys_main.h @@ -53,6 +53,8 @@ bool sys_window_set_size(int w, int h, bool center); // Locks on unlocks mouse inside the window. // Returns new state of the mouse lock. bool sys_window_lock_mouse(bool on); +// Sets mouse position within the game window +void sys_window_set_mouse(int x, int y); // Destroy current game window, if one exists. void sys_window_destroy(); // Set window title text. From 6ec1876a92457ac5b71fc5dc6c17a4bfd61b0f1c Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:40:42 +0300 Subject: [PATCH 19/41] Rewrote mouse speed option relying on SDL, and made it off by default Mouse speed control was necessary mostly for Direct3D fullscreen, because Allegro4 had some issues with mouse input in that mode. SDL2 does not seem to have such problem. But I'd like to keep this functionality in the engine just in case, at least for some time. --- Engine/ac/gamesetup.cpp | 2 +- Engine/ac/gamestate.cpp | 2 +- Engine/ac/mouse.cpp | 20 ++---- Engine/ac/sys_events.cpp | 12 ++++ Engine/ac/sys_events.h | 2 + Engine/device/mousew32.cpp | 83 ++++++------------------ Engine/device/mousew32.h | 8 +-- Engine/main/config.cpp | 2 +- Engine/main/engine_setup.cpp | 8 +-- Engine/platform/base/agsplatformdriver.h | 2 - Engine/platform/windows/acplwin.cpp | 6 -- 11 files changed, 48 insertions(+), 99 deletions(-) diff --git a/Engine/ac/gamesetup.cpp b/Engine/ac/gamesetup.cpp index e5d0fd1e089..9c8dcd4dd42 100644 --- a/Engine/ac/gamesetup.cpp +++ b/Engine/ac/gamesetup.cpp @@ -28,7 +28,7 @@ GameSetup::GameSetup() override_upscale = false; mouse_speed = 1.f; mouse_ctrl_when = kMouseCtrl_Fullscreen; - mouse_ctrl_enabled = true; + mouse_ctrl_enabled = false; mouse_speed_def = kMouseSpeed_CurrentDisplay; RenderAtScreenRes = false; Supersampling = 1; diff --git a/Engine/ac/gamestate.cpp b/Engine/ac/gamestate.cpp index da4ec8079da..aaae28d48d4 100644 --- a/Engine/ac/gamestate.cpp +++ b/Engine/ac/gamestate.cpp @@ -63,7 +63,7 @@ void GameState::SetAutoRoomViewport(bool on) void GameState::SetMainViewport(const Rect &viewport) { _mainViewport.SetRect(viewport); - Mouse::SetGraphicArea(); + Mouse::UpdateGraphicArea(); scsystem.viewport_width = game_to_data_coord(_mainViewport.GetRect().GetWidth()); scsystem.viewport_height = game_to_data_coord(_mainViewport.GetRect().GetHeight()); _mainViewportHasChanged = true; diff --git a/Engine/ac/mouse.cpp b/Engine/ac/mouse.cpp index b5fcd8dbf56..819c7916ea6 100644 --- a/Engine/ac/mouse.cpp +++ b/Engine/ac/mouse.cpp @@ -320,23 +320,11 @@ int IsModeEnabled(int which) { void Mouse_EnableControl(bool on) { + bool should_control_mouse = + usetup.mouse_ctrl_when == kMouseCtrl_Always || + (usetup.mouse_ctrl_when == kMouseCtrl_Fullscreen && (scsystem.windowed == 0)); + Mouse::SetMovementControl(should_control_mouse & on); usetup.mouse_ctrl_enabled = on; // remember setting in config - - bool is_windowed = scsystem.windowed != 0; - // Whether mouse movement should be controlled by the engine - this is - // determined based on related config option. - bool should_control_mouse = usetup.mouse_ctrl_when == kMouseCtrl_Always || - (usetup.mouse_ctrl_when == kMouseCtrl_Fullscreen && !is_windowed); - // Whether mouse movement control is supported by the engine - this is - // determined on per platform basis. Some builds may not have such - // capability, e.g. because of how backend library implements mouse utils. - bool can_control_mouse = platform->IsMouseControlSupported(is_windowed); - // The resulting choice is made based on two aforementioned factors. - on &= should_control_mouse && can_control_mouse; - if (on) - Mouse::EnableControl(!is_windowed); - else - Mouse::DisableControl(); } //============================================================================= diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index f9ec7c71197..bfea2825dca 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -187,6 +187,7 @@ Instead we accumulate button presses over a couple of timer loops. static int mouse_button_state = 0; static int mouse_accum_button_state = 0; static auto mouse_clear_at_time = AGS_Clock::now(); +static int mouse_accum_relx = 0, mouse_accum_rely = 0; // Returns accumulated mouse button state and clears internal cache by timer static int mouse_button_poll() @@ -203,6 +204,8 @@ static int mouse_button_poll() static void on_sdl_mouse_motion(const SDL_MouseMotionEvent &event) { sys_mouse_x = event.x; sys_mouse_y = event.y; + mouse_accum_relx += event.xrel; + mouse_accum_rely += event.yrel; } static void on_sdl_mouse_button(const SDL_MouseButtonEvent &event) @@ -279,6 +282,13 @@ int ags_mgetbutton() { return result; } +void ags_mouse_get_relxy(int &x, int &y) { + x = mouse_accum_relx; + y = mouse_accum_rely; + mouse_accum_relx = 0; + mouse_accum_rely = 0; +} + void ags_domouse(int what) { // do mouse is "update the mouse x,y and also the cursor position", unless DOMOUSE_NOCURSOR is set. if (what == DOMOUSE_NOCURSOR) @@ -308,6 +318,8 @@ void ags_clear_input_buffer() mouse_button_state = 0; mouse_accum_button_state = 0; mouse_clear_at_time = AGS_Clock::now() + std::chrono::milliseconds(50); + mouse_accum_relx = 0; + mouse_accum_rely = 0; } void ags_wait_until_keypress() diff --git a/Engine/ac/sys_events.h b/Engine/ac/sys_events.h index c0302e8a9dc..29269b6c393 100644 --- a/Engine/ac/sys_events.h +++ b/Engine/ac/sys_events.h @@ -42,6 +42,8 @@ int ags_iskeypressed (int keycode); bool ags_misbuttondown(int but); // Returns mouse button code int ags_mgetbutton(); +// Returns recent relative mouse movement +void ags_mouse_get_relxy(int &x, int &y); // Updates mouse cursor position in game void ags_domouse(int what); // Returns -1 for wheel down and +1 for wheel up diff --git a/Engine/device/mousew32.cpp b/Engine/device/mousew32.cpp index d60f4d34c2c..32524b5c982 100644 --- a/Engine/device/mousew32.cpp +++ b/Engine/device/mousew32.cpp @@ -20,19 +20,14 @@ // Win32 (allegro) update (c) 1999 Chris Jones // //============================================================================= - -#include "core/platform.h" -#include "util/wgt2allg.h" +#include "device/mousew32.h" +#include #include "ac/gamestate.h" #include "ac/sys_events.h" #include "debug/out.h" -#include "device/mousew32.h" #include "gfx/bitmap.h" -#include "gfx/gfx_util.h" #include "main/graphics_mode.h" -#include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" -#include "util/math.h" using namespace AGS::Common; using namespace AGS::Engine; @@ -60,8 +55,6 @@ namespace Mouse Rect ControlRect; // Mouse control enabled flag bool ControlEnabled = false; - // Flag that tells whether the mouse must be forced to stay inside control rect - bool ConfineInCtrlRect = false; // Mouse speed value provided by user float SpeedVal = 1.f; // Mouse speed unit @@ -69,8 +62,8 @@ namespace Mouse // Actual speed factor (cached) float Speed = 1.f; - - void AdjustPosition(int &x, int &y); + // Converts real window coordinates to native game coords + void WindowToGame(int &x, int &y); } void mgetgraphpos() @@ -99,46 +92,11 @@ void mgetgraphpos() if (!switched_away && Mouse::ControlEnabled) { - // Control mouse movement by querying mouse mickeys (movement deltas) - // and applying them to saved mouse coordinates. - int mickey_x, mickey_y; - get_mouse_mickeys(&mickey_x, &mickey_y); - - // Apply mouse speed - int dx = Mouse::Speed * mickey_x; - int dy = Mouse::Speed * mickey_y; - - // - // Perform actual cursor update - //--------------------------------------------------------------------- - // If the real cursor is inside the control rectangle (read - game window), - // then apply sensitivity factors and adjust real cursor position - if (Mouse::ControlRect.IsInside(real_mouse_x + dx, real_mouse_y + dy)) - { - real_mouse_x += dx; - real_mouse_y += dy; - sys_window_set_mouse(real_mouse_x, real_mouse_y); - } - // Otherwise, if real cursor was moved outside the control rect, yet we - // are required to confine cursor inside one, then adjust cursor position - // to stay inside the rect's bounds. - else if (Mouse::ConfineInCtrlRect) - { - real_mouse_x = Math::Clamp(real_mouse_x + dx, Mouse::ControlRect.Left, Mouse::ControlRect.Right); - real_mouse_y = Math::Clamp(real_mouse_y + dy, Mouse::ControlRect.Top, Mouse::ControlRect.Bottom); - sys_window_set_mouse(real_mouse_x, real_mouse_y); - } - // Lastly, if the real cursor is out of the control rect, simply add - // actual movement to keep up with the system cursor coordinates. - else - { - real_mouse_x += mickey_x; - real_mouse_y += mickey_y; - } - - // Do not update the game cursor if the real cursor is beyond the control rect - if (!Mouse::ControlRect.IsInside(real_mouse_x, real_mouse_y)) - return; + // Use relative mouse movement; speed factor should already be applied by SDL in this mode + int rel_x, rel_y; + ags_mouse_get_relxy(rel_x, rel_y); + real_mouse_x = Math::Clamp(real_mouse_x + rel_x, Mouse::ControlRect.Left, Mouse::ControlRect.Right); + real_mouse_y = Math::Clamp(real_mouse_y + rel_y, Mouse::ControlRect.Top, Mouse::ControlRect.Bottom); } else { @@ -160,7 +118,7 @@ void mgetgraphpos() } // Convert to virtual coordinates - Mouse::AdjustPosition(mousex, mousey); + Mouse::WindowToGame(mousex, mousey); } void msetcursorlimit(int x1, int y1, int x2, int y2) @@ -217,13 +175,13 @@ int minstalled() return 3; // SDL *theoretically* support 3 mouse buttons, but that does not mean they are physically present... } -void Mouse::AdjustPosition(int &x, int &y) +void Mouse::WindowToGame(int &x, int &y) { x = GameScaling.X.UnScalePt(x) - play.GetMainViewport().Left; y = GameScaling.Y.UnScalePt(y) - play.GetMainViewport().Top; } -void Mouse::SetGraphicArea() +void Mouse::UpdateGraphicArea() { Mouse::ControlRect = GameScaling.ScaleRange(play.GetMainViewport()); Debug::Printf("Mouse cursor graphic area: (%d,%d)-(%d,%d) (%dx%d)", @@ -261,16 +219,15 @@ void Mouse::UnlockFromWindow() LockedToWindow = false; } -void Mouse::EnableControl(bool confine) +void Mouse::SetMovementControl(bool on) { - ControlEnabled = true; - ConfineInCtrlRect = confine; -} - -void Mouse::DisableControl() -{ - ControlEnabled = false; - ConfineInCtrlRect = false; + ControlEnabled = on; + SDL_SetRelativeMouseMode(static_cast(on)); + if (on) + SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, String::FromFormat("%.2f", Mouse::Speed).GetCStr()); + else + SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, "1.0"); + ags_clear_input_buffer(); } bool Mouse::IsControlEnabled() diff --git a/Engine/device/mousew32.h b/Engine/device/mousew32.h index de9bbe8005c..354fb292537 100644 --- a/Engine/device/mousew32.h +++ b/Engine/device/mousew32.h @@ -47,10 +47,8 @@ namespace Mouse // Unlock mouse from the game window void UnlockFromWindow(); - // Enable mouse movement control - void EnableControl(bool confine); - // Disable mouse movement control - void DisableControl(); + // Enable or disable mouse movement control + void SetMovementControl(bool on); // Tell if the mouse movement control is enabled bool IsControlEnabled(); // Set base speed factor, which would serve as a mouse speed unit @@ -67,7 +65,7 @@ namespace Mouse { // Updates limits of the area inside which the standard OS cursor is not shown; // uses game's main viewport (in native coordinates) to calculate real area on screen - void SetGraphicArea(); + void UpdateGraphicArea(); // Limits the area where the game cursor can move on virtual screen; // parameter must be in native game coordinates void SetMoveLimit(const Rect &r); diff --git a/Engine/main/config.cpp b/Engine/main/config.cpp index 97dbb09e176..1e9777e018e 100644 --- a/Engine/main/config.cpp +++ b/Engine/main/config.cpp @@ -456,7 +456,7 @@ void apply_config(const ConfigTree &cfg) break; } } - usetup.mouse_ctrl_enabled = INIreadint(cfg, "mouse", "control_enabled", 1) > 0; + usetup.mouse_ctrl_enabled = INIreadint(cfg, "mouse", "control_enabled", usetup.mouse_ctrl_enabled) > 0; const char *mouse_speed_options[kNumMouseSpeedDefs] = { "absolute", "current_display" }; mouse_str = INIreadstring(cfg, "mouse", "speed_def", "current_display"); for (int i = 0; i < kNumMouseSpeedDefs; ++i) diff --git a/Engine/main/engine_setup.cpp b/Engine/main/engine_setup.cpp index 01f606695e5..c44c4b730f7 100644 --- a/Engine/main/engine_setup.cpp +++ b/Engine/main/engine_setup.cpp @@ -292,8 +292,8 @@ void engine_post_gfxmode_mouse_setup(const DisplayMode &dm, const Size &init_des } Mouse_EnableControl(usetup.mouse_ctrl_enabled); - Debug::Printf(kDbgMsg_Info, "Mouse control: %s, base: %f, speed: %f", Mouse::IsControlEnabled() ? "on" : "off", - Mouse::GetSpeedUnit(), Mouse::GetSpeed()); + Debug::Printf(kDbgMsg_Info, "Mouse speed control: %s, unit: %f, user value: %f", + usetup.mouse_ctrl_enabled ? "enabled" : "disabled", Mouse::GetSpeedUnit(), Mouse::GetSpeed()); on_coordinates_scaling_changed(); @@ -306,7 +306,7 @@ void engine_post_gfxmode_mouse_setup(const DisplayMode &dm, const Size &init_des void engine_pre_gfxmode_mouse_cleanup() { // Always disable mouse control and unlock mouse when releasing down gfx mode - Mouse::DisableControl(); + Mouse::SetMovementControl(false); Mouse::UnlockFromWindow(); } @@ -359,7 +359,7 @@ void engine_pre_gfxsystem_shutdown() void on_coordinates_scaling_changed() { // Reset mouse graphic area and bounds - Mouse::SetGraphicArea(); + Mouse::UpdateGraphicArea(); // If mouse bounds do not have valid values yet, then limit cursor to viewport if (play.mboundx1 == 0 && play.mboundy1 == 0 && play.mboundx2 == 0 && play.mboundy2 == 0) Mouse::SetMoveLimit(play.GetMainViewport()); diff --git a/Engine/platform/base/agsplatformdriver.h b/Engine/platform/base/agsplatformdriver.h index 5b1653f9bcb..c85c00cf86e 100644 --- a/Engine/platform/base/agsplatformdriver.h +++ b/Engine/platform/base/agsplatformdriver.h @@ -75,8 +75,6 @@ struct AGSPlatformDriver virtual const char *GetGraphicsTroubleshootingText() { return ""; } virtual unsigned long GetDiskFreeSpaceMB() = 0; virtual const char* GetNoMouseErrorString() = 0; - // Tells whether build is capable of controlling mouse movement properly - virtual bool IsMouseControlSupported(bool windowed) { return false; } // Tells whether this platform's backend library deals with mouse cursor // virtual->real coordinate transformation itself (otherwise AGS engine should do it) virtual bool IsBackendResponsibleForMouseScaling() { return false; } diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index afbca81d6f3..cbd3ecdba83 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -112,7 +112,6 @@ struct AGSWin32 : AGSPlatformDriver { virtual const char *GetGraphicsTroubleshootingText(); virtual unsigned long GetDiskFreeSpaceMB(); virtual const char* GetNoMouseErrorString(); - virtual bool IsMouseControlSupported(bool windowed); virtual const char* GetAllegroFailUserHint(); virtual eScriptSystemOSID GetSystemOSID(); virtual int InitializeCDPlayer(); @@ -821,11 +820,6 @@ const char* AGSWin32::GetNoMouseErrorString() { return "No mouse was detected on your system, or your mouse is not configured to work with DirectInput. You must have a mouse to play this game."; } -bool AGSWin32::IsMouseControlSupported(bool windowed) -{ - return true; // supported for both fullscreen and windowed modes -} - const char* AGSWin32::GetAllegroFailUserHint() { return "Make sure you have DirectX 5 or above installed."; From 16c4631d35ef701fa88431a766edb6fb1203490b Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:40:53 +0300 Subject: [PATCH 20/41] Hide system cursor in SDL window --- Engine/main/engine.cpp | 4 +--- Engine/platform/base/sys_main.cpp | 4 ++++ Engine/platform/base/sys_main.h | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index f2ed6230ae2..a115b68239b 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -1361,9 +1361,7 @@ int initialize_engine(const ConfigTree &startup_opts) SetMultitasking(0); - // [ER] 2014-03-13 - // Hide the system cursor via allegro - show_os_cursor(MOUSE_CURSOR_NONE); + sys_window_show_cursor(false); // hide the system cursor show_preload(); diff --git a/Engine/platform/base/sys_main.cpp b/Engine/platform/base/sys_main.cpp index a18449ad6a4..61014e66a23 100644 --- a/Engine/platform/base/sys_main.cpp +++ b/Engine/platform/base/sys_main.cpp @@ -120,6 +120,10 @@ void sys_window_set_style(bool windowed) { SDL_SetWindowFullscreen(window, windowed ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); } +void sys_window_show_cursor(bool on) { + SDL_ShowCursor(on ? SDL_ENABLE : SDL_DISABLE); +} + bool sys_window_lock_mouse(bool on) { if (!window) return false; SDL_SetWindowGrab(window, static_cast(on)); diff --git a/Engine/platform/base/sys_main.h b/Engine/platform/base/sys_main.h index 2e6b7613bb2..4fab65cb1a8 100644 --- a/Engine/platform/base/sys_main.h +++ b/Engine/platform/base/sys_main.h @@ -50,6 +50,8 @@ SDL_Window *sys_get_window(); void sys_window_set_style(bool windowed); // Set new window size; optionally center new window on screen bool sys_window_set_size(int w, int h, bool center); +// Shows or hides system cursor when it's in the game window +void sys_window_show_cursor(bool on); // Locks on unlocks mouse inside the window. // Returns new state of the mouse lock. bool sys_window_lock_mouse(bool on); From 45f444423b3aaa98b800a87645c1cb33a107a068 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 16:41:07 +0300 Subject: [PATCH 21/41] Added SDL-AGS key code conversions, amended keycode tables Based on the work of @sonneveld (Nick Sonneveld) with certain simplifications. --- Common/ac/keycode.cpp | 29 ++++++-- Common/ac/keycode.h | 137 ++++++++++++++++++++++++++++------ Engine/ac/dialog.cpp | 2 +- Engine/ac/game.cpp | 2 +- Engine/ac/sys_events.cpp | 155 +++++++++++++++++++++++++++++++++++++++ Engine/ac/sys_events.h | 14 +++- Engine/main/game_run.cpp | 2 +- 7 files changed, 308 insertions(+), 33 deletions(-) diff --git a/Common/ac/keycode.cpp b/Common/ac/keycode.cpp index ba6b0390a38..3c8b5d5f577 100644 --- a/Common/ac/keycode.cpp +++ b/Common/ac/keycode.cpp @@ -1,12 +1,31 @@ - +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= #include "ac/keycode.h" - #include -int GetKeyForKeyPressCb(int keycode) +int AGSKeyToScriptKey(int keycode) +{ + // Script API requires strictly capital letters, if this is a small letter - capitalize it + return (keycode >= 'a' && keycode <= 'z') ? keycode - 'a' + 'A' : keycode; +} + +char AGSKeyToText(int keycode) { - // lower case 'a'..'z' do not exist as keycodes, only ascii. 'A'..'Z' do though! - return (keycode >= 'a' && keycode <= 'z') ? keycode - 32 : keycode; + // support only printable characters (128-255 are chars from extended fonts) + if (keycode >= 32 && keycode < 256) + return static_cast(keycode); + return 0; } int PlatformKeyFromAgsKey(int key) diff --git a/Common/ac/keycode.h b/Common/ac/keycode.h index 834696cc0e7..523474a0d67 100644 --- a/Common/ac/keycode.h +++ b/Common/ac/keycode.h @@ -23,9 +23,22 @@ #define EXTENDED_KEY_CODE ('\0') #define EXTENDED_KEY_CODE_MACOS ('?') +// Constant used to define Alt+Key codes #define AGS_EXT_KEY_SHIFT 300 +#define AGS_EXT_KEY_ALPHA(key) (AGS_EXT_KEY_SHIFT + (key - eAGSKeyCodeCtrlA) + 1) -// These are based on values in agsdefn.sh +// These are based on eKeyCode values in AGS Script. +// The actual values are based on scan codes of the old backend (allegro 3 and/or 4), +// which in turn mostly match ASCII values (at least for ones below 128), including +// Ctrl + letter combination codes. +// More codes are added at much higher ranges, for example Alt + letter combo codes +// are defined as 300 + letter's order. +// It should be specifically noted that eAGSKeyCode is directly conversible to ASCII +// at the range of 1 - 128, and AGS script makes use of this. +// Another important thing to note is that letter codes are always sent into script +// callbacks (like "on_key_pressed") in capitalized form, and that's how they are +// declared in script API (that's why in these callbacks user would have to check +// the Shift key state if they want to know if it's A or Shift + A). enum eAGSKeyCode { eAGSKeyCodeNone = 0, @@ -57,10 +70,12 @@ enum eAGSKeyCode eAGSKeyCodeCtrlY = 25, eAGSKeyCodeCtrlZ = 26, - eAGSKeyCodeBackspace = 8, - eAGSKeyCodeTab = 9, - eAGSKeyCodeReturn = 13, + eAGSKeyCodeBackspace = 8, // matches Ctrl + H + eAGSKeyCodeTab = 9, // matches Ctrl + I + eAGSKeyCodeReturn = 13, // matches Ctrl + M eAGSKeyCodeEscape = 27, + + /* printable chars - from eAGSKeyCodeSpace to eAGSKeyCode_z */ eAGSKeyCodeSpace = 32, eAGSKeyCodeExclamationMark = 33, eAGSKeyCodeDoubleQuote = 34, @@ -77,17 +92,6 @@ enum eAGSKeyCode eAGSKeyCodeHyphen = 45, eAGSKeyCodePeriod = 46, eAGSKeyCodeForwardSlash = 47, - eAGSKeyCodeColon = 58, - eAGSKeyCodeSemiColon = 59, - eAGSKeyCodeLessThan = 60, - eAGSKeyCodeEquals = 61, - eAGSKeyCodeGreaterThan = 62, - eAGSKeyCodeQuestionMark = 63, - eAGSKeyCodeAt = 64, - eAGSKeyCodeOpenBracket = 91, - eAGSKeyCodeBackSlash = 92, - eAGSKeyCodeCloseBracket = 93, - eAGSKeyCodeUnderscore = 95, eAGSKeyCode0 = 48, eAGSKeyCode1 = 49, @@ -100,8 +104,17 @@ enum eAGSKeyCode eAGSKeyCode8 = 56, eAGSKeyCode9 = 57, - eAGSKeyCodeA = 65, - eAGSKeyCodeB = 66, + eAGSKeyCodeColon = 58, + eAGSKeyCodeSemiColon = 59, + eAGSKeyCodeLessThan = 60, + eAGSKeyCodeEquals = 61, + eAGSKeyCodeGreaterThan = 62, + eAGSKeyCodeQuestionMark = 63, + eAGSKeyCodeAt = 64, // '@' + + /* Notice that default letter codes match capital ASCII letters */ + eAGSKeyCodeA = 65, // 'A' + eAGSKeyCodeB = 66, // 'B', etc eAGSKeyCodeC = 67, eAGSKeyCodeD = 68, eAGSKeyCodeE = 69, @@ -125,8 +138,44 @@ enum eAGSKeyCode eAGSKeyCodeW = 87, eAGSKeyCodeX = 88, eAGSKeyCodeY = 89, - eAGSKeyCodeZ = 90, + eAGSKeyCodeZ = 90, // 'Z' + eAGSKeyCodeOpenBracket = 91, + eAGSKeyCodeBackSlash = 92, + eAGSKeyCodeCloseBracket = 93, + eAGSKeyCodeCaret = 94, // '^' + eAGSKeyCodeUnderscore = 95, + eAGSKeyCodeBackquote = 96, // '`' + + /* Small ASCII letter codes are declared here for consistency, but unused in script callbacks */ + eAGSKeyCode_a = 97, // 'a' + eAGSKeyCode_b = 98, // 'b', etc + eAGSKeyCode_c = 99, + eAGSKeyCode_d = 100, + eAGSKeyCode_e = 101, + eAGSKeyCode_f = 102, + eAGSKeyCode_g = 103, + eAGSKeyCode_h = 104, + eAGSKeyCode_i = 105, + eAGSKeyCode_j = 106, + eAGSKeyCode_k = 107, + eAGSKeyCode_l = 108, + eAGSKeyCode_m = 109, + eAGSKeyCode_n = 110, + eAGSKeyCode_o = 111, + eAGSKeyCode_p = 112, + eAGSKeyCode_q = 113, + eAGSKeyCode_r = 114, + eAGSKeyCode_s = 115, + eAGSKeyCode_t = 116, + eAGSKeyCode_u = 117, + eAGSKeyCode_v = 118, + eAGSKeyCode_w = 119, + eAGSKeyCode_x = 120, + eAGSKeyCode_y = 121, + eAGSKeyCode_z = 122, // 'z' + + /* extended symbol codes */ eAGSKeyCodeF1 = AGS_EXT_KEY_SHIFT + 59, eAGSKeyCodeF2 = AGS_EXT_KEY_SHIFT + 60, eAGSKeyCodeF3 = AGS_EXT_KEY_SHIFT + 61, @@ -152,18 +201,58 @@ enum eAGSKeyCode eAGSKeyCodeInsert = AGS_EXT_KEY_SHIFT + 82, eAGSKeyCodeDelete = AGS_EXT_KEY_SHIFT + 83, + // not certain if necessary anymore (and not certain what was the origin of this value) eAGSKeyCodeAltTab = AGS_EXT_KEY_SHIFT + 99, - // These are only used by debugging and abort keys. - // They're based on allegro4 codes so I won't expand here. - eAGSKeyCodeAltV = 322, - eAGSKeyCodeAltX = 324 + // [sonneveld] These are only used by debugging and abort keys. + // They're based on allegro4 codes ... + eAGSKeyCodeAltV = AGS_EXT_KEY_ALPHA(eAGSKeyCodeV), + eAGSKeyCodeAltX = AGS_EXT_KEY_ALPHA(eAGSKeyCodeX), + + // These keys are not defined in the script eAGSKey enum but are in the manual + // https://adventuregamestudio.github.io/ags-manual/ASCIIcodes.html + // *Probably* made-up numbers not derived from allegro scan codes. + eAGSKeyCodeLShift = 403, + eAGSKeyCodeRShift = 404, + eAGSKeyCodeLCtrl = 405, + eAGSKeyCodeRCtrl = 406, + eAGSKeyCodeLAlt = 407, + + // [sonneveld] + // The following are the AGS_EXT_KEY_SHIFT, derived from applying arithmetic to the original keycodes. + // These do not have a corresponding ags key enum, do not appear in the manual and may not be accessible because of OS contraints. + eAGSKeyCodeRAlt = 420, + // TODO: judging that above works (at least on Win), following might also work, + // but idk which ones may be necessary; still keeping here this excerpt from an old code + // if they'd want to be restored (also add them to script API then!). + // Also see allegro 4's keyboard.h, where these were declared. + /* + case 392: __allegro_KEY_PRTSCR + case 393: __allegro_KEY_PAUSE + case 394: __allegro_KEY_ABNT_C1 // The ABNT_C1 (Brazilian) key + case 395: __allegro_KEY_YEN) + case 396: __allegro_KEY_KANA + case 397: __allegro_KEY_CONVERT + case 398: __allegro_KEY_NOCONVERT + case 400: __allegro_KEY_CIRCUMFLEX + case 402: __allegro_KEY_KANJI + case 421: __allegro_KEY_LWIN + case 422: __allegro_KEY_RWIN + case 423: __allegro_KEY_MENU + case 424: __allegro_KEY_SCRLOCK + case 425: __allegro_KEY_NUMLOCK + case 426: __allegro_KEY_CAPSLOCK + */ }; + #define READKEY_CODE_ALT_TAB 0x4000 -// Gets a key code for "on_key_press" script callback -int GetKeyForKeyPressCb(int keycode); +// Converts eAGSKeyCode to script API code, for "on_key_press" and similar callbacks +int AGSKeyToScriptKey(int keycode); +// Converts eAGSKeyCode to ASCII text representation with the range check; returns 0 on failure +// Not unicode compatible. +char AGSKeyToText(int keycode); // Allegro4 "platform" keycode from an AGS keycode. // Returns -1 if not found. diff --git a/Engine/ac/dialog.cpp b/Engine/ac/dialog.cpp index 02205725e45..d7141b899e1 100644 --- a/Engine/ac/dialog.cpp +++ b/Engine/ac/dialog.cpp @@ -898,7 +898,7 @@ bool DialogOptions::Run() else if (new_custom_render) { runDialogOptionKeyPressHandlerFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering); - runDialogOptionKeyPressHandlerFunc.params[1].SetInt32(GetKeyForKeyPressCb(gkey)); + runDialogOptionKeyPressHandlerFunc.params[1].SetInt32(AGSKeyToScriptKey(gkey)); run_function_on_non_blocking_thread(&runDialogOptionKeyPressHandlerFunc); } // Allow selection of options by keyboard shortcuts diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index 570b2913e5d..83e871ac7f7 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -945,7 +945,7 @@ ScriptCamera* Game_GetAnyCamera(int index) void Game_SimulateKeyPress(int key) { - int platformKey = GetKeyForKeyPressCb(key); + int platformKey = AGSKeyToScriptKey(key); platformKey = PlatformKeyFromAgsKey(platformKey); if (platformKey >= 0) { simulate_keypress(platformKey); diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index bfea2825dca..48c1761a80d 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -33,6 +33,161 @@ extern int displayed_room; extern char check_dynamic_sprites_at_exit; + +// Converts SDL scan and key codes to the ags keycode +eAGSKeyCode ags_keycode_from_sdl(const SDL_Keysym &key) +{ + const SDL_Keycode sym = key.sym; + const Uint16 mod = key.mod; + // Letter codes have special treatment depending on mods + if (sym >= SDLK_a && sym <= SDLK_z) + { + int agskey = sym; + // capitalize a letter if *any* mod is down (see why below) + if ((mod & (KMOD_SHIFT | KMOD_CTRL | KMOD_ALT)) != 0) + agskey = agskey - eAGSKeyCode_a + eAGSKeyCodeA; + // Ctrl and Alt combinations realign the letter code to certain offset + if ((mod & KMOD_CTRL) != 0) + agskey = 0 + (agskey - eAGSKeyCodeA) + 1; // align letters to code 1 + else if ((mod & KMOD_ALT) != 0) + agskey = AGS_EXT_KEY_SHIFT + (agskey - eAGSKeyCodeA) + 1; // align letters to code 301 + return static_cast(agskey); + } + // Rest of the printable characters seem to match 1:1 (and match ascii codes) + if (sym >= SDLK_SPACE && sym <= SDLK_BACKQUOTE) + { + return static_cast(sym); + } + + // Remaining codes may match or not, but we use a big table anyway. + // TODO: this is code by [sonneveld], + // double check that we must use scan codes here, maybe can use sdl key (sym) too? + switch (key.scancode) + { + case SDL_SCANCODE_BACKSPACE: return eAGSKeyCodeBackspace; + case SDL_SCANCODE_TAB: + case SDL_SCANCODE_KP_TAB: return eAGSKeyCodeTab; + case SDL_SCANCODE_RETURN: + case SDL_SCANCODE_RETURN2: + case SDL_SCANCODE_KP_ENTER: return eAGSKeyCodeReturn; + case SDL_SCANCODE_ESCAPE: return eAGSKeyCodeEscape; + + case SDL_SCANCODE_F1: return eAGSKeyCodeF1; + case SDL_SCANCODE_F2: return eAGSKeyCodeF2; + case SDL_SCANCODE_F3: return eAGSKeyCodeF3; + case SDL_SCANCODE_F4: return eAGSKeyCodeF4; + case SDL_SCANCODE_F5: return eAGSKeyCodeF5; + case SDL_SCANCODE_F6: return eAGSKeyCodeF6; + case SDL_SCANCODE_F7: return eAGSKeyCodeF7; + case SDL_SCANCODE_F8: return eAGSKeyCodeF8; + case SDL_SCANCODE_F9: return eAGSKeyCodeF9; + case SDL_SCANCODE_F10: return eAGSKeyCodeF10; + case SDL_SCANCODE_F11: return eAGSKeyCodeF11; + case SDL_SCANCODE_F12: return eAGSKeyCodeF12; + + case SDL_SCANCODE_KP_7: + case SDL_SCANCODE_HOME: return eAGSKeyCodeHome; + case SDL_SCANCODE_KP_8: + case SDL_SCANCODE_UP: return eAGSKeyCodeUpArrow; + case SDL_SCANCODE_KP_9: + case SDL_SCANCODE_PAGEUP: return eAGSKeyCodePageUp; + case SDL_SCANCODE_KP_4: + case SDL_SCANCODE_LEFT: return eAGSKeyCodeLeftArrow; + case SDL_SCANCODE_KP_5: return eAGSKeyCodeNumPad5; + case SDL_SCANCODE_KP_6: + case SDL_SCANCODE_RIGHT: return eAGSKeyCodeRightArrow; + case SDL_SCANCODE_KP_1: + case SDL_SCANCODE_END: return eAGSKeyCodeEnd; + case SDL_SCANCODE_KP_2: + case SDL_SCANCODE_DOWN: return eAGSKeyCodeDownArrow; + case SDL_SCANCODE_KP_3: + case SDL_SCANCODE_PAGEDOWN: return eAGSKeyCodePageDown; + case SDL_SCANCODE_KP_0: + case SDL_SCANCODE_INSERT: return eAGSKeyCodeInsert; + case SDL_SCANCODE_KP_PERIOD: + case SDL_SCANCODE_DELETE: return eAGSKeyCodeDelete; + + default: return eAGSKeyCodeNone; + } + return eAGSKeyCodeNone; +} + +// Converts ags key to SDL key scans (up to 3 values, because this is not a 1:1 match); +// NOTE: will ignore Ctrl+ or Alt+ script keys. +// TODO: double check and ammend later if anything is missing +bool ags_key_to_sdl_scan(eAGSKeyCode key, SDL_Scancode(&scan)[3]) +{ + scan[0] = SDL_SCANCODE_UNKNOWN; + scan[1] = SDL_SCANCODE_UNKNOWN; + scan[2] = SDL_SCANCODE_UNKNOWN; + SDL_Keycode sym = SDLK_UNKNOWN; + + // SDL sym codes happen to match small ASCII letters, so lowercase ours if necessary + if (key >= eAGSKeyCodeA && key <= eAGSKeyCodeZ) + { + sym = static_cast(key - eAGSKeyCodeA + SDLK_a); + } + // Rest of the printable characters seem to match (and match ascii codes) + else if (key >= eAGSKeyCodeSpace && key <= eAGSKeyCodeBackquote) + { + sym = static_cast(key); + } + + // If we have got key sym, convert it to SDL scancode using library's function + if (sym != SDLK_UNKNOWN) + { + scan[0] = SDL_GetScancodeFromKey(sym); + return true; + } + + // Other keys are mapped directly to scancode (based on [sonneveld]'s code) + switch (key) + { + case eAGSKeyCodeBackspace: scan[0] = SDL_SCANCODE_BACKSPACE; scan[1] = SDL_SCANCODE_KP_BACKSPACE; return true; + case eAGSKeyCodeTab: scan[0] = SDL_SCANCODE_TAB; scan[1] = SDL_SCANCODE_KP_TAB; return true; + case eAGSKeyCodeReturn: scan[0] = SDL_SCANCODE_RETURN; scan[1] = SDL_SCANCODE_RETURN2; scan[2] = SDL_SCANCODE_KP_ENTER; return true; + case eAGSKeyCodeEscape: scan[0] = SDL_SCANCODE_ESCAPE; return true; + + case eAGSKeyCodeF1: scan[0] = SDL_SCANCODE_F1; return true; + case eAGSKeyCodeF2: scan[0] = SDL_SCANCODE_F2; return true; + case eAGSKeyCodeF3: scan[0] = SDL_SCANCODE_F3; return true; + case eAGSKeyCodeF4: scan[0] = SDL_SCANCODE_F4; return true; + case eAGSKeyCodeF5: scan[0] = SDL_SCANCODE_F5; return true; + case eAGSKeyCodeF6: scan[0] = SDL_SCANCODE_F6; return true; + case eAGSKeyCodeF7: scan[0] = SDL_SCANCODE_F7; return true; + case eAGSKeyCodeF8: scan[0] = SDL_SCANCODE_F8; return true; + case eAGSKeyCodeF9: scan[0] = SDL_SCANCODE_F9; return true; + case eAGSKeyCodeF10: scan[0] = SDL_SCANCODE_F10; return true; + case eAGSKeyCodeF11: scan[0] = SDL_SCANCODE_F11; return true; + case eAGSKeyCodeF12: scan[0] = SDL_SCANCODE_F12; return true; + + case eAGSKeyCodeHome: scan[0] = SDL_SCANCODE_KP_7; scan[1] = SDL_SCANCODE_HOME; return true; + case eAGSKeyCodeUpArrow: scan[0] = SDL_SCANCODE_KP_8; scan[1] = SDL_SCANCODE_UP; return true; + case eAGSKeyCodePageUp: scan[0] = SDL_SCANCODE_KP_9; scan[1] = SDL_SCANCODE_PAGEUP; return true; + case eAGSKeyCodeLeftArrow: scan[0] = SDL_SCANCODE_KP_4; scan[1] = SDL_SCANCODE_LEFT; return true; + case eAGSKeyCodeNumPad5: scan[0] = SDL_SCANCODE_KP_5; return true; + case eAGSKeyCodeRightArrow: scan[0] = SDL_SCANCODE_KP_6; scan[1] = SDL_SCANCODE_RIGHT; return true; + case eAGSKeyCodeEnd: scan[0] = SDL_SCANCODE_KP_1; scan[1] = SDL_SCANCODE_END; return true; + case eAGSKeyCodeDownArrow: scan[0] = SDL_SCANCODE_KP_2; scan[1] = SDL_SCANCODE_DOWN; return true; + case eAGSKeyCodePageDown: scan[0] = SDL_SCANCODE_KP_3; scan[1] = SDL_SCANCODE_PAGEDOWN; return true; + case eAGSKeyCodeInsert: scan[0] = SDL_SCANCODE_KP_0; scan[1] = SDL_SCANCODE_INSERT; return true; + case eAGSKeyCodeDelete: scan[0] = SDL_SCANCODE_KP_PERIOD; scan[1] = SDL_SCANCODE_DELETE; return true; + + case eAGSKeyCodeLShift: scan[0] = SDL_SCANCODE_LSHIFT; return true; + case eAGSKeyCodeRShift: scan[0] = SDL_SCANCODE_RSHIFT; return true; + case eAGSKeyCodeLCtrl: scan[0] = SDL_SCANCODE_LCTRL; return true; + case eAGSKeyCodeRCtrl: scan[0] = SDL_SCANCODE_RCTRL; return true; + case eAGSKeyCodeLAlt: scan[0] = SDL_SCANCODE_LALT; return true; + case eAGSKeyCodeRAlt: scan[0] = SDL_SCANCODE_RALT; return true; + + default: return false; + } + return false; +} + + + + int ags_kbhit () { return keypressed(); } diff --git a/Engine/ac/sys_events.h b/Engine/ac/sys_events.h index 29269b6c393..46793bf8639 100644 --- a/Engine/ac/sys_events.h +++ b/Engine/ac/sys_events.h @@ -17,6 +17,8 @@ //============================================================================= #ifndef __AGS_EE_AC__SYS_EVENTS_H #define __AGS_EE_AC__SYS_EVENTS_H +#include +#include "ac/keycode.h" // AGS own mouse button codes // TODO: these were internal button codes, but AGS script uses different ones, @@ -32,12 +34,22 @@ enum eAGSMouseButton MouseMiddle = 2 }; -// Input handling +// Keyboard input handling // +// Converts SDL key data to eAGSKeyCode, which may be also directly used as an ASCII char +// if it is in proper range, see comments to eAGSKeyCode for details. +eAGSKeyCode ags_keycode_from_sdl(const SDL_Keysym &key); +// Converts eAGSKeyCode to SDL key scans (up to 3 values, because this is not a 1:1 match); +// NOTE: fails at Ctrl+ or Alt+ AGS keys, or any unknown key codes. +bool ags_key_to_sdl_scan(eAGSKeyCode key, SDL_Scancode(&scan)[3]); + + int ags_getch (); int ags_kbhit (); int ags_iskeypressed (int keycode); +// Mouse input handling +// // Tells if the mouse button is currently down bool ags_misbuttondown(int but); // Returns mouse button code diff --git a/Engine/main/game_run.cpp b/Engine/main/game_run.cpp index 479eb3ab317..3595230515a 100644 --- a/Engine/main/game_run.cpp +++ b/Engine/main/game_run.cpp @@ -539,7 +539,7 @@ static void check_keyboard_controls() } if (!keywasprocessed) { - kgn = GetKeyForKeyPressCb(kgn); + kgn = AGSKeyToScriptKey(kgn); debug_script_log("Running on_key_press keycode %d", kgn); setevent(EV_TEXTSCRIPT,TS_KEYPRESS,kgn); } From ee2f2d8eec7467813da6e6a3c08d54c5dd06e82a Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 29 Oct 2020 17:04:43 +0300 Subject: [PATCH 22/41] SDL-based keyboard input Based on the work of @sonneveld (Nick Sonneveld) with certain simplifications. This keeps original AGS keycodes (based on allegro scancodes, although that's irrelevant now) throughout the engine, and only replaces the way it's generated from backend events. Note that this won't be compatible with unicode text events, and simple AGS code will have to be replaced with something to optionally store unicode text as well. Also, in the future it may be beneficial to refactor event handling globally, and pass all wanted events to the engine components, either directly, or converted to convenient custom data. --- Common/ac/keycode.cpp | 132 ------------ Common/ac/keycode.h | 7 - Engine/ac/game.cpp | 6 +- Engine/ac/global_game.cpp | 144 +------------ Engine/ac/sys_events.cpp | 228 +++++++++------------ Engine/ac/sys_events.h | 44 +++- Engine/ac/system.cpp | 33 +-- Engine/ac/system.h | 1 - Engine/debug/debug.cpp | 6 +- Engine/main/engine.cpp | 11 +- Engine/main/game_run.cpp | 124 +++++------ Engine/main/game_run.h | 2 +- Engine/platform/base/agsplatformdriver.cpp | 6 - Engine/platform/base/agsplatformdriver.h | 1 - Engine/platform/windows/acplwin.cpp | 16 -- 15 files changed, 224 insertions(+), 537 deletions(-) diff --git a/Common/ac/keycode.cpp b/Common/ac/keycode.cpp index 3c8b5d5f577..4d44d91ade4 100644 --- a/Common/ac/keycode.cpp +++ b/Common/ac/keycode.cpp @@ -12,7 +12,6 @@ // //============================================================================= #include "ac/keycode.h" -#include int AGSKeyToScriptKey(int keycode) { @@ -28,134 +27,3 @@ char AGSKeyToText(int keycode) return 0; } -int PlatformKeyFromAgsKey(int key) -{ - int platformKey = -1; - - switch (key) { - // ctrl-[A-Z] keys are numbered 1-26 for A-Z - case eAGSKeyCodeCtrlA: platformKey = 1; break; - case eAGSKeyCodeCtrlB: platformKey = 2; break; - case eAGSKeyCodeCtrlC: platformKey = 3; break; - case eAGSKeyCodeCtrlD: platformKey = 4; break; - case eAGSKeyCodeCtrlE: platformKey = 5; break; - case eAGSKeyCodeCtrlF: platformKey = 6; break; - case eAGSKeyCodeCtrlG: platformKey = 7; break; - // case eAGSKeyCodeCtrlH: // overlap with backspace - // case eAGSKeyCodeCtrlI: // overlap with tab - case eAGSKeyCodeCtrlJ: platformKey = 10; break; - case eAGSKeyCodeCtrlK: platformKey = 11; break; - case eAGSKeyCodeCtrlL: platformKey = 12; break; - // case eAGSKeyCodeCtrlM: // overlap with return - case eAGSKeyCodeCtrlN: platformKey = 14; break; - case eAGSKeyCodeCtrlO: platformKey = 15; break; - case eAGSKeyCodeCtrlP: platformKey = 16; break; - case eAGSKeyCodeCtrlQ: platformKey = 17; break; - case eAGSKeyCodeCtrlR: platformKey = 18; break; - case eAGSKeyCodeCtrlS: platformKey = 19; break; - case eAGSKeyCodeCtrlT: platformKey = 20; break; - case eAGSKeyCodeCtrlU: platformKey = 21; break; - case eAGSKeyCodeCtrlV: platformKey = 22; break; - case eAGSKeyCodeCtrlW: platformKey = 23; break; - case eAGSKeyCodeCtrlX: platformKey = 24; break; - case eAGSKeyCodeCtrlY: platformKey = 25; break; - case eAGSKeyCodeCtrlZ: platformKey = 26; break; - - case eAGSKeyCodeBackspace: platformKey = (__allegro_KEY_BACKSPACE << 8) | 8; break; - case eAGSKeyCodeTab: platformKey = (__allegro_KEY_TAB << 8) | 9; break; - case eAGSKeyCodeReturn: platformKey = (__allegro_KEY_ENTER << 8) | 13; break; - case eAGSKeyCodeEscape: platformKey = (__allegro_KEY_ESC << 8) | 27; break; - case eAGSKeyCodeSpace: platformKey = (__allegro_KEY_SPACE << 8) | ' '; break; - case eAGSKeyCodeExclamationMark: platformKey = '!'; break; - case eAGSKeyCodeDoubleQuote: platformKey = '"'; break; - case eAGSKeyCodeHash: platformKey = '#'; break; - case eAGSKeyCodeDollar: platformKey = '$'; break; - case eAGSKeyCodePercent: platformKey = '%'; break; - case eAGSKeyCodeAmpersand: platformKey = '&'; break; - case eAGSKeyCodeSingleQuote: platformKey = '\''; break; - case eAGSKeyCodeOpenParenthesis: platformKey = '('; break; - case eAGSKeyCodeCloseParenthesis: platformKey = ')'; break; - case eAGSKeyCodeAsterisk: platformKey = '*'; break; - case eAGSKeyCodePlus: platformKey = '+'; break; - case eAGSKeyCodeComma: platformKey = ','; break; - case eAGSKeyCodeHyphen: platformKey = '-'; break; - case eAGSKeyCodePeriod: platformKey = '.'; break; - case eAGSKeyCodeForwardSlash: platformKey = '/'; break; - case eAGSKeyCodeColon: platformKey = ':'; break; - case eAGSKeyCodeSemiColon: platformKey = ';'; break; - case eAGSKeyCodeLessThan: platformKey = '<'; break; - case eAGSKeyCodeEquals: platformKey = '='; break; - case eAGSKeyCodeGreaterThan: platformKey = '>'; break; - case eAGSKeyCodeQuestionMark: platformKey = '?'; break; - case eAGSKeyCodeAt: platformKey = '@'; break; - case eAGSKeyCodeOpenBracket: platformKey = '['; break; - case eAGSKeyCodeBackSlash: platformKey = '\\'; break; - case eAGSKeyCodeCloseBracket: platformKey = ']'; break; - case eAGSKeyCodeUnderscore: platformKey = '_'; break; - - case eAGSKeyCode0: platformKey = (__allegro_KEY_0 << 8) | '0'; break; - case eAGSKeyCode1: platformKey = (__allegro_KEY_1 << 8) | '1'; break; - case eAGSKeyCode2: platformKey = (__allegro_KEY_2 << 8) | '2'; break; - case eAGSKeyCode3: platformKey = (__allegro_KEY_3 << 8) | '3'; break; - case eAGSKeyCode4: platformKey = (__allegro_KEY_4 << 8) | '4'; break; - case eAGSKeyCode5: platformKey = (__allegro_KEY_5 << 8) | '5'; break; - case eAGSKeyCode6: platformKey = (__allegro_KEY_6 << 8) | '6'; break; - case eAGSKeyCode7: platformKey = (__allegro_KEY_7 << 8) | '7'; break; - case eAGSKeyCode8: platformKey = (__allegro_KEY_8 << 8) | '8'; break; - case eAGSKeyCode9: platformKey = (__allegro_KEY_9 << 8) | '9'; break; - - case eAGSKeyCodeA: platformKey = (__allegro_KEY_A << 8) | 'a'; break; - case eAGSKeyCodeB: platformKey = (__allegro_KEY_B << 8) | 'b'; break; - case eAGSKeyCodeC: platformKey = (__allegro_KEY_C << 8) | 'c'; break; - case eAGSKeyCodeD: platformKey = (__allegro_KEY_D << 8) | 'd'; break; - case eAGSKeyCodeE: platformKey = (__allegro_KEY_E << 8) | 'e'; break; - case eAGSKeyCodeF: platformKey = (__allegro_KEY_F << 8) | 'f'; break; - case eAGSKeyCodeG: platformKey = (__allegro_KEY_G << 8) | 'g'; break; - case eAGSKeyCodeH: platformKey = (__allegro_KEY_H << 8) | 'h'; break; - case eAGSKeyCodeI: platformKey = (__allegro_KEY_I << 8) | 'i'; break; - case eAGSKeyCodeJ: platformKey = (__allegro_KEY_J << 8) | 'j'; break; - case eAGSKeyCodeK: platformKey = (__allegro_KEY_K << 8) | 'k'; break; - case eAGSKeyCodeL: platformKey = (__allegro_KEY_L << 8) | 'l'; break; - case eAGSKeyCodeM: platformKey = (__allegro_KEY_M << 8) | 'm'; break; - case eAGSKeyCodeN: platformKey = (__allegro_KEY_N << 8) | 'n'; break; - case eAGSKeyCodeO: platformKey = (__allegro_KEY_O << 8) | 'o'; break; - case eAGSKeyCodeP: platformKey = (__allegro_KEY_P << 8) | 'p'; break; - case eAGSKeyCodeQ: platformKey = (__allegro_KEY_Q << 8) | 'q'; break; - case eAGSKeyCodeR: platformKey = (__allegro_KEY_R << 8) | 'r'; break; - case eAGSKeyCodeS: platformKey = (__allegro_KEY_S << 8) | 's'; break; - case eAGSKeyCodeT: platformKey = (__allegro_KEY_T << 8) | 't'; break; - case eAGSKeyCodeU: platformKey = (__allegro_KEY_U << 8) | 'u'; break; - case eAGSKeyCodeV: platformKey = (__allegro_KEY_V << 8) | 'v'; break; - case eAGSKeyCodeW: platformKey = (__allegro_KEY_W << 8) | 'w'; break; - case eAGSKeyCodeX: platformKey = (__allegro_KEY_X << 8) | 'x'; break; - case eAGSKeyCodeY: platformKey = (__allegro_KEY_Y << 8) | 'y'; break; - case eAGSKeyCodeZ: platformKey = (__allegro_KEY_Z << 8) | 'z'; break; - - case eAGSKeyCodeF1: platformKey = __allegro_KEY_F1 << 8; break; - case eAGSKeyCodeF2: platformKey = __allegro_KEY_F2 << 8; break; - case eAGSKeyCodeF3: platformKey = __allegro_KEY_F3 << 8; break; - case eAGSKeyCodeF4: platformKey = __allegro_KEY_F4 << 8; break; - case eAGSKeyCodeF5: platformKey = __allegro_KEY_F5 << 8; break; - case eAGSKeyCodeF6: platformKey = __allegro_KEY_F6 << 8; break; - case eAGSKeyCodeF7: platformKey = __allegro_KEY_F7 << 8; break; - case eAGSKeyCodeF8: platformKey = __allegro_KEY_F8 << 8; break; - case eAGSKeyCodeF9: platformKey = __allegro_KEY_F9 << 8; break; - case eAGSKeyCodeF10: platformKey = __allegro_KEY_F10 << 8; break; - case eAGSKeyCodeF11: platformKey = __allegro_KEY_F11 << 8; break; - case eAGSKeyCodeF12: platformKey = __allegro_KEY_F12 << 8; break; - - case eAGSKeyCodeHome: platformKey = __allegro_KEY_HOME << 8; break; - case eAGSKeyCodeUpArrow: platformKey = __allegro_KEY_UP << 8; break; - case eAGSKeyCodePageUp: platformKey = __allegro_KEY_PGUP << 8; break; - case eAGSKeyCodeLeftArrow: platformKey = __allegro_KEY_LEFT << 8; break; - case eAGSKeyCodeNumPad5: platformKey = __allegro_KEY_5_PAD << 8; break; - case eAGSKeyCodeRightArrow: platformKey = __allegro_KEY_RIGHT << 8; break; - case eAGSKeyCodeEnd: platformKey = __allegro_KEY_END << 8; break; - case eAGSKeyCodeDownArrow: platformKey = __allegro_KEY_DOWN << 8; break; - case eAGSKeyCodePageDown: platformKey = __allegro_KEY_PGDN << 8; break; - case eAGSKeyCodeInsert: platformKey = __allegro_KEY_INSERT << 8; break; - case eAGSKeyCodeDelete: platformKey = __allegro_KEY_DEL << 8; break; - } - - return platformKey; -} diff --git a/Common/ac/keycode.h b/Common/ac/keycode.h index 523474a0d67..6499a4ee984 100644 --- a/Common/ac/keycode.h +++ b/Common/ac/keycode.h @@ -246,16 +246,9 @@ enum eAGSKeyCode }; -#define READKEY_CODE_ALT_TAB 0x4000 - // Converts eAGSKeyCode to script API code, for "on_key_press" and similar callbacks int AGSKeyToScriptKey(int keycode); // Converts eAGSKeyCode to ASCII text representation with the range check; returns 0 on failure // Not unicode compatible. char AGSKeyToText(int keycode); - -// Allegro4 "platform" keycode from an AGS keycode. -// Returns -1 if not found. -int PlatformKeyFromAgsKey(int key); - #endif // __AGS_EE_AC__KEYCODE_H diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index 83e871ac7f7..85b1d376473 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -945,11 +945,7 @@ ScriptCamera* Game_GetAnyCamera(int index) void Game_SimulateKeyPress(int key) { - int platformKey = AGSKeyToScriptKey(key); - platformKey = PlatformKeyFromAgsKey(platformKey); - if (platformKey >= 0) { - simulate_keypress(platformKey); - } + ags_simulate_keypress(static_cast(key)); } //============================================================================= diff --git a/Engine/ac/global_game.cpp b/Engine/ac/global_game.cpp index ea9cc97bb77..6b826a428a4 100644 --- a/Engine/ac/global_game.cpp +++ b/Engine/ac/global_game.cpp @@ -64,8 +64,6 @@ using namespace AGS::Common; -#define ALLEGRO_KEYBOARD_HANDLER - extern GameState play; extern ExecutingScript*curscript; extern int displayed_room; @@ -603,144 +601,12 @@ void GetLocationName(int xxx,int yyy,char*tempo) { } int IsKeyPressed (int keycode) { -#ifdef ALLEGRO_KEYBOARD_HANDLER - if (keyboard_needs_poll()) - poll_keyboard(); - - switch(keycode) { - case eAGSKeyCodeBackspace: return ags_iskeypressed(__allegro_KEY_BACKSPACE); break; - case eAGSKeyCodeTab: return ags_iskeypressed(__allegro_KEY_TAB); break; - case eAGSKeyCodeReturn: return ags_iskeypressed(__allegro_KEY_ENTER) || ags_iskeypressed(__allegro_KEY_ENTER_PAD); break; - case eAGSKeyCodeEscape: return ags_iskeypressed(__allegro_KEY_ESC); break; - case eAGSKeyCodeSpace: return ags_iskeypressed(__allegro_KEY_SPACE); break; - case eAGSKeyCodeSingleQuote: return ags_iskeypressed(__allegro_KEY_QUOTE); break; - case eAGSKeyCodeComma: return ags_iskeypressed(__allegro_KEY_COMMA); break; - case eAGSKeyCodePeriod: return ags_iskeypressed(__allegro_KEY_STOP); break; - case eAGSKeyCodeForwardSlash: return ags_iskeypressed(__allegro_KEY_SLASH) || ags_iskeypressed(__allegro_KEY_SLASH_PAD); break; - case eAGSKeyCodeBackSlash: return ags_iskeypressed(__allegro_KEY_BACKSLASH) || ags_iskeypressed(__allegro_KEY_BACKSLASH2); break; - case eAGSKeyCodeSemiColon: return ags_iskeypressed(__allegro_KEY_SEMICOLON); break; - case eAGSKeyCodeEquals: return ags_iskeypressed(__allegro_KEY_EQUALS) || ags_iskeypressed(__allegro_KEY_EQUALS_PAD); break; - case eAGSKeyCodeOpenBracket: return ags_iskeypressed(__allegro_KEY_OPENBRACE); break; - case eAGSKeyCodeCloseBracket: return ags_iskeypressed(__allegro_KEY_CLOSEBRACE); break; - // NOTE: we're treating EQUALS like PLUS, even though it is only available shifted. - case eAGSKeyCodePlus: return ags_iskeypressed(__allegro_KEY_EQUALS) || ags_iskeypressed(__allegro_KEY_PLUS_PAD); break; - case eAGSKeyCodeHyphen: return ags_iskeypressed(__allegro_KEY_MINUS) || ags_iskeypressed(__allegro_KEY_MINUS_PAD); break; - - // non-shifted versions of keys - case eAGSKeyCodeColon: return ags_iskeypressed(__allegro_KEY_COLON) || ags_iskeypressed(__allegro_KEY_COLON2); break; - case eAGSKeyCodeAsterisk: return ags_iskeypressed(__allegro_KEY_ASTERISK); break; - case eAGSKeyCodeAt: return ags_iskeypressed(__allegro_KEY_AT); break; - - case eAGSKeyCode0: return ags_iskeypressed(__allegro_KEY_0); break; - case eAGSKeyCode1: return ags_iskeypressed(__allegro_KEY_1); break; - case eAGSKeyCode2: return ags_iskeypressed(__allegro_KEY_2); break; - case eAGSKeyCode3: return ags_iskeypressed(__allegro_KEY_3); break; - case eAGSKeyCode4: return ags_iskeypressed(__allegro_KEY_4); break; - case eAGSKeyCode5: return ags_iskeypressed(__allegro_KEY_5); break; - case eAGSKeyCode6: return ags_iskeypressed(__allegro_KEY_6); break; - case eAGSKeyCode7: return ags_iskeypressed(__allegro_KEY_7); break; - case eAGSKeyCode8: return ags_iskeypressed(__allegro_KEY_8); break; - case eAGSKeyCode9: return ags_iskeypressed(__allegro_KEY_9); break; - - case eAGSKeyCodeA: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('A')); break; - case eAGSKeyCodeB: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('B')); break; - case eAGSKeyCodeC: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('C')); break; - case eAGSKeyCodeD: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('D')); break; - case eAGSKeyCodeE: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('E')); break; - case eAGSKeyCodeF: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('F')); break; - case eAGSKeyCodeG: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('G')); break; - case eAGSKeyCodeH: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('H')); break; - case eAGSKeyCodeI: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('I')); break; - case eAGSKeyCodeJ: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('J')); break; - case eAGSKeyCodeK: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('K')); break; - case eAGSKeyCodeL: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('L')); break; - case eAGSKeyCodeM: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('M')); break; - case eAGSKeyCodeN: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('N')); break; - case eAGSKeyCodeO: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('O')); break; - case eAGSKeyCodeP: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('P')); break; - case eAGSKeyCodeQ: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('Q')); break; - case eAGSKeyCodeR: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('R')); break; - case eAGSKeyCodeS: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('S')); break; - case eAGSKeyCodeT: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('T')); break; - case eAGSKeyCodeU: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('U')); break; - case eAGSKeyCodeV: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('V')); break; - case eAGSKeyCodeW: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('W')); break; - case eAGSKeyCodeX: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('X')); break; - case eAGSKeyCodeY: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('Y')); break; - case eAGSKeyCodeZ: return ags_iskeypressed(platform->ConvertKeycodeToScanCode('Z')); break; - - case eAGSKeyCodeF1: return ags_iskeypressed(__allegro_KEY_F1); break; - case eAGSKeyCodeF2: return ags_iskeypressed(__allegro_KEY_F2); break; - case eAGSKeyCodeF3: return ags_iskeypressed(__allegro_KEY_F3); break; - case eAGSKeyCodeF4: return ags_iskeypressed(__allegro_KEY_F4); break; - case eAGSKeyCodeF5: return ags_iskeypressed(__allegro_KEY_F5); break; - case eAGSKeyCodeF6: return ags_iskeypressed(__allegro_KEY_F6); break; - case eAGSKeyCodeF7: return ags_iskeypressed(__allegro_KEY_F7); break; - case eAGSKeyCodeF8: return ags_iskeypressed(__allegro_KEY_F8); break; - case eAGSKeyCodeF9: return ags_iskeypressed(__allegro_KEY_F9); break; - case eAGSKeyCodeF10: return ags_iskeypressed(__allegro_KEY_F10); break; - case eAGSKeyCodeF11: return ags_iskeypressed(__allegro_KEY_F11); break; - case eAGSKeyCodeF12: return ags_iskeypressed(__allegro_KEY_F12); break; - - case eAGSKeyCodeHome: return ags_iskeypressed(__allegro_KEY_HOME) || ags_iskeypressed(__allegro_KEY_7_PAD); break; - case eAGSKeyCodeUpArrow: return ags_iskeypressed(__allegro_KEY_UP) || ags_iskeypressed(__allegro_KEY_8_PAD); break; - case eAGSKeyCodePageUp: return ags_iskeypressed(__allegro_KEY_PGUP) || ags_iskeypressed(__allegro_KEY_9_PAD); break; - case eAGSKeyCodeLeftArrow: return ags_iskeypressed(__allegro_KEY_LEFT) || ags_iskeypressed(__allegro_KEY_4_PAD); break; - case eAGSKeyCodeNumPad5: return ags_iskeypressed(__allegro_KEY_5_PAD); break; - case eAGSKeyCodeRightArrow: return ags_iskeypressed(__allegro_KEY_RIGHT) || ags_iskeypressed(__allegro_KEY_6_PAD); break; - case eAGSKeyCodeEnd: return ags_iskeypressed(__allegro_KEY_END) || ags_iskeypressed(__allegro_KEY_1_PAD); break; - case eAGSKeyCodeDownArrow: return ags_iskeypressed(__allegro_KEY_DOWN) || ags_iskeypressed(__allegro_KEY_2_PAD); break; - case eAGSKeyCodePageDown: return ags_iskeypressed(__allegro_KEY_PGDN) || ags_iskeypressed(__allegro_KEY_3_PAD); break; - case eAGSKeyCodeInsert: return ags_iskeypressed(__allegro_KEY_INSERT) || ags_iskeypressed(__allegro_KEY_0_PAD); break; - case eAGSKeyCodeDelete: return ags_iskeypressed(__allegro_KEY_DEL) || ags_iskeypressed(__allegro_KEY_DEL_PAD); break; - - // These keys are not defined in the eAGSKey enum but are in the manual - // https://adventuregamestudio.github.io/ags-manual/ASCIIcodes.html - - case 403: return ags_iskeypressed(__allegro_KEY_LSHIFT); break; - case 404: return ags_iskeypressed(__allegro_KEY_RSHIFT); break; - case 405: return ags_iskeypressed(__allegro_KEY_LCONTROL); break; - case 406: return ags_iskeypressed(__allegro_KEY_RCONTROL); break; - case 407: return ags_iskeypressed(__allegro_KEY_ALT); break; - - // (noted here for interest) - // The following are the AGS_EXT_KEY_SHIFT, derived from applying arithmetic to the original keycodes. - // These do not have a corresponding ags key enum, do not appear in the manual and may not be accessible because of OS contraints. - - case 392: return ags_iskeypressed(__allegro_KEY_PRTSCR); break; - case 393: return ags_iskeypressed(__allegro_KEY_PAUSE); break; - case 394: return ags_iskeypressed(__allegro_KEY_ABNT_C1); break; // The ABNT_C1 (Brazilian) key - case 395: return ags_iskeypressed(__allegro_KEY_YEN); break; - case 396: return ags_iskeypressed(__allegro_KEY_KANA); break; - case 397: return ags_iskeypressed(__allegro_KEY_CONVERT); break; - case 398: return ags_iskeypressed(__allegro_KEY_NOCONVERT); break; - case 400: return ags_iskeypressed(__allegro_KEY_CIRCUMFLEX); break; - case 402: return ags_iskeypressed(__allegro_KEY_KANJI); break; - case 420: return ags_iskeypressed(__allegro_KEY_ALTGR); break; - case 421: return ags_iskeypressed(__allegro_KEY_LWIN); break; - case 422: return ags_iskeypressed(__allegro_KEY_RWIN); break; - case 423: return ags_iskeypressed(__allegro_KEY_MENU); break; - case 424: return ags_iskeypressed(__allegro_KEY_SCRLOCK); break; - case 425: return ags_iskeypressed(__allegro_KEY_NUMLOCK); break; - case 426: return ags_iskeypressed(__allegro_KEY_CAPSLOCK); break; - - // Allegro4 keys that were never supported: - // __allegro_KEY_COMMAND - // __allegro_KEY_TILDE - // __allegro_KEY_BACKQUOTE - - default: - // Remaining Allegro4 keycodes are offset by AGS_EXT_KEY_SHIFT - if (keycode >= AGS_EXT_KEY_SHIFT) { - if (ags_iskeypressed(keycode - AGS_EXT_KEY_SHIFT)) { return 1; } - } - debug_script_log("IsKeyPressed: unsupported keycode %d", keycode); - return 0; + auto status = ags_iskeydown(static_cast(keycode)); + if (status < 0) { + debug_script_log("IsKeyPressed: unsupported keycode %d", keycode); + return 0; } -#else - // old allegro version - quit("allegro keyboard handler not in use??"); -#endif + return status; } int SaveScreenShot(const char*namm) { diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index 48c1761a80d..59df8ff445f 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -12,51 +12,54 @@ // //============================================================================= #include "ac/sys_events.h" +#include #include #include "core/platform.h" #include "ac/common.h" #include "ac/gamesetupstruct.h" -#include "ac/gamestate.h" #include "ac/keycode.h" #include "ac/mouse.h" +#include "ac/timer.h" #include "device/mousew32.h" #include "platform/base/agsplatformdriver.h" -#include "ac/timer.h" using namespace AGS::Common; using namespace AGS::Engine; extern GameSetupStruct game; -extern GameState play; - -extern int displayed_room; -extern char check_dynamic_sprites_at_exit; - - // Converts SDL scan and key codes to the ags keycode -eAGSKeyCode ags_keycode_from_sdl(const SDL_Keysym &key) +eAGSKeyCode ags_keycode_from_sdl(const SDL_Event &event) { + // Printable ASCII characters are returned only from SDL_TEXTINPUT event, + // as it has key presses + mods correctly converted using current system locale already, + // so no need to do that manually. + // NOTE: keycodes such as SDLK_EXCLAIM ('!') could be misleading, as they are NOT + // received when user presses for example Shift + 1 on regular keyboard, but only on + // systems where single keypress can produce that symbol. + // NOTE: following will not work for Unicode, will need to reimplement whole thing + if (event.type == SDL_TEXTINPUT) + { + unsigned char textch = event.text.text[0]; + if (textch >= 32 && textch <= 255) { + return static_cast(textch); + } + return eAGSKeyCodeNone; + } + + if (event.type != SDL_KEYDOWN) + return eAGSKeyCodeNone; + + const SDL_Keysym key = event.key.keysym; const SDL_Keycode sym = key.sym; const Uint16 mod = key.mod; - // Letter codes have special treatment depending on mods + // Ctrl and Alt combinations realign the letter code to certain offset if (sym >= SDLK_a && sym <= SDLK_z) { - int agskey = sym; - // capitalize a letter if *any* mod is down (see why below) - if ((mod & (KMOD_SHIFT | KMOD_CTRL | KMOD_ALT)) != 0) - agskey = agskey - eAGSKeyCode_a + eAGSKeyCodeA; - // Ctrl and Alt combinations realign the letter code to certain offset - if ((mod & KMOD_CTRL) != 0) - agskey = 0 + (agskey - eAGSKeyCodeA) + 1; // align letters to code 1 - else if ((mod & KMOD_ALT) != 0) - agskey = AGS_EXT_KEY_SHIFT + (agskey - eAGSKeyCodeA) + 1; // align letters to code 301 - return static_cast(agskey); - } - // Rest of the printable characters seem to match 1:1 (and match ascii codes) - if (sym >= SDLK_SPACE && sym <= SDLK_BACKQUOTE) - { - return static_cast(sym); + if ((mod & KMOD_CTRL) != 0) // align letters to code 1 + return static_cast( 0 + (sym - SDLK_a) + 1 ); + else if ((mod & KMOD_ALT) != 0) // align letters to code 301 + return static_cast( AGS_EXT_KEY_SHIFT + (sym - SDLK_a) + 1 ); } // Remaining codes may match or not, but we use a big table anyway. @@ -188,118 +191,69 @@ bool ags_key_to_sdl_scan(eAGSKeyCode key, SDL_Scancode(&scan)[3]) -int ags_kbhit () { - return keypressed(); -} -int ags_iskeypressed (int keycode) { - if (keycode >= 0 && keycode < __allegro_KEY_MAX) - { - return key[keycode] != 0; - } - return 0; -} -int ags_getch() { - const int read_key_value = readkey(); - int gott = read_key_value; - const int scancode = ((gott >> 8) & 0x00ff); - const int ascii = (gott & 0x00ff); - - bool is_extended = (ascii == EXTENDED_KEY_CODE); - // On macos, the extended keycode is the ascii character '?' or '\0' if alt-key - // so check it's not actually the character '?' - #if AGS_PLATFORM_OS_MACOS && ! AGS_PLATFORM_OS_IOS - is_extended = is_extended || ((ascii == EXTENDED_KEY_CODE_MACOS) && (scancode != __allegro_KEY_SLASH)); - #endif - - /* char message[200]; - sprintf(message, "Scancode: %04X", gott); - Debug::Printf(message);*/ - - /*if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) { - // fix numeric pad keys if numlock is off (allegro 4.2 changed this behaviour) - if ((key_shifts & KB_NUMLOCK_FLAG) == 0) - gott = (gott & 0xff00) | EXTENDED_KEY_CODE; - }*/ - - if (gott == READKEY_CODE_ALT_TAB) - { - // Alt+Tab, it gets stuck down unless we do this - gott = eAGSKeyCodeAltTab; - } - #if AGS_PLATFORM_OS_MACOS - else if (scancode == __allegro_KEY_BACKSPACE) - { - gott = eAGSKeyCodeBackspace; - } - #endif - else if (is_extended) - { - // I believe we rely on a lot of keys being converted to ASCII, which is why - // the complete scan code list is not here. +// ---------------------------------------------------------------------------- +// KEYBOARD INPUT +// ---------------------------------------------------------------------------- - switch(scancode) - { - case __allegro_KEY_F1 : gott = eAGSKeyCodeF1 ; break; - case __allegro_KEY_F2 : gott = eAGSKeyCodeF2 ; break; - case __allegro_KEY_F3 : gott = eAGSKeyCodeF3 ; break; - case __allegro_KEY_F4 : gott = eAGSKeyCodeF4 ; break; - case __allegro_KEY_F5 : gott = eAGSKeyCodeF5 ; break; - case __allegro_KEY_F6 : gott = eAGSKeyCodeF6 ; break; - case __allegro_KEY_F7 : gott = eAGSKeyCodeF7 ; break; - case __allegro_KEY_F8 : gott = eAGSKeyCodeF8 ; break; - case __allegro_KEY_F9 : gott = eAGSKeyCodeF9 ; break; - case __allegro_KEY_F10 : gott = eAGSKeyCodeF10 ; break; - case __allegro_KEY_F11 : gott = eAGSKeyCodeF11 ; break; - case __allegro_KEY_F12 : gott = eAGSKeyCodeF12 ; break; - - case __allegro_KEY_INSERT : gott = eAGSKeyCodeInsert ; break; - case __allegro_KEY_DEL : gott = eAGSKeyCodeDelete ; break; - case __allegro_KEY_HOME : gott = eAGSKeyCodeHome ; break; - case __allegro_KEY_END : gott = eAGSKeyCodeEnd ; break; - case __allegro_KEY_PGUP : gott = eAGSKeyCodePageUp ; break; - case __allegro_KEY_PGDN : gott = eAGSKeyCodePageDown ; break; - case __allegro_KEY_LEFT : gott = eAGSKeyCodeLeftArrow ; break; - case __allegro_KEY_RIGHT : gott = eAGSKeyCodeRightArrow ; break; - case __allegro_KEY_UP : gott = eAGSKeyCodeUpArrow ; break; - case __allegro_KEY_DOWN : gott = eAGSKeyCodeDownArrow ; break; - - case __allegro_KEY_0_PAD : gott = eAGSKeyCodeInsert ; break; - case __allegro_KEY_1_PAD : gott = eAGSKeyCodeEnd ; break; - case __allegro_KEY_2_PAD : gott = eAGSKeyCodeDownArrow ; break; - case __allegro_KEY_3_PAD : gott = eAGSKeyCodePageDown ; break; - case __allegro_KEY_4_PAD : gott = eAGSKeyCodeLeftArrow ; break; - case __allegro_KEY_5_PAD : gott = eAGSKeyCodeNumPad5 ; break; - case __allegro_KEY_6_PAD : gott = eAGSKeyCodeRightArrow ; break; - case __allegro_KEY_7_PAD : gott = eAGSKeyCodeHome ; break; - case __allegro_KEY_8_PAD : gott = eAGSKeyCodeUpArrow ; break; - case __allegro_KEY_9_PAD : gott = eAGSKeyCodePageUp ; break; - case __allegro_KEY_DEL_PAD : gott = eAGSKeyCodeDelete ; break; - - default: - // no meaningful mappings - // this is how we accidentally got the alt-key mappings - gott = scancode + AGS_EXT_KEY_SHIFT; - } - } - else +// Because our game engine still uses input polling, we have to accumulate +// key events for our internal use whenever engine have to query key input. +static std::deque g_keyEvtQueue; + +bool ags_keyevent_ready() +{ + return g_keyEvtQueue.size() > 0; +} + +SDL_Event ags_get_next_keyevent() +{ + if (g_keyEvtQueue.size() > 0) { - // this includes ascii characters and ctrl-A-Z - gott = ascii; + auto evt = g_keyEvtQueue.front(); + g_keyEvtQueue.pop_front(); + return evt; } + SDL_Event empty = {}; + return empty; +} - // Alt+X, abort (but only once game is loaded) - if ((gott == play.abort_key) && (displayed_room >= 0)) { - check_dynamic_sprites_at_exit = 0; - quit("!|"); - } +int ags_iskeydown(eAGSKeyCode ags_key) +{ + SDL_PumpEvents(); + const Uint8 *state = SDL_GetKeyboardState(NULL); + SDL_Scancode scan[3]; + if (!ags_key_to_sdl_scan(ags_key, scan)) + return -1; + return (state[scan[0]] || state[scan[1]] || state[scan[2]]); +} - //sprintf(message, "Keypress: %d", gott); - //Debug::Printf(message); +void ags_simulate_keypress(eAGSKeyCode ags_key) +{ + SDL_Scancode scan[3]; + if (!ags_key_to_sdl_scan(ags_key, scan)) + return; + // Push a key event to the event queue; note that this won't affect the key states array + SDL_Event sdlevent = {}; + sdlevent.type = SDL_KEYDOWN; + sdlevent.key.keysym.sym = SDL_GetKeyFromScancode(scan[0]); + sdlevent.key.keysym.scancode = scan[0]; + SDL_PushEvent(&sdlevent); +} - return gott; +static void on_sdl_key_down(const SDL_Event &event) +{ + // Engine is not structured very well yet, and we cannot pass this event where it's needed; + // instead we save it in the queue where it will be ready whenever any component asks for one. + g_keyEvtQueue.push_back(event); +} + +static void on_sdl_textinput(const SDL_Event &event) +{ + // We also push text input events to the same queue, as this is only valid way to get proper + // text interpretation of the pressed key combination based on current system locale. + g_keyEvtQueue.push_back(event); } @@ -469,7 +423,7 @@ int ags_check_mouse_wheel() { void ags_clear_input_buffer() { - while (ags_kbhit()) ags_getch(); + g_keyEvtQueue.clear(); mouse_button_state = 0; mouse_accum_button_state = 0; mouse_clear_at_time = AGS_Clock::now() + std::chrono::milliseconds(50); @@ -477,12 +431,16 @@ void ags_clear_input_buffer() mouse_accum_rely = 0; } +// TODO: this is an awful function that should be removed eventually. +// Must replace with proper updateable game state. void ags_wait_until_keypress() { - while (!ags_kbhit()) { + do + { + sys_evt_process_pending(); platform->YieldCPU(); - } - ags_getch(); + } while (!ags_keyevent_ready()); + ags_clear_input_buffer(); } @@ -527,6 +485,12 @@ void sys_evt_process_one(const SDL_Event &event) { } break; // INPUT + case SDL_KEYDOWN: + on_sdl_key_down(event); + break; + case SDL_TEXTINPUT: + on_sdl_textinput(event); + break; case SDL_MOUSEMOTION: on_sdl_mouse_motion(event.motion); break; diff --git a/Engine/ac/sys_events.h b/Engine/ac/sys_events.h index 46793bf8639..efa9b291e99 100644 --- a/Engine/ac/sys_events.h +++ b/Engine/ac/sys_events.h @@ -17,8 +17,8 @@ //============================================================================= #ifndef __AGS_EE_AC__SYS_EVENTS_H #define __AGS_EE_AC__SYS_EVENTS_H -#include #include "ac/keycode.h" +#include // AGS own mouse button codes // TODO: these were internal button codes, but AGS script uses different ones, @@ -26,6 +26,7 @@ // Must research if there are any dependencies to these internal values, and if not, // then just replace these matching script ones! // UPD: even plugin API seem to match script codes and require remap to internals. +// UPD: or use SDL constants in the engine, but make conversion more visible by using a function. enum eAGSMouseButton { MouseNone = -1, @@ -34,19 +35,50 @@ enum eAGSMouseButton MouseMiddle = 2 }; + // Keyboard input handling // +// avoid including SDL.h here, at least for now, because that leads to conflicts with allegro +union SDL_Event; + // Converts SDL key data to eAGSKeyCode, which may be also directly used as an ASCII char // if it is in proper range, see comments to eAGSKeyCode for details. -eAGSKeyCode ags_keycode_from_sdl(const SDL_Keysym &key); +eAGSKeyCode ags_keycode_from_sdl(const SDL_Event &event); // Converts eAGSKeyCode to SDL key scans (up to 3 values, because this is not a 1:1 match); // NOTE: fails at Ctrl+ or Alt+ AGS keys, or any unknown key codes. bool ags_key_to_sdl_scan(eAGSKeyCode key, SDL_Scancode(&scan)[3]); +// Tells if key event refers to one of the mod-keys +inline bool is_mod_key(const SDL_Keysym &key) +{ + return key.scancode == SDL_SCANCODE_LCTRL || key.scancode == SDL_SCANCODE_RCTRL || + key.scancode == SDL_SCANCODE_LALT || key.scancode == SDL_SCANCODE_RALT || + key.scancode == SDL_SCANCODE_LSHIFT || key.scancode == SDL_SCANCODE_RSHIFT || + key.scancode == SDL_SCANCODE_MODE; +} + +// Converts mod key into merged mod (left & right) for easier handling +inline int make_merged_mod(int mod) +{ + int m_mod = 0; + if ((mod & KMOD_CTRL) != 0) m_mod |= KMOD_CTRL; + if ((mod & KMOD_SHIFT) != 0) m_mod |= KMOD_SHIFT; + if ((mod & KMOD_ALT) != 0) m_mod |= KMOD_ALT; + // what about KMOD_GUI, and there's also some SDL_SCANCODE_MODE? + return m_mod; +} + +// Tells if there are any buffered key events +bool ags_keyevent_ready(); +// Queries for the next key event in buffer; returns uninitialized data if none was queued +SDL_Event ags_get_next_keyevent(); +// Tells if the key is currently down, provided AGS key; +// Returns positive value if it's down, 0 if it's not, negative value if the key code is not supported. +// NOTE: for particular script codes this function returns positive if either of two keys are down. +int ags_iskeydown(eAGSKeyCode ags_key); +// Simulates key press with the given AGS key +void ags_simulate_keypress(eAGSKeyCode ags_key); -int ags_getch (); -int ags_kbhit (); -int ags_iskeypressed (int keycode); // Mouse input handling // @@ -68,6 +100,8 @@ extern volatile int sys_mouse_y; // mouse y position extern volatile int sys_mouse_z; // mouse wheel position +// Other input utilities +// // Clears buffered keypresses and mouse clicks, if any void ags_clear_input_buffer(); // Halts execution until any user input diff --git a/Engine/ac/system.cpp b/Engine/ac/system.cpp index ceb82fd1c66..ecabf31aea6 100644 --- a/Engine/ac/system.cpp +++ b/Engine/ac/system.cpp @@ -11,7 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - +#include #include "ac/common.h" #include "ac/draw.h" #include "ac/gamesetup.h" @@ -104,28 +104,23 @@ int System_GetHardwareAcceleration() int System_GetNumLock() { - return (key_shifts & KB_NUMLOCK_FLAG) ? 1 : 0; + SDL_PumpEvents(); + SDL_Keymod mod_state = SDL_GetModState(); + return (mod_state & KMOD_NUM) ? 1 : 0; } int System_GetCapsLock() { - return (key_shifts & KB_CAPSLOCK_FLAG) ? 1 : 0; + SDL_PumpEvents(); + SDL_Keymod mod_state = SDL_GetModState(); + return (mod_state & KMOD_CAPS) ? 1 : 0; } int System_GetScrollLock() { - return (key_shifts & KB_SCROLOCK_FLAG) ? 1 : 0; -} - -void System_SetNumLock(int newValue) -{ - // doesn't work ... maybe allegro doesn't implement this on windows - int ledState = key_shifts & (KB_SCROLOCK_FLAG | KB_CAPSLOCK_FLAG); - if (newValue) - { - ledState |= KB_NUMLOCK_FLAG; - } - set_leds(ledState); + SDL_PumpEvents(); + const Uint8 *state = SDL_GetKeyboardState(NULL); + return (state[SDL_SCANCODE_SCROLLLOCK]) ? 1 : 0; } int System_GetVsync() { @@ -279,12 +274,6 @@ RuntimeScriptValue Sc_System_GetNumLock(const RuntimeScriptValue *params, int32_ API_SCALL_INT(System_GetNumLock); } -// void (int newValue) -RuntimeScriptValue Sc_System_SetNumLock(const RuntimeScriptValue *params, int32_t param_count) -{ - API_SCALL_VOID_PINT(System_SetNumLock); -} - // int () RuntimeScriptValue Sc_System_GetOS(const RuntimeScriptValue *params, int32_t param_count) { @@ -397,7 +386,6 @@ void RegisterSystemAPI() ccAddExternalStaticFunction("System::get_HardwareAcceleration", Sc_System_GetHardwareAcceleration); ccAddExternalStaticFunction("System::get_HasInputFocus", Sc_System_GetHasInputFocus); ccAddExternalStaticFunction("System::get_NumLock", Sc_System_GetNumLock); - ccAddExternalStaticFunction("System::set_NumLock", Sc_System_SetNumLock); ccAddExternalStaticFunction("System::get_OperatingSystem", Sc_System_GetOS); ccAddExternalStaticFunction("System::get_RenderAtScreenResolution", Sc_System_GetRenderAtScreenResolution); ccAddExternalStaticFunction("System::set_RenderAtScreenResolution", Sc_System_SetRenderAtScreenResolution); @@ -427,7 +415,6 @@ void RegisterSystemAPI() ccAddExternalFunctionForPlugin("System::set_Gamma", (void*)System_SetGamma); ccAddExternalFunctionForPlugin("System::get_HardwareAcceleration", (void*)System_GetHardwareAcceleration); ccAddExternalFunctionForPlugin("System::get_NumLock", (void*)System_GetNumLock); - ccAddExternalFunctionForPlugin("System::set_NumLock", (void*)System_SetNumLock); ccAddExternalFunctionForPlugin("System::get_OperatingSystem", (void*)System_GetOS); ccAddExternalFunctionForPlugin("System::get_RuntimeInfo", (void*)System_GetRuntimeInfo); ccAddExternalFunctionForPlugin("System::get_ScreenHeight", (void*)System_GetScreenHeight); diff --git a/Engine/ac/system.h b/Engine/ac/system.h index b1f42e884c4..c19e856662b 100644 --- a/Engine/ac/system.h +++ b/Engine/ac/system.h @@ -31,7 +31,6 @@ int System_GetHardwareAcceleration(); int System_GetNumLock(); int System_GetCapsLock(); int System_GetScrollLock(); -void System_SetNumLock(int newValue); int System_GetVsync(); void System_SetVsync(int newValue); int System_GetWindowed(); diff --git a/Engine/debug/debug.cpp b/Engine/debug/debug.cpp index 4710495d5cf..059fe2c0f39 100644 --- a/Engine/debug/debug.cpp +++ b/Engine/debug/debug.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "core/platform.h" #include "ac/common.h" #include "ac/gamesetupstruct.h" @@ -609,9 +610,10 @@ void check_debug_keys() { if (play.debug_mode) { // do the run-time script debugging - if ((!key[KEY_SCRLOCK]) && (scrlockWasDown)) + const Uint8 *ks = SDL_GetKeyboardState(NULL); + if ((!ks[SDL_SCANCODE_SCROLLLOCK]) && (scrlockWasDown)) scrlockWasDown = 0; - else if ((key[KEY_SCRLOCK]) && (!scrlockWasDown)) { + else if ((ks[SDL_SCANCODE_SCROLLLOCK]) && (!scrlockWasDown)) { break_on_next_script_step = 1; scrlockWasDown = 1; diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index a115b68239b..e74d8db2e05 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -105,8 +105,6 @@ ResourcePaths ResPaths; t_engine_pre_init_callback engine_pre_init_callback = nullptr; -#define ALLEGRO_KEYBOARD_HANDLER - bool engine_init_allegro() { Debug::Printf(kDbgMsg_Info, "Initializing allegro"); @@ -416,14 +414,7 @@ void engine_locate_audio_pak() void engine_init_keyboard() { -#ifdef ALLEGRO_KEYBOARD_HANDLER - Debug::Printf(kDbgMsg_Info, "Initializing keyboard"); - - install_keyboard(); -#endif -#if AGS_PLATFORM_OS_LINUX - setlocale(LC_NUMERIC, "C"); // needed in X platform because install keyboard affects locale of printfs -#endif + /* do nothing */ } void engine_init_timer() diff --git a/Engine/main/game_run.cpp b/Engine/main/game_run.cpp index 3595230515a..0c063f7b720 100644 --- a/Engine/main/game_run.cpp +++ b/Engine/main/game_run.cpp @@ -87,6 +87,7 @@ extern RoomStatus*croom; extern CharacterExtras *charextra; extern SpriteCache spriteset; extern int cur_mode,cur_cursor; +extern char check_dynamic_sprites_at_exit; // Checks if user interface should remain disabled for now static int ShouldStayInWaitMode(); @@ -274,94 +275,103 @@ static void check_mouse_controls() setevent (EV_TEXTSCRIPT, TS_MCLICK, 8); } -// Returns current key modifiers; -// NOTE: annoyingly enough, on Windows (not sure about other platforms) -// Allegro API's 'key_shifts' variable seem to be always one step behind real -// situation: if first modifier gets pressed, 'key_shifts' will be zero, -// when second modifier gets pressed it will only contain first one, and so on. -static int get_active_shifts() -{ - int shifts = 0; - if (key[KEY_LSHIFT] || key[KEY_RSHIFT]) - shifts |= KB_SHIFT_FLAG; - if (key[KEY_LCONTROL] || key[KEY_RCONTROL]) - shifts |= KB_CTRL_FLAG; - if (key[KEY_ALT] || key[KEY_ALTGR]) - shifts |= KB_ALT_FLAG; - return shifts; -} -// Special flags to OR saved shift flags with: -// Shifts key combination already fired (wait until full shifts release) -#define KEY_SHIFTS_FIRED 0x80000000 + +// Special flags to OR saved SDL_Keymod flags with: +// Mod key combination already fired (wait until full mod release) +#define KEY_MODS_FIRED 0x80000000 + +int cur_key_mods = 0; +int old_key_mod = 0; // for saving previous key mods // Runs service key controls, returns false if service key combinations were handled // and no more processing required, otherwise returns true and provides current keycode and key shifts. -bool run_service_key_controls(int &kgn) +bool run_service_key_controls(int &out_key) { - // check keypresses - static int old_key_shifts = 0; // for saving shift modes - bool handled = false; - int kbhit_res = ags_kbhit(); - // First, check shifts - const int act_shifts = get_active_shifts(); + const bool key_valid = ags_keyevent_ready(); + const SDL_Event key_evt = key_valid ? ags_get_next_keyevent() : SDL_Event(); + const bool is_only_mod_key = key_evt.type == SDL_KEYDOWN ? is_mod_key(key_evt.key.keysym) : false; + + // Following section is for testing for pushed and released mod-keys. + // A bit of explanation: some service actions may require combination of + // mod-keys, for example [Ctrl + Alt] toggles mouse lock in window. + // Here comes a problem: other actions may also use [Ctrl + Alt] mods in + // combination with a third key: e.g. [Ctrl + Alt + V] displays engine info. + // For this reason we cannot simply test for pressed Ctrl and Alt here, + // but we must wait until player *releases at least one mod key* of this combo, + // while no third key was pressed. + // In other words, such action should only trigger if: + // * if combination of held down mod-keys was gathered, + // * if no other key was pressed meanwhile, + // * if at least one of those gathered mod-keys was released. + // + // TODO: maybe split this mod handling into sep procedure and make it easier to use (not that it's used alot)? + + // First, check mods + const int cur_mod = make_merged_mod(SDL_GetModState()); + // If shifts combination have already triggered an action, then do nothing // until new shifts are empty, in which case reset saved shifts - if (old_key_shifts & KEY_SHIFTS_FIRED) + if (old_key_mod & KEY_MODS_FIRED) { - if (act_shifts == 0) - old_key_shifts = 0; + if (cur_mod == 0) + old_key_mod = 0; } else { - // If any non-shift key is pressed, add fired flag to indicate that - // this is no longer a pure shifts key combination - if (kbhit_res) + // If any non-mod key is pressed, add fired flag to indicate that + // this is no longer a pure mod keys combination + if (key_valid && !is_only_mod_key) { - old_key_shifts = act_shifts | KEY_SHIFTS_FIRED; + old_key_mod = cur_mod | KEY_MODS_FIRED; } - // If all the previously registered shifts are still pressed, - // then simply resave new shift state. - else if ((old_key_shifts & act_shifts) == old_key_shifts) + // If all the previously registered mods are still pressed, + // then simply resave new mods state. + else if ((old_key_mod & cur_mod) == old_key_mod) { - old_key_shifts = act_shifts; + old_key_mod = cur_mod; } - // Otherwise some of the shifts were released, then run key combo action - // and set KEY_COMBO_FIRED flag to prevent multiple execution - else if (old_key_shifts) + // Otherwise some of the mods were released, then run key combo action + // and set KEY_MODS_FIRED flag to prevent multiple execution + else if (old_key_mod) { // Toggle mouse lock on Ctrl + Alt - if (old_key_shifts == (KB_ALT_FLAG | KB_CTRL_FLAG)) + if (old_key_mod == (KMOD_CTRL | KMOD_ALT)) { toggle_mouse_lock(); handled = true; } - old_key_shifts |= KEY_SHIFTS_FIRED; + old_key_mod |= KEY_MODS_FIRED; } } + cur_key_mods = cur_mod; - if (!kbhit_res || handled) - return false; + if (!key_valid) + return false; // if there was no key press, finish after handling current mod state + if (is_only_mod_key || handled) + return false; // rest of engine currently does not use pressed mod keys + // change this when it's no longer true (but be mindful about key-skipping!) - int keycode = ags_getch(); - // NS: I'm still not sure why we read a second key. - // Perhaps it's of a time when we read the keyboard one byte at a time? - // if (keycode == 0) - // keycode = ags_getch() + AGS_EXT_KEY_SHIFT; - if (keycode == 0) - return false; + int agskey = ags_keycode_from_sdl(key_evt); + if (agskey == eAGSKeyCodeNone) + return false; // should skip this key event - // LAlt or RAlt + Enter - // NOTE: for some reason LAlt + Enter produces same code as F9 - if (act_shifts == KB_ALT_FLAG && ((keycode == eAGSKeyCodeF9 && !key[KEY_F9]) || keycode == eAGSKeyCodeReturn)) + // LAlt or RAlt + Enter/Return + if ((cur_mod == KMOD_ALT) && agskey == eAGSKeyCodeReturn) { engine_try_switch_windowed_gfxmode(); return false; } - // No service operation triggered? return active keypress and shifts to caller - kgn = keycode; + // Alt+X, abort (but only once game is loaded) + if ((displayed_room >= 0) && (play.abort_key > 0 && agskey == play.abort_key)) { + check_dynamic_sprites_at_exit = 0; + quit("!|"); + } + + // No service operation triggered? return active keypress and mods to caller + out_key = agskey; return true; } @@ -486,7 +496,7 @@ static void check_keyboard_controls() // return; // } - if ((kgn == eAGSKeyCodeAltV) && (key[KEY_LCONTROL] || key[KEY_RCONTROL]) && (play.wait_counter < 1) && (is_text_overlay == 0) && (restrict_until == 0)) { + if ((kgn == eAGSKeyCodeAltV) && ((cur_key_mods & KMOD_CTRL) != 0) && (play.wait_counter < 1) && (is_text_overlay == 0) && (restrict_until == 0)) { // make sure we can't interrupt a Wait() // and desync the music to cutscene play.debug_mode++; diff --git a/Engine/main/game_run.h b/Engine/main/game_run.h index 450cd3ba750..26b90797dee 100644 --- a/Engine/main/game_run.h +++ b/Engine/main/game_run.h @@ -38,7 +38,7 @@ void UpdateGameOnce(bool checkControls = false, IDriverDependantBitmap *extraBit // Gets current logical game FPS, this is normally a fixed number set in script; // in case of "maxed fps" mode this function returns real measured FPS. float get_current_fps(); -// Runs service key controls, returns false if key input was claimed by the engine, +// Runs service key controls, returns false if no key was pressed or key input was claimed by the engine, // otherwise returns true and provides a keycode. bool run_service_key_controls(int &kgn); // Runs service mouse controls, returns false if mouse input was claimed by the engine, diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index 678480c3be4..1d2cfc25897 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -110,12 +110,6 @@ SetupReturnValue AGSPlatformDriver::RunSetup(const ConfigTree &cfg_in, ConfigTre return kSetup_Cancel; } -int AGSPlatformDriver::ConvertKeycodeToScanCode(int keycode) -{ - keycode -= ('A' - KEY_A); - return keycode; -} - //----------------------------------------------- // IOutputHandler implementation //----------------------------------------------- diff --git a/Engine/platform/base/agsplatformdriver.h b/Engine/platform/base/agsplatformdriver.h index c85c00cf86e..f1f6f76e8e7 100644 --- a/Engine/platform/base/agsplatformdriver.h +++ b/Engine/platform/base/agsplatformdriver.h @@ -99,7 +99,6 @@ struct AGSPlatformDriver virtual void ResumeApplication(); virtual void RegisterGameWithGameExplorer(); virtual void UnRegisterGameWithGameExplorer(); - virtual int ConvertKeycodeToScanCode(int keyCode); // Adjust window size to ensure it is in the supported limits virtual void ValidateWindowSize(int &x, int &y, bool borderless) const {} diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index cbd3ecdba83..b558687706f 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -125,7 +125,6 @@ struct AGSWin32 : AGSPlatformDriver { virtual void ResumeApplication(); virtual void RegisterGameWithGameExplorer(); virtual void UnRegisterGameWithGameExplorer(); - virtual int ConvertKeycodeToScanCode(int keyCode); virtual void ValidateWindowSize(int &x, int &y, bool borderless) const; #ifndef AGS_NO_VIDEO_PLAYER @@ -939,21 +938,6 @@ void AGSWin32::ShutdownCDPlayer() { cd_exit(); } -extern "C" const unsigned char hw_to_mycode[256]; - -int AGSWin32::ConvertKeycodeToScanCode(int keycode) -{ - // ** HIDEOUS HACK TO WORK AROUND ALLEGRO BUG - // the key[] array is hardcoded to qwerty keyboards, so we - // have to re-map it to make it work on other keyboard layouts - keycode += ('a' - 'A'); - int vkey = VkKeyScan(keycode); - int scancode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC); - if ((scancode >= 0) && (scancode < 256)) - keycode = hw_to_mycode[scancode]; - return keycode; -} - void AGSWin32::ValidateWindowSize(int &x, int &y, bool borderless) const { RECT wa_rc, nc_rc; From eda1755cdb7546005b00a8c62620e9e38e1a8671 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Mon, 2 Nov 2020 03:28:08 +0300 Subject: [PATCH 23/41] Use SDL_Get/SetError instead of allegro_error --- Engine/gfx/ali3dogl.cpp | 11 +++-- Engine/gfx/ali3dsw.cpp | 5 +-- Engine/gfx/gfxdriverfactory.cpp | 4 +- Engine/main/engine.cpp | 3 +- Engine/main/graphics_mode.cpp | 12 +++--- Engine/main/main.cpp | 14 ------- Engine/main/main_allegro.h | 31 -------------- Engine/platform/windows/gfx/ali3dd3d.cpp | 40 ++++++++++--------- Solutions/Engine.App/Engine.App.vcxproj | 1 - .../Engine.App/Engine.App.vcxproj.filters | 3 -- 10 files changed, 36 insertions(+), 88 deletions(-) delete mode 100644 Engine/main/main_allegro.h diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index dc4b338646b..aa1961f3531 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -23,7 +23,6 @@ #include "gfx/ali3dexception.h" #include "gfx/gfxfilter_ogl.h" #include "gfx/gfxfilter_aaogl.h" -#include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" @@ -251,11 +250,11 @@ bool OGLGraphicsDriver::IsModeSupported(const DisplayMode &mode) { if (mode.Width <= 0 || mode.Height <= 0) { - set_allegro_error("Invalid resolution parameters: %d x %d", mode.Width, mode.Height); + SDL_SetError("Invalid resolution parameters: %d x %d", mode.Width, mode.Height); return false; } if (mode.ColorDepth != 32) { - set_allegro_error("Display colour depth not supported: %d", mode.ColorDepth); + SDL_SetError("Display colour depth not supported: %d", mode.ColorDepth); return false; } return true; @@ -707,7 +706,7 @@ bool OGLGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *lo if (mode.ColorDepth < 15) { - set_allegro_error("OpenGL driver does not support 256-color display mode"); + SDL_SetError("OpenGL driver does not support 256-color display mode"); return false; } @@ -721,8 +720,8 @@ bool OGLGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *lo } catch (Ali3DException exception) { - if (exception._message != get_allegro_error()) - set_allegro_error(exception._message); + if (exception._message != SDL_GetError()) + SDL_SetError(exception._message); return false; } diff --git a/Engine/gfx/ali3dsw.cpp b/Engine/gfx/ali3dsw.cpp index 49ee51aa8b7..0749cd1e786 100644 --- a/Engine/gfx/ali3dsw.cpp +++ b/Engine/gfx/ali3dsw.cpp @@ -17,7 +17,6 @@ #include "gfx/ali3dexception.h" #include "gfx/gfxfilter_sdl_renderer.h" #include "gfx/gfx_util.h" -#include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" #include "ac/timer.h" @@ -72,11 +71,11 @@ bool SDLRendererGraphicsDriver::IsModeSupported(const DisplayMode &mode) { if (mode.Width <= 0 || mode.Height <= 0) { - set_allegro_error("Invalid resolution parameters: %d x %d", mode.Width, mode.Height); + SDL_SetError("Invalid resolution parameters: %d x %d", mode.Width, mode.Height); return false; } if (mode.ColorDepth != 32) { - set_allegro_error("Display colour depth not supported: %d", mode.ColorDepth); + SDL_SetError("Display colour depth not supported: %d", mode.ColorDepth); return false; } return true; diff --git a/Engine/gfx/gfxdriverfactory.cpp b/Engine/gfx/gfxdriverfactory.cpp index b8e886544ed..e7522589604 100644 --- a/Engine/gfx/gfxdriverfactory.cpp +++ b/Engine/gfx/gfxdriverfactory.cpp @@ -32,8 +32,6 @@ #include "gfx/gfxfilter_d3d.h" #endif -#include "main/main_allegro.h" - namespace AGS { namespace Engine @@ -62,7 +60,7 @@ IGfxDriverFactory *GetGfxDriverFactory(const String id) #endif if (id.CompareNoCase("Software") == 0) return ALSW::SDLRendererGraphicsFactory::GetFactory(); - set_allegro_error("No graphics factory with such id: %s", id.GetCStr()); + SDL_SetError("No graphics factory with such id: %s", id.GetCStr()); return nullptr; } diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index e74d8db2e05..704e1d7b5ec 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -63,7 +63,6 @@ #include "main/engine_setup.h" #include "main/graphics_mode.h" #include "main/main.h" -#include "main/main_allegro.h" #include "media/audio/audio_core.h" #include "platform/base/sys_main.h" #include "platform/util/pe.h" @@ -114,7 +113,7 @@ bool engine_init_allegro() set_uformat(U_ASCII); if (install_allegro(SYSTEM_NONE, &errno, atexit)) { - const char *al_err = get_allegro_error(); + const char *al_err = SDL_GetError(); const char *user_hint = platform->GetAllegroFailUserHint(); platform->DisplayAlert("Unable to initialize Allegro system driver.\n%s\n\n%s", al_err[0] ? al_err : "Allegro library provided no further information on the problem.", diff --git a/Engine/main/graphics_mode.cpp b/Engine/main/graphics_mode.cpp index 4b311844b56..68a37835018 100644 --- a/Engine/main/graphics_mode.cpp +++ b/Engine/main/graphics_mode.cpp @@ -17,6 +17,7 @@ // #include +#include #include "core/platform.h" #include "ac/draw.h" #include "debug/debugger.h" @@ -29,7 +30,6 @@ #include "main/config.h" #include "main/engine_setup.h" #include "main/graphics_mode.h" -#include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" @@ -110,14 +110,14 @@ bool create_gfx_driver(const String &gfx_driver_id) GfxFactory = GetGfxDriverFactory(gfx_driver_id); if (!GfxFactory) { - Debug::Printf(kDbgMsg_Error, "Failed to initialize %s graphics factory. Error: %s", gfx_driver_id.GetCStr(), get_allegro_error()); + Debug::Printf(kDbgMsg_Error, "Failed to initialize %s graphics factory. Error: %s", gfx_driver_id.GetCStr(), SDL_GetError()); return false; } Debug::Printf("Using graphics factory: %s", gfx_driver_id.GetCStr()); gfxDriver = GfxFactory->GetDriver(); if (!gfxDriver) { - Debug::Printf(kDbgMsg_Error, "Failed to create graphics driver. Error: %s", get_allegro_error()); + Debug::Printf(kDbgMsg_Error, "Failed to create graphics driver. Error: %s", SDL_GetError()); return false; } Debug::Printf("Created graphics driver: %s", gfxDriver->GetDriverName()); @@ -465,7 +465,7 @@ void display_gfx_mode_error(const Size &game_size, const ScreenSetup &setup, con "(Problem: '%s')\n" "Try to correct the problem, or seek help from the AGS homepage." "%s", - main_error.GetCStr(), get_allegro_error(), platform->GetGraphicsTroubleshootingText()); + main_error.GetCStr(), SDL_GetError(), platform->GetGraphicsTroubleshootingText()); } bool graphics_mode_init_any(const Size game_size, const ScreenSetup &setup, const ColorDepthOption &color_depth) @@ -574,7 +574,7 @@ bool graphics_mode_set_dm(const DisplayMode &dm) if (!gfxDriver->SetDisplayMode(dm, nullptr)) { - Debug::Printf(kDbgMsg_Error, "Failed to init gfx mode. Error: %s", get_allegro_error()); + Debug::Printf(kDbgMsg_Error, "Failed to init gfx mode. Error: %s", SDL_GetError()); return false; } @@ -603,7 +603,7 @@ bool graphics_mode_update_render_frame() { Debug::Printf(kDbgMsg_Error, "Failed to set render frame (%d, %d, %d, %d : %d x %d). Error: %s", render_frame.Left, render_frame.Top, render_frame.Right, render_frame.Bottom, - render_frame.GetWidth(), render_frame.GetHeight(), get_allegro_error()); + render_frame.GetWidth(), render_frame.GetHeight(), SDL_GetError()); return false; } diff --git a/Engine/main/main.cpp b/Engine/main/main.cpp index 0357574e465..ee0a47fad45 100644 --- a/Engine/main/main.cpp +++ b/Engine/main/main.cpp @@ -414,20 +414,6 @@ String GetPathFromCmdArg(int arg_index) return global_argv[arg_index]; } -const char *get_allegro_error() -{ - return allegro_error; -} - -const char *set_allegro_error(const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - uvszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(format), argptr); - va_end(argptr); - return allegro_error; -} - int ags_entry_point(int argc, char *argv[]) { #ifdef AGS_RUN_TESTS diff --git a/Engine/main/main_allegro.h b/Engine/main/main_allegro.h deleted file mode 100644 index bbf7bcf6e8a..00000000000 --- a/Engine/main/main_allegro.h +++ /dev/null @@ -1,31 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= -// -// -// -//============================================================================= -#ifndef __AGS_EE_MAIN__MAINALLEGRO_H -#define __AGS_EE_MAIN__MAINALLEGRO_H - -// Gets allegro_error as a const string. -// Please, use this getter to acquire error text, do not use allegro_error -// global variable directly. -const char *get_allegro_error(); -// Sets allegro_error global variable and returns a resulting string. -// The maximal allowed text length is defined by ALLEGRO_ERROR_SIZE macro -// (usually 256). If the formatted message is larger than that it will be -// truncated. Null terminator is always guaranteed. -const char *set_allegro_error(const char *format, ...); - -#endif // __AGS_EE_MAIN__MAINALLEGRO_H diff --git a/Engine/platform/windows/gfx/ali3dd3d.cpp b/Engine/platform/windows/gfx/ali3dd3d.cpp index 2c97fd74d6c..fa57218ea02 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.cpp +++ b/Engine/platform/windows/gfx/ali3dd3d.cpp @@ -28,7 +28,6 @@ #include "gfx/ali3dexception.h" #include "gfx/gfxfilter_d3d.h" #include "gfx/gfxfilter_aad3d.h" -#include "main/main_allegro.h" #include "platform/base/agsplatformdriver.h" #include "platform/base/sys_main.h" #include "util/library.h" @@ -294,8 +293,8 @@ int D3DGraphicsDriver::FirstTimeInit() { direct3ddevice->Release(); direct3ddevice = NULL; - previousError = - set_allegro_error("Graphics card does not support Pixel Shader %d.%d", requiredPSMajorVersion, requiredPSMinorVersion); + SDL_SetError("Graphics card does not support Pixel Shader %d.%d", requiredPSMajorVersion, requiredPSMinorVersion); + previousError = SDL_GetError(); return -1; } @@ -314,7 +313,8 @@ int D3DGraphicsDriver::FirstTimeInit() { direct3ddevice->Release(); direct3ddevice = NULL; - previousError = set_allegro_error("Failed to create pixel shader: 0x%08X", hr); + SDL_SetError("Failed to create pixel shader: 0x%08X", hr); + previousError = SDL_GetError(); return -1; } UnlockResource(hGlobal); @@ -325,7 +325,8 @@ int D3DGraphicsDriver::FirstTimeInit() { direct3ddevice->Release(); direct3ddevice = NULL; - previousError = set_allegro_error("Failed to load pixel shader resource"); + SDL_SetError("Failed to load pixel shader resource"); + previousError = SDL_GetError(); return -1; } @@ -334,7 +335,8 @@ int D3DGraphicsDriver::FirstTimeInit() { direct3ddevice->Release(); direct3ddevice = NULL; - previousError = set_allegro_error("Failed to create vertex buffer"); + SDL_SetError("Failed to create vertex buffer"); + previousError = SDL_GetError(); return -1; } @@ -373,12 +375,12 @@ void D3DGraphicsDriver::initD3DDLL(const DisplayMode &mode) { if (!IsModeSupported(mode)) { - throw Ali3DException(get_allegro_error()); + throw Ali3DException(SDL_GetError()); } d3d_mode_to_init = mode; if (wnd_create_device()) { - throw Ali3DException(get_allegro_error()); + throw Ali3DException(SDL_GetError()); } availableVideoMemory = direct3ddevice->GetAvailableTextureMem(); @@ -455,7 +457,7 @@ bool D3DGraphicsDriver::IsModeSupported(const DisplayMode &mode) { if (mode.Width <= 0 || mode.Height <= 0 || mode.ColorDepth <= 0) { - set_allegro_error("Invalid resolution parameters: %d x %d x %d", mode.Width, mode.Height, mode.ColorDepth); + SDL_SetError("Invalid resolution parameters: %d x %d x %d", mode.Width, mode.Height, mode.ColorDepth); return false; } @@ -472,7 +474,7 @@ bool D3DGraphicsDriver::IsModeSupported(const DisplayMode &mode) { if (FAILED(direct3d->EnumAdapterModes(D3DADAPTER_DEFAULT, pixelFormat, i, &d3d_mode))) { - set_allegro_error("IDirect3D9::EnumAdapterModes failed"); + SDL_SetError("IDirect3D9::EnumAdapterModes failed"); return false; } @@ -482,7 +484,7 @@ bool D3DGraphicsDriver::IsModeSupported(const DisplayMode &mode) } } - set_allegro_error("The requested adapter mode is not supported"); + SDL_SetError("The requested adapter mode is not supported"); return false; } @@ -611,9 +613,9 @@ int D3DGraphicsDriver::_initDLLCallback(const DisplayMode &mode) if (hr != D3D_OK) { if (!previousError.IsEmpty()) - set_allegro_error(previousError); + SDL_SetError(previousError); else - set_allegro_error("Failed to create Direct3D Device: 0x%08X", hr); + SDL_SetError("Failed to create Direct3D Device: 0x%08X", hr); return -1; } @@ -760,7 +762,7 @@ bool D3DGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *lo if (mode.ColorDepth < 15) { - set_allegro_error("Direct3D driver does not support 256-color display mode"); + SDL_SetError("Direct3D driver does not support 256-color display mode"); return false; } @@ -770,8 +772,8 @@ bool D3DGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *lo } catch (Ali3DException exception) { - if (exception._message != get_allegro_error()) - set_allegro_error(exception._message); + if (exception._message != SDL_GetError()) + SDL_SetError(exception._message); return false; } OnInit(loopTimer); @@ -1958,7 +1960,7 @@ bool D3DGraphicsFactory::Init() if (!_library.Load("d3d9")) { - set_allegro_error("Direct3D 9 is not installed"); + SDL_SetError("Direct3D 9 is not installed"); return false; } @@ -1967,14 +1969,14 @@ bool D3DGraphicsFactory::Init() if (!lpDirect3DCreate9) { _library.Unload(); - set_allegro_error("Entry point not found in d3d9.dll"); + SDL_SetError("Entry point not found in d3d9.dll"); return false; } _direct3d = lpDirect3DCreate9(D3D_SDK_VERSION); if (!_direct3d) { _library.Unload(); - set_allegro_error("Direct3DCreate failed!"); + SDL_SetError("Direct3DCreate failed!"); return false; } return true; diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 14f58145a7a..edf20b4c609 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -708,7 +708,6 @@ - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index 47a9a44f638..001b9dc4bec 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -1445,9 +1445,6 @@ Header Files\main - - Header Files\main - Header Files\main From 82c27220659ba0181d019db459fbf5f863d7026e Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Sun, 1 Nov 2020 00:39:07 +0300 Subject: [PATCH 24/41] Common: removed few unnecessary bitmap functions --- Common/gfx/allegrobitmap.cpp | 10 ------ Common/gfx/allegrobitmap.h | 21 ------------ Common/libsrc/aastr-0.1.1/aarot.c | 14 ++------ Common/libsrc/aastr-0.1.1/aastr.c | 15 ++------- Common/util/compress.cpp | 4 --- Editor/AGS.Native/agsnative.cpp | 5 +-- Engine/ac/draw.cpp | 4 --- Engine/ac/draw_software.cpp | 2 +- Engine/ac/event.cpp | 1 - Engine/ac/route_finder_impl_legacy.cpp | 5 +-- Engine/ac/sprite.cpp | 4 --- Engine/ac/walkablearea.cpp | 6 ---- Engine/ac/walkbehind.cpp | 5 --- .../platform/windows/media/video/acwavi.cpp | 32 ++++++------------- Engine/plugin/agsplugin.cpp | 6 ---- 15 files changed, 17 insertions(+), 117 deletions(-) diff --git a/Common/gfx/allegrobitmap.cpp b/Common/gfx/allegrobitmap.cpp index 47cbf481411..8e6b5e5a320 100644 --- a/Common/gfx/allegrobitmap.cpp +++ b/Common/gfx/allegrobitmap.cpp @@ -143,16 +143,6 @@ void Bitmap::SetMaskColor(color_t color) // not supported? CHECKME } -void Bitmap::Acquire() -{ - acquire_bitmap(_alBitmap); -} - -void Bitmap::Release() -{ - release_bitmap(_alBitmap); -} - color_t Bitmap::GetCompatibleColor(color_t color) { color_t compat_color = 0; diff --git a/Common/gfx/allegrobitmap.h b/Common/gfx/allegrobitmap.h index fc73dcc0a42..a6a106f2f2a 100644 --- a/Common/gfx/allegrobitmap.h +++ b/Common/gfx/allegrobitmap.h @@ -64,22 +64,6 @@ class Bitmap return _alBitmap; } - // Is this a "normal" bitmap created by application which data can be directly accessed for reading and writing - inline bool IsMemoryBitmap() const - { - return is_memory_bitmap(_alBitmap) != 0; - } - // Is this a video bitmap - inline bool IsVideoBitmap() const - { - return is_video_bitmap(_alBitmap) != 0; - } - // Is this a linear bitmap, the one that can be accessed linearly within each scanline - inline bool IsLinearBitmap() const - { - return is_linear_bitmap(_alBitmap) != 0; - } - // Checks if bitmap cannot be used inline bool IsNull() const { @@ -143,11 +127,6 @@ class Bitmap return bitmap_mask_color(_alBitmap); } - // FIXME: allegro manual states these should not be used externally; - // should hide or totally remove those later - void Acquire(); - void Release(); - // Converts AGS color-index into RGB color according to the bitmap format. // TODO: this method was added to the Bitmap class during large refactoring, // but that's a mistake, because in retrospect is has nothing to do with diff --git a/Common/libsrc/aastr-0.1.1/aarot.c b/Common/libsrc/aastr-0.1.1/aarot.c index 1bb6fe344b9..0530bfe7939 100644 --- a/Common/libsrc/aastr-0.1.1/aarot.c +++ b/Common/libsrc/aastr-0.1.1/aarot.c @@ -306,11 +306,7 @@ _aa_rotate_bitmap (BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed _angle, return; /* Color manipulation routines. */ - if (is_screen_bitmap (_src)) - return; - else - { - switch (bitmap_color_depth (_src)) + switch (bitmap_color_depth (_src)) { case 8: add = ((_masked != 0) ? _aa_masked_add_rgb8 : _aa_add_rgb8); @@ -337,13 +333,8 @@ _aa_rotate_bitmap (BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed _angle, default: return; } - } - if (is_planar_bitmap (_dst)) - return; - else - { - switch (bitmap_color_depth (_dst)) + switch (bitmap_color_depth (_dst)) { case 8: put = ((_masked != 0) ? _aa_masked_put_rgb8 : _aa_put_rgb8); @@ -370,7 +361,6 @@ _aa_rotate_bitmap (BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed _angle, default: return; } - } lindex = 1; rindex = 1; diff --git a/Common/libsrc/aastr-0.1.1/aastr.c b/Common/libsrc/aastr-0.1.1/aastr.c index 7f33fc87e37..314f7e1a0e3 100644 --- a/Common/libsrc/aastr-0.1.1/aastr.c +++ b/Common/libsrc/aastr-0.1.1/aastr.c @@ -100,11 +100,8 @@ _aa_stretch_blit (BITMAP *_src, BITMAP *_dst, } /* Color manipulation routines. */ - if (is_screen_bitmap (_src)) - return; - else - { - switch (bitmap_color_depth (_src)) + + switch (bitmap_color_depth (_src)) { case 8: add = ((_masked != 0) ? _aa_masked_add_rgb8 : _aa_add_rgb8); @@ -131,13 +128,8 @@ _aa_stretch_blit (BITMAP *_src, BITMAP *_dst, default: return; } - } - if (is_planar_bitmap (_dst)) - return; - else - { - switch (bitmap_color_depth (_dst)) + switch (bitmap_color_depth (_dst)) { case 8: put = ((_masked != 0) ? _aa_masked_put_rgb8 : _aa_put_rgb8); @@ -164,7 +156,6 @@ _aa_stretch_blit (BITMAP *_src, BITMAP *_dst, default: return; } - } /* Walk in y until we reach first non-clipped line. */ aa_PREPARE (yinc, ydd, yi1, yi2, _sh, _dh); diff --git a/Common/util/compress.cpp b/Common/util/compress.cpp index 8561fb68759..ff4ebe9f6f8 100644 --- a/Common/util/compress.cpp +++ b/Common/util/compress.cpp @@ -381,13 +381,9 @@ void load_lzw(Stream *in, Bitmap **dst_bmp, int dst_bpp, color *pall) { update_polled_stuff_if_runtime(); - bmm->Acquire (); - for (arin = 0; arin < loptr[1]; arin++) memcpy(&bmm->GetScanLineForWriting(arin)[0], &membuffer[arin * loptr[0]], loptr[0]); - bmm->Release (); - update_polled_stuff_if_runtime(); free(membuffer-8); diff --git a/Editor/AGS.Native/agsnative.cpp b/Editor/AGS.Native/agsnative.cpp index 09da04e2e68..47fb4b6cfe2 100644 --- a/Editor/AGS.Native/agsnative.cpp +++ b/Editor/AGS.Native/agsnative.cpp @@ -1540,8 +1540,6 @@ void remap_background (Common::Bitmap *scene, color *oldpale, color*palette, int // find which colours from the image palette are actually used int imgpalcnt[256],numimgclr=0; memset(&imgpalcnt[0],0,sizeof(int)*256); - if (scene->IsLinearBitmap()==0) - quit("mem bitmap non-linear?"); for (a=0;a<(scene->GetWidth()) * (scene->GetHeight());a++) { imgpalcnt[scene->GetScanLine(0)[a]]++; @@ -1601,8 +1599,7 @@ void remap_background (Common::Bitmap *scene, color *oldpale, color*palette, int } void validate_mask(Common::Bitmap *toValidate, const char *name, int maxColour) { - if ((toValidate == NULL) || (toValidate->GetColorDepth() != 8) || - (!toValidate->IsMemoryBitmap())) { + if ((toValidate == NULL) || (toValidate->GetColorDepth() != 8)) { quit("Invalid mask passed to validate_mask"); return; } diff --git a/Engine/ac/draw.cpp b/Engine/ac/draw.cpp index 14374d16973..bf786f6ab55 100644 --- a/Engine/ac/draw.cpp +++ b/Engine/ac/draw.cpp @@ -883,10 +883,6 @@ int sort_out_walk_behinds(Bitmap *sprit,int xx,int yy,int basel, Bitmap *copyPix if (noWalkBehindsAtAll) return 0; - if ((!thisroom.WalkBehindMask->IsMemoryBitmap()) || - (!sprit->IsMemoryBitmap())) - quit("!sort_out_walk_behinds: wb bitmap not linear"); - int rr,tmm, toheight;//,tcol; // precalculate this to try and shave some time off int maskcol = sprit->GetMaskColor(); diff --git a/Engine/ac/draw_software.cpp b/Engine/ac/draw_software.cpp index 721b676924f..a1ae4238354 100644 --- a/Engine/ac/draw_software.cpp +++ b/Engine/ac/draw_software.cpp @@ -400,7 +400,7 @@ void update_invalid_region(Bitmap *ds, Bitmap *src, const DirtyRects &rects, boo const int surf_height = rects.SurfaceSize.Height; // TODO: is this IsMemoryBitmap check is still relevant? // If bitmaps properties match and no transform required other than linear offset - if ((src->GetColorDepth() == ds->GetColorDepth()) && (ds->IsMemoryBitmap())) + if (src->GetColorDepth() == ds->GetColorDepth()) { const int bypp = src->GetBPP(); // do the fast memory copy diff --git a/Engine/ac/event.cpp b/Engine/ac/event.cpp index 17c57d9e6b3..3c986a9fabc 100644 --- a/Engine/ac/event.cpp +++ b/Engine/ac/event.cpp @@ -324,7 +324,6 @@ void process_event(EventHappened*evp) { WaitForNextFrame(); transparency -= 16; } - saved_viewport_bitmap->Release(); delete saved_viewport_bitmap; saved_viewport_bitmap = nullptr; diff --git a/Engine/ac/route_finder_impl_legacy.cpp b/Engine/ac/route_finder_impl_legacy.cpp index 085a75b28a1..02c3224bfe2 100644 --- a/Engine/ac/route_finder_impl_legacy.cpp +++ b/Engine/ac/route_finder_impl_legacy.cpp @@ -156,18 +156,15 @@ static int is_route_possible(int fromx, int fromy, int tox, int toy, Bitmap *wss suggestx = -1; // ensure it's a memory bitmap, so we can use direct access to line[] array - if ((wss == nullptr) || (!wss->IsMemoryBitmap()) || (wss->GetColorDepth() != 8)) + if ((wss == nullptr) || (wss->GetColorDepth() != 8)) quit("is_route_possible: invalid walkable areas bitmap supplied"); if (wallscreen->GetPixel(fromx, fromy) < 1) return 0; Bitmap *tempw = BitmapHelper::CreateBitmapCopy(wallscreen, 8); - if (tempw == nullptr) quit("no memory for route calculation"); - if (!tempw->IsMemoryBitmap()) - quit("tempw is not memory bitmap"); int dd, ff; // initialize array for finding widths of walkable areas diff --git a/Engine/ac/sprite.cpp b/Engine/ac/sprite.cpp index a14bfc577be..0ae47147a4a 100644 --- a/Engine/ac/sprite.cpp +++ b/Engine/ac/sprite.cpp @@ -157,11 +157,7 @@ void initialize_sprite (int ee) { tmpdbl = BitmapHelper::CreateTransparentBitmap(newwid,newhit,curspr->GetColorDepth()); if (tmpdbl == nullptr) quit("Not enough memory to load sprite graphics"); - tmpdbl->Acquire (); - curspr->Acquire (); tmpdbl->StretchBlt(curspr,RectWH(0,0,tmpdbl->GetWidth(),tmpdbl->GetHeight()), Common::kBitmap_Transparency); - curspr->Release (); - tmpdbl->Release (); delete curspr; spriteset.SubstituteBitmap(ee, tmpdbl); } diff --git a/Engine/ac/walkablearea.cpp b/Engine/ac/walkablearea.cpp index c6631789920..ff319f414a7 100644 --- a/Engine/ac/walkablearea.cpp +++ b/Engine/ac/walkablearea.cpp @@ -37,12 +37,6 @@ extern RoomObject*objs; Bitmap *walkareabackup=nullptr, *walkable_areas_temp = nullptr; void redo_walkable_areas() { - - // since this is an 8-bit memory bitmap, we can just use direct - // memory access - if ((!thisroom.WalkAreaMask->IsLinearBitmap()) || (thisroom.WalkAreaMask->GetColorDepth() != 8)) - quit("Walkable areas bitmap not linear"); - thisroom.WalkAreaMask->Blit(walkareabackup, 0, 0, 0, 0, thisroom.WalkAreaMask->GetWidth(), thisroom.WalkAreaMask->GetHeight()); int hh,ww; diff --git a/Engine/ac/walkbehind.cpp b/Engine/ac/walkbehind.cpp index f254800f4be..ce344d3f15c 100644 --- a/Engine/ac/walkbehind.cpp +++ b/Engine/ac/walkbehind.cpp @@ -110,11 +110,6 @@ void recache_walk_behinds () { update_polled_stuff_if_runtime(); - // since this is an 8-bit memory bitmap, we can just use direct - // memory access - if ((!thisroom.WalkBehindMask->IsLinearBitmap()) || (thisroom.WalkBehindMask->GetColorDepth() != 8)) - quit("Walk behinds bitmap not linear"); - for (ee=0;eeGetWidth();ee++) { walkBehindExists[ee] = 0; for (rr=0;rrGetHeight();rr++) { diff --git a/Engine/platform/windows/media/video/acwavi.cpp b/Engine/platform/windows/media/video/acwavi.cpp index 8e8dc3240ad..7031dc2ff47 100644 --- a/Engine/platform/windows/media/video/acwavi.cpp +++ b/Engine/platform/windows/media/video/acwavi.cpp @@ -245,31 +245,17 @@ void RenderToSurface(Bitmap *vscreen) { } else { g_bAppactive = TRUE; + // TODO: don't render on virtual screen, use gfxDriver->DrawSprite instead! Bitmap *screen_bmp = gfxDriver->GetMemoryBackBuffer(); - // TODO: don't render on screen bitmap, use gfxDriver->DrawSprite instead! - screen_bmp->Acquire(); // Because vscreen is a DX Video Bitmap, it can be stretched - // onto the screen (also a Video Bmp) but not onto a memory - // bitmap (which is what "screen" is when using gfx filters) - if (screen_bmp->IsVideoBitmap()) - { - screen_bmp->StretchBlt(vscreen, - RectWH(0, 0, vscreen->GetWidth(), vscreen->GetHeight()), - RectWH(screen_bmp->GetWidth() / 2 - newWidth / 2, - screen_bmp->GetHeight() / 2 - newHeight / 2, - newWidth, newHeight)); - } - else - { - vsMemory->Blit(vscreen, 0, 0, 0, 0, vscreen->GetWidth(), vscreen->GetHeight()); - screen_bmp->StretchBlt(vsMemory, - RectWH(0, 0, vscreen->GetWidth(), vscreen->GetHeight()), - RectWH(screen_bmp->GetWidth() / 2 - newWidth / 2, - screen_bmp->GetHeight() / 2 - newHeight / 2, - newWidth, newHeight)); - } - screen_bmp->Release(); - + // onto the video bitmap but not onto a memory + // bitmap (which is what "screen" is when using backbuffer) + vsMemory->Blit(vscreen, 0, 0, 0, 0, vscreen->GetWidth(), vscreen->GetHeight()); + screen_bmp->StretchBlt(vsMemory, + RectWH(0, 0, vscreen->GetWidth(), vscreen->GetHeight()), + RectWH(screen_bmp->GetWidth() / 2 - newWidth / 2, + screen_bmp->GetHeight() / 2 - newHeight / 2, + newWidth, newHeight)); // if we're not playing AVI sound, poll the audio system if (!useSound) update_audio_system_on_game_loop(); diff --git a/Engine/plugin/agsplugin.cpp b/Engine/plugin/agsplugin.cpp index a266bcd3da5..2fb2e3bbaff 100644 --- a/Engine/plugin/agsplugin.cpp +++ b/Engine/plugin/agsplugin.cpp @@ -247,10 +247,6 @@ void IAGSEngine::GetScreenDimensions (int32 *width, int32 *height, int32 *coldep unsigned char ** IAGSEngine::GetRawBitmapSurface (BITMAP *bmp) { - if (!is_linear_bitmap(bmp)) - quit("!IAGSEngine::GetRawBitmapSurface: invalid bitmap for access to surface"); - acquire_bitmap(bmp); - Bitmap *stage = gfxDriver->GetStageBackBuffer(); if (stage && bmp == stage->GetAllegroBitmap()) plugins[this->pluginId].invalidatedRegion = 0; @@ -260,8 +256,6 @@ unsigned char ** IAGSEngine::GetRawBitmapSurface (BITMAP *bmp) void IAGSEngine::ReleaseBitmapSurface (BITMAP *bmp) { - release_bitmap (bmp); - Bitmap *stage = gfxDriver->GetStageBackBuffer(); if (stage && bmp == stage->GetAllegroBitmap()) { From d86c185ca7b5beec22ea07a817ba9cc822f493b4 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Tue, 10 Nov 2020 05:38:06 +0300 Subject: [PATCH 25/41] Cleanup wgt2allg.h and include allegro.h more explicitly --- Common/ac/common.h | 3 + Common/ac/gamesetupstruct.cpp | 2 +- Common/ac/gamesetupstructbase.cpp | 4 +- Common/ac/gamesetupstructbase.h | 5 +- Common/ac/oldgamesetupstruct.h | 2 +- Common/ac/spritecache.cpp | 2 +- Common/game/room_file.cpp | 2 +- Common/game/roomstruct.h | 7 +- Common/gfx/allegrobitmap.cpp | 1 + Common/gfx/allegrobitmap.h | 2 +- Common/libsrc/alfont-2.0.9/alfont.h | 3 - Common/util/compress.cpp | 14 +-- Common/util/compress.h | 13 +-- Common/util/misc.cpp | 2 +- Common/util/wgt2allg.cpp | 103 ++---------------- Common/util/wgt2allg.h | 46 ++------ Engine/ac/draw.cpp | 3 +- Engine/ac/draw.h | 12 -- Engine/ac/dynamicsprite.cpp | 2 +- Engine/ac/event.cpp | 6 +- Engine/ac/file.cpp | 2 +- Engine/ac/game.cpp | 7 +- Engine/ac/gamesetup.cpp | 2 - Engine/ac/global_dynamicsprite.cpp | 2 - Engine/ac/global_game.cpp | 4 +- Engine/ac/global_overlay.cpp | 1 + Engine/ac/global_palette.cpp | 3 +- Engine/ac/global_screen.cpp | 3 +- Engine/ac/global_video.cpp | 2 - Engine/ac/invwindow.cpp | 1 + Engine/ac/listbox.cpp | 2 +- Engine/ac/movelist.h | 4 +- Engine/ac/region.cpp | 2 +- Engine/ac/room.cpp | 4 +- Engine/ac/screen.cpp | 2 +- Engine/ac/sprite.cpp | 2 +- Engine/debug/debug.cpp | 11 +- Engine/debug/filebasedagsdebugger.cpp | 2 +- Engine/device/mousew32.cpp | 2 +- Engine/game/savegame_components.cpp | 6 +- Engine/gfx/blender.cpp | 13 +-- Engine/gfx/color_engine.cpp | 5 +- Engine/gfx/gfxdriverbase.cpp | 2 - Engine/gfx/graphicsdriver.h | 3 +- Engine/gfx/ogl_headers.h | 6 +- Engine/gui/cscidialog.cpp | 2 - Engine/gui/guidialog.cpp | 3 +- Engine/gui/mylistbox.cpp | 2 - Engine/gui/mypushbutton.cpp | 2 - Engine/gui/mytextbox.cpp | 1 - Engine/main/config.cpp | 2 +- Engine/main/engine.cpp | 5 +- Engine/main/game_file.cpp | 1 - Engine/main/main.cpp | 2 +- Engine/main/quit.cpp | 7 +- Engine/media/audio/audio.cpp | 3 - Engine/media/audio/soundclip.cpp | 2 - Engine/media/video/video.cpp | 2 +- Engine/platform/base/agsplatformdriver.cpp | 3 - Engine/platform/windows/acplwin.cpp | 10 +- .../windows/debug/namedpipesagsdebugger.h | 1 - Engine/platform/windows/gfx/ali3dd3d.h | 4 +- .../platform/windows/media/video/acwavi.cpp | 6 +- .../platform/windows/media/video/acwavi3d.cpp | 4 - Engine/platform/windows/setup/winsetup.cpp | 6 +- Engine/plugin/agsplugin.cpp | 46 ++++---- Engine/util/library_windows.h | 2 +- Solutions/Common.Lib/Common.Lib.vcxproj | 12 +- Solutions/Engine.App/Engine.App.vcxproj | 8 +- 69 files changed, 146 insertions(+), 317 deletions(-) diff --git a/Common/ac/common.h b/Common/ac/common.h index 469605c3205..8b4859542b2 100644 --- a/Common/ac/common.h +++ b/Common/ac/common.h @@ -24,4 +24,7 @@ int get_our_eip(); extern const char *game_file_sig; +// archive attributes to search for - al_findfirst breaks with 0 +#define FA_SEARCH -1 + #endif // __AC_COMMON_H diff --git a/Common/ac/gamesetupstruct.cpp b/Common/ac/gamesetupstruct.cpp index 3be59c397fe..22eb9d51b1d 100644 --- a/Common/ac/gamesetupstruct.cpp +++ b/Common/ac/gamesetupstruct.cpp @@ -425,7 +425,7 @@ void ConvertOldGameStruct (OldGameSetupStruct *ogss, GameSetupStruct *gss) { for (int i = 0; i < 20; i++) gss->options[i] = ogss->options[i]; memcpy (&gss->paluses[0], &ogss->paluses[0], 256); - memcpy (&gss->defpal[0], &ogss->defpal[0], 256 * sizeof(color)); + memcpy (&gss->defpal[0], &ogss->defpal[0], 256 * sizeof(RGB)); gss->numviews = ogss->numviews; gss->numcharacters = ogss->numcharacters; gss->playercharacter = ogss->playercharacter; diff --git a/Common/ac/gamesetupstructbase.cpp b/Common/ac/gamesetupstructbase.cpp index f3cbe33b803..3dc674b1450 100644 --- a/Common/ac/gamesetupstructbase.cpp +++ b/Common/ac/gamesetupstructbase.cpp @@ -161,7 +161,7 @@ void GameSetupStructBase::ReadFromFile(Stream *in) } in->Read(&paluses[0], 256); // colors are an array of chars - in->Read(&defpal[0], sizeof(color)*256); + in->Read(&defpal[0], sizeof(RGB)*256); numviews = in->ReadInt32(); numcharacters = in->ReadInt32(); playercharacter = in->ReadInt32(); @@ -207,7 +207,7 @@ void GameSetupStructBase::WriteToFile(Stream *out) out->WriteArrayOfInt32(options, 100); out->Write(&paluses[0], 256); // colors are an array of chars - out->Write(&defpal[0], sizeof(color)*256); + out->Write(&defpal[0], sizeof(RGB)*256); out->WriteInt32(numviews); out->WriteInt32(numcharacters); out->WriteInt32(playercharacter); diff --git a/Common/ac/gamesetupstructbase.h b/Common/ac/gamesetupstructbase.h index 1b075834e7f..e633668f37d 100644 --- a/Common/ac/gamesetupstructbase.h +++ b/Common/ac/gamesetupstructbase.h @@ -17,11 +17,10 @@ //============================================================================= #ifndef __AGS_CN_AC__GAMESETUPSTRUCTBASE_H #define __AGS_CN_AC__GAMESETUPSTRUCTBASE_H - +#include // RGB #include "ac/game_version.h" #include "ac/gamestructdefines.h" #include "util/string.h" -#include "util/wgt2allg.h" // color (allegro RGB) // Forward declaration namespace AGS { namespace Common { class Stream; } } @@ -40,7 +39,7 @@ struct GameSetupStructBase { char gamename[GAME_NAME_LENGTH]; int options[MAX_OPTIONS]; unsigned char paluses[256]; - color defpal[256]; + RGB defpal[256]; int numviews; int numcharacters; int playercharacter; diff --git a/Common/ac/oldgamesetupstruct.h b/Common/ac/oldgamesetupstruct.h index 40dbfb7555f..57ea01ccc36 100644 --- a/Common/ac/oldgamesetupstruct.h +++ b/Common/ac/oldgamesetupstruct.h @@ -32,7 +32,7 @@ struct OriGameSetupStruct { char gamename[30]; char options[20]; unsigned char paluses[256]; - color defpal[256]; + RGB defpal[256]; InterfaceElement iface[10]; int numiface; int numviews; diff --git a/Common/ac/spritecache.cpp b/Common/ac/spritecache.cpp index eecf492e6d6..d657c53d0e6 100644 --- a/Common/ac/spritecache.cpp +++ b/Common/ac/spritecache.cpp @@ -21,7 +21,7 @@ #pragma unmanaged #pragma warning (disable: 4996 4312) // disable deprecation warnings #endif - +#include #include "ac/common.h" // quit #include "ac/gamestructdefines.h" #include "ac/spritecache.h" diff --git a/Common/game/room_file.cpp b/Common/game/room_file.cpp index 65a65e69c3e..21ac5e8e2bd 100644 --- a/Common/game/room_file.cpp +++ b/Common/game/room_file.cpp @@ -737,7 +737,7 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g } // sync bpalettes[0] with room.pal - memcpy(room->BgFrames[0].Palette, room->Palette, sizeof(color) * 256); + memcpy(room->BgFrames[0].Palette, room->Palette, sizeof(RGB) * 256); return HRoomFileError::None(); } diff --git a/Common/game/roomstruct.h b/Common/game/roomstruct.h index e9d1fd2ccaf..eb99bbca153 100644 --- a/Common/game/roomstruct.h +++ b/Common/game/roomstruct.h @@ -36,12 +36,11 @@ //============================================================================= #ifndef __AGS_CN_GAME__ROOMINFO_H #define __AGS_CN_GAME__ROOMINFO_H - #include +#include // RGB #include "ac/common_defines.h" #include "game/interactions.h" #include "util/geometry.h" -#include "util/wgt2allg.h" // color (allegro RGB) struct ccScript; struct SpriteInfo; @@ -120,7 +119,7 @@ struct RoomBgFrame { PBitmap Graphic; // Palette is only valid in 8-bit games - color Palette[256]; + RGB Palette[256]; // Tells if this frame should keep previous frame palette instead of using its own bool IsPaletteShared; @@ -303,7 +302,7 @@ class RoomStruct int32_t Width; int32_t Height; // Primary room palette (8-bit games) - color Palette[256]; + RGB Palette[256]; // Basic room options RoomOptions Options; diff --git a/Common/gfx/allegrobitmap.cpp b/Common/gfx/allegrobitmap.cpp index 8e6b5e5a320..d69c1898460 100644 --- a/Common/gfx/allegrobitmap.cpp +++ b/Common/gfx/allegrobitmap.cpp @@ -14,6 +14,7 @@ #include #include "gfx/allegrobitmap.h" +#include // memcpy #include "debug/assert.h" extern void __my_setcolor(int *ctset, int newcol, int wantColDep); diff --git a/Common/gfx/allegrobitmap.h b/Common/gfx/allegrobitmap.h index a6a106f2f2a..c8631a0818e 100644 --- a/Common/gfx/allegrobitmap.h +++ b/Common/gfx/allegrobitmap.h @@ -21,7 +21,7 @@ #ifndef __AGS_CN_GFX__ALLEGROBITMAP_H #define __AGS_CN_GFX__ALLEGROBITMAP_H -#include +#include // BITMAP #include "core/types.h" #include "gfx/bitmap.h" diff --git a/Common/libsrc/alfont-2.0.9/alfont.h b/Common/libsrc/alfont-2.0.9/alfont.h index f59fa9da1db..a7934100dae 100644 --- a/Common/libsrc/alfont-2.0.9/alfont.h +++ b/Common/libsrc/alfont-2.0.9/alfont.h @@ -40,13 +40,10 @@ extern "C" { /* includes */ -#include - /* structs */ typedef struct ALFONT_FONT ALFONT_FONT; - /* API */ ALFONT_DLL_DECLSPEC char* alfont_get_name(ALFONT_FONT *f); diff --git a/Common/util/compress.cpp b/Common/util/compress.cpp index ff4ebe9f6f8..88390c0a10f 100644 --- a/Common/util/compress.cpp +++ b/Common/util/compress.cpp @@ -140,7 +140,7 @@ void cpackbitl32(const uint32_t *line, int size, Stream *out) } -void csavecompressed(Stream *out, const unsigned char * tobesaved, const color pala[256]) +void csavecompressed(Stream *out, const unsigned char * tobesaved, const RGB pala[256]) { int widt, hit; widt = *tobesaved++; @@ -288,7 +288,7 @@ int cunpackbitl32(uint32_t *line, int size, Stream *in) const char *lztempfnm = "~aclzw.tmp"; -void save_lzw(Stream *out, const Bitmap *bmpp, const color *pall) +void save_lzw(Stream *out, const Bitmap *bmpp, const RGB *pall) { // First write original bitmap into temporary file Stream *lz_temp_s = ci_fopen(lztempfnm, kFile_CreateAlways, kFile_Write); @@ -300,7 +300,7 @@ void save_lzw(Stream *out, const Bitmap *bmpp, const color *pall) // Now open same file for reading, and begin writing compressed data into required output stream lz_temp_s = ci_fopen(lztempfnm); soff_t temp_sz = lz_temp_s->GetLength(); - out->WriteArray(&pall[0], sizeof(color), 256); + out->WriteArray(&pall[0], sizeof(RGB), 256); out->WriteInt32(temp_sz); soff_t gobacto = out->GetPosition(); @@ -320,13 +320,13 @@ void save_lzw(Stream *out, const Bitmap *bmpp, const color *pall) out->Seek(toret, kSeekBegin); } -void load_lzw(Stream *in, Bitmap **dst_bmp, int dst_bpp, color *pall) { +void load_lzw(Stream *in, Bitmap **dst_bmp, int dst_bpp, RGB *pall) { soff_t uncompsiz; int *loptr; unsigned char *membuffer; int arin; - in->Read(&pall[0], sizeof(color)*256); + in->Read(&pall[0], sizeof(RGB)*256); maxsize = in->ReadInt32(); uncompsiz = in->ReadInt32(); @@ -396,7 +396,7 @@ void load_lzw(Stream *in, Bitmap **dst_bmp, int dst_bpp, color *pall) { *dst_bmp = bmm; } -void savecompressed_allegro(Stream *out, const Bitmap *bmpp, const color *pall) { +void savecompressed_allegro(Stream *out, const Bitmap *bmpp, const RGB *pall) { unsigned char *wgtbl = (unsigned char *)malloc(bmpp->GetWidth() * bmpp->GetHeight() + 4); short *sss = (short *)wgtbl; @@ -409,7 +409,7 @@ void savecompressed_allegro(Stream *out, const Bitmap *bmpp, const color *pall) free(wgtbl); } -void loadcompressed_allegro(Stream *in, Bitmap **bimpp, color *pall) { +void loadcompressed_allegro(Stream *in, Bitmap **bimpp, RGB *pall) { short widd,hitt; int ii; diff --git a/Common/util/compress.h b/Common/util/compress.h index 356f8782e00..f3a1397769c 100644 --- a/Common/util/compress.h +++ b/Common/util/compress.h @@ -11,16 +11,15 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #ifndef __AC_COMPRESS_H #define __AC_COMPRESS_H -#include "util/wgt2allg.h" // color (allegro RGB) +struct RGB; namespace AGS { namespace Common { class Stream; class Bitmap; } } using namespace AGS; // FIXME later -void csavecompressed(Common::Stream *out, const unsigned char * tobesaved, const color pala[256]); +void csavecompressed(Common::Stream *out, const unsigned char * tobesaved, const RGB pala[256]); // RLE compression void cpackbitl(const uint8_t *line, int size, Common::Stream *out); void cpackbitl16(const uint16_t *line, int size, Common::Stream *out); @@ -32,9 +31,9 @@ int cunpackbitl32(uint32_t *line, int size, Common::Stream *in); //============================================================================= -void save_lzw(Common::Stream *out, const Common::Bitmap *bmpp, const color *pall); -void load_lzw(Common::Stream *in, Common::Bitmap **bmm, int dst_bpp, color *pall); -void savecompressed_allegro(Common::Stream *out, const Common::Bitmap *bmpp, const color *pall); -void loadcompressed_allegro(Common::Stream *in, Common::Bitmap **bimpp, color *pall); +void save_lzw(Common::Stream *out, const Common::Bitmap *bmpp, const RGB *pall); +void load_lzw(Common::Stream *in, Common::Bitmap **bmm, int dst_bpp, RGB *pall); +void savecompressed_allegro(Common::Stream *out, const Common::Bitmap *bmpp, const RGB *pall); +void loadcompressed_allegro(Common::Stream *in, Common::Bitmap **bimpp, RGB *pall); #endif // __AC_COMPRESS_H diff --git a/Common/util/misc.cpp b/Common/util/misc.cpp index 8848b7e0255..51b403376ab 100644 --- a/Common/util/misc.cpp +++ b/Common/util/misc.cpp @@ -50,7 +50,7 @@ #include #endif -#include "allegro.h" +#include // file path functions #include "util/file.h" #include "util/stream.h" diff --git a/Common/util/wgt2allg.cpp b/Common/util/wgt2allg.cpp index 31a81523d10..48a974d1cf8 100644 --- a/Common/util/wgt2allg.cpp +++ b/Common/util/wgt2allg.cpp @@ -11,32 +11,24 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include "core/assetmanager.h" -#include "gfx/bitmap.h" -#include "util/stream.h" #include "util/wgt2allg.h" +#include "gfx/bitmap.h" using namespace AGS::Common; -#ifdef __cplusplus -extern "C" -{ -#endif - - void wsetrgb(int coll, int r, int g, int b, color * pall) + void wsetrgb(int coll, int r, int g, int b, RGB * pall) { pall[coll].r = r; pall[coll].g = g; pall[coll].b = b; } - void wcolrotate(unsigned char start, unsigned char finish, int dir, color * pall) + void wcolrotate(unsigned char start, unsigned char finish, int dir, RGB * pall) { int jj; if (dir == 0) { // rotate left - color tempp = pall[start]; + RGB tempp = pall[start]; for (jj = start; jj < finish; jj++) pall[jj] = pall[jj + 1]; @@ -45,7 +37,7 @@ extern "C" } else { // rotate right - color tempp = pall[finish]; + RGB tempp = pall[finish]; for (jj = finish - 1; jj >= start; jj--) pall[jj + 1] = pall[jj]; @@ -54,7 +46,7 @@ extern "C" } } - Bitmap *wnewblock(Common::Bitmap *src, int x1, int y1, int x2, int y2) + Bitmap *wnewblock(Bitmap *src, int x1, int y1, int x2, int y2) { Bitmap *tempbitm; int twid = (x2 - x1) + 1, thit = (y2 - y1) + 1; @@ -74,86 +66,20 @@ extern "C" return tempbitm; } - int wloadsprites(color * pall, char *filnam, Bitmap ** sarray, int strt, int eend) - { - int vers; - char buff[20]; - int numspri = 0, vv, hh, wdd, htt; - - Stream *in = Common::AssetManager::OpenAsset(filnam); - if (in == nullptr) - return -1; - - vers = in->ReadInt16(); - in->ReadArray(&buff[0], 13, 1); - for (vv = 0; vv < 256; vv++) // there's a filler byte - in->ReadArray(&pall[vv], 3, 1); - - if (vers > 4) - return -1; - - if (vers == 4) - numspri = in->ReadInt16(); - else { - numspri = in->ReadInt16(); - if ((numspri < 2) || (numspri > 200)) - numspri = 200; - } - - for (vv = strt; vv <= eend; vv++) - sarray[vv] = nullptr; - - for (vv = 0; vv <= numspri; vv++) { - int coldep = in->ReadInt16(); - - if (coldep == 0) { - sarray[vv] = nullptr; - if (in->EOS()) - break; - - continue; - } - - if (in->EOS()) - break; - - if (vv > eend) - break; - - wdd = in->ReadInt16(); - htt = in->ReadInt16(); - if (vv < strt) { - in->Seek(wdd * htt); - continue; - } - sarray[vv] = BitmapHelper::CreateBitmap(wdd, htt, coldep * 8); - - if (sarray[vv] == nullptr) { - delete in; - return -1; - } - - for (hh = 0; hh < htt; hh++) - in->ReadArray(&sarray[vv]->GetScanLineForWriting(hh)[0], wdd * coldep, 1); - } - delete in; - return 0; - } - - void wputblock(Common::Bitmap *ds, int xx, int yy, Bitmap *bll, int xray) + void wputblock(Bitmap *ds, int xx, int yy, Bitmap *bll, int xray) { if (xray) - ds->Blit(bll, xx, yy, Common::kBitmap_Transparency); + ds->Blit(bll, xx, yy, kBitmap_Transparency); else ds->Blit(bll, 0, 0, xx, yy, bll->GetWidth(), bll->GetHeight()); } Bitmap wputblock_wrapper; // [IKM] argh! :[ - void wputblock_raw(Common::Bitmap *ds, int xx, int yy, BITMAP *bll, int xray) + void wputblock_raw(Bitmap *ds, int xx, int yy, BITMAP *bll, int xray) { wputblock_wrapper.WrapAllegroBitmap(bll, true); if (xray) - ds->Blit(&wputblock_wrapper, xx, yy, Common::kBitmap_Transparency); + ds->Blit(&wputblock_wrapper, xx, yy, kBitmap_Transparency); else ds->Blit(&wputblock_wrapper, 0, 0, xx, yy, wputblock_wrapper.GetWidth(), wputblock_wrapper.GetHeight()); } @@ -168,7 +94,7 @@ extern "C" int __wremap_keep_transparent = 1; - void wremap(color * pal1, Bitmap *picc, color * pal2) + void wremap(RGB * pal1, Bitmap *picc, RGB * pal2) { int jj; unsigned char color_mapped_table[256]; @@ -203,14 +129,9 @@ extern "C" } } - void wremapall(color * pal1, Bitmap *picc, color * pal2) + void wremapall(RGB * pal1, Bitmap *picc, RGB * pal2) { __wremap_keep_transparent--; wremap(pal1, picc, pal2); __wremap_keep_transparent++; } - - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Common/util/wgt2allg.h b/Common/util/wgt2allg.h index 8036d4ffb13..0c7442cfac5 100644 --- a/Common/util/wgt2allg.h +++ b/Common/util/wgt2allg.h @@ -12,68 +12,36 @@ // //============================================================================= // -// WGT -> Allegro portability interface -// -// wsavesprites and wloadsprites are hi-color compliant +// Few graphic utility functions, remains of a bigger deprecated api. // //============================================================================= - -#include "core/platform.h" - -#define _WGT45_ - #ifndef __WGT4_H #define __WGT4_H -#include "allegro.h" +#include // RGB namespace AGS { namespace Common { class Bitmap; }} using namespace AGS; // FIXME later - -#if defined WGT2ALLEGRO_NOFUNCTIONS -#error WGT2ALLEGRO_NOFUNCTIONS macro is obsolete and should not be defined anymore. -#endif - -#define color RGB - //============================================================================= // [IKM] 2012-09-13: this function is now defined in engine and editor separately extern void __my_setcolor(int *ctset, int newcol, int wantColDep); - -#ifdef __cplusplus -extern "C" -{ -#endif - extern void wsetrgb(int coll, int r, int g, int b, color * pall); - extern void wcolrotate(unsigned char start, unsigned char finish, int dir, color * pall); + extern void wsetrgb(int coll, int r, int g, int b, RGB * pall); + extern void wcolrotate(unsigned char start, unsigned char finish, int dir, RGB * pall); extern Common::Bitmap *wnewblock(Common::Bitmap *src, int x1, int y1, int x2, int y2); - extern int wloadsprites(color * pall, char *filnam, Common::Bitmap ** sarray, int strt, int eend); - extern void wputblock(Common::Bitmap *ds, int xx, int yy, Common::Bitmap *bll, int xray); // CHECKME: temporary solution for plugin system extern void wputblock_raw(Common::Bitmap *ds, int xx, int yy, BITMAP *bll, int xray); extern const int col_lookups[32]; - //extern void wsetcolor(int nval); - + // TODO: these are used only in the Editor's agsnative.cpp extern int __wremap_keep_transparent; - extern void wremap(color * pal1, Common::Bitmap *picc, color * pal2); - extern void wremapall(color * pal1, Common::Bitmap *picc, color * pal2); - -#ifdef __cplusplus -} -#endif - -#define XRAY 1 -#define NORMAL 0 - -// archive attributes to search for - al_findfirst breaks with 0 -#define FA_SEARCH -1 + extern void wremap(RGB * pal1, Common::Bitmap *picc, RGB * pal2); + extern void wremapall(RGB * pal1, Common::Bitmap *picc, RGB * pal2); #endif // __WGT4_H diff --git a/Engine/ac/draw.cpp b/Engine/ac/draw.cpp index bf786f6ab55..716b8e3dfb9 100644 --- a/Engine/ac/draw.cpp +++ b/Engine/ac/draw.cpp @@ -62,6 +62,7 @@ #include "gfx/blender.h" #include "media/audio/audio_system.h" #include "ac/game.h" +#include "util/wgt2allg.h" using namespace AGS::Common; using namespace AGS::Engine; @@ -114,7 +115,7 @@ extern IDriverDependantBitmap *mouseCursor; extern int hotx,hoty; extern int bg_just_changed; -color palette[256]; +RGB palette[256]; COLOR_MAP maincoltable; diff --git a/Engine/ac/draw.h b/Engine/ac/draw.h index af6e8e93549..2fc34283fcf 100644 --- a/Engine/ac/draw.h +++ b/Engine/ac/draw.h @@ -22,7 +22,6 @@ #include "core/types.h" #include "ac/common_defines.h" #include "gfx/gfx_def.h" -#include "util/wgt2allg.h" namespace AGS { @@ -37,17 +36,6 @@ using namespace AGS; // FIXME later #define IS_ANTIALIAS_SPRITES usetup.enable_antialiasing && (play.disable_antialiasing == 0) -// [IKM] WARNING: these definitions has to be made AFTER Allegro headers -// were included, because they override few Allegro function names; -// otherwise Allegro headers should not be included at all to the same -// code unit which uses these defines. -#define getr32(xx) ((xx >> _rgb_r_shift_32) & 0xFF) -#define getg32(xx) ((xx >> _rgb_g_shift_32) & 0xFF) -#define getb32(xx) ((xx >> _rgb_b_shift_32) & 0xFF) -#define geta32(xx) ((xx >> _rgb_a_shift_32) & 0xFF) -#define makeacol32(r,g,b,a) ((r << _rgb_r_shift_32) | (g << _rgb_g_shift_32) | (b << _rgb_b_shift_32) | (a << _rgb_a_shift_32)) - - struct CachedActSpsData { int xWas, yWas; int baselineWas; diff --git a/Engine/ac/dynamicsprite.cpp b/Engine/ac/dynamicsprite.cpp index 480a233e1ae..3d2fdb7ab33 100644 --- a/Engine/ac/dynamicsprite.cpp +++ b/Engine/ac/dynamicsprite.cpp @@ -44,7 +44,7 @@ extern RoomStatus*croom; extern CharacterCache *charcache; extern ObjectCache objcache[MAX_ROOM_OBJECTS]; -extern color palette[256]; +extern RGB palette[256]; extern AGS::Engine::IGraphicsDriver *gfxDriver; char check_dynamic_sprites_at_exit = 1; diff --git a/Engine/ac/event.cpp b/Engine/ac/event.cpp index 3c986a9fabc..b4d4cf4bcd2 100644 --- a/Engine/ac/event.cpp +++ b/Engine/ac/event.cpp @@ -42,10 +42,10 @@ extern RoomStruct thisroom; extern RoomStatus*croom; extern int displayed_room; extern GameState play; -extern color palette[256]; +extern RGB palette[256]; extern IGraphicsDriver *gfxDriver; extern AGSPlatformDriver *platform; -extern color old_palette[256]; +extern RGB old_palette[256]; int in_enters_screen=0,done_es_error = 0; int in_leaves_screen = -1; @@ -333,7 +333,7 @@ void process_event(EventHappened*evp) { else if (theTransition == FADE_DISSOLVE) { int pattern[16]={0,4,14,9,5,11,2,8,10,3,12,7,15,6,13,1}; int aa,bb,cc; - color interpal[256]; + RGB interpal[256]; IDriverDependantBitmap *ddb = prepare_screen_for_transition_in(); for (aa=0;aa<16;aa++) { diff --git a/Engine/ac/file.cpp b/Engine/ac/file.cpp index f733d3e0bf2..d98b2ae8e4d 100644 --- a/Engine/ac/file.cpp +++ b/Engine/ac/file.cpp @@ -11,7 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - +#include // file path functions, PACKFILE #include "ac/asset_helper.h" #include "ac/audiocliptype.h" #include "ac/file.h" diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index 85b1d376473..f154daa8d47 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -11,9 +11,8 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - +#include // file functions #include "ac/game.h" - #include "ac/common.h" #include "ac/view.h" #include "ac/audiocliptype.h" @@ -127,7 +126,7 @@ extern CachedActSpsData* actspswbcache; extern Bitmap **guibg; extern IDriverDependantBitmap **guibgbmp; extern char transFileName[MAX_PATH]; -extern color palette[256]; +extern RGB palette[256]; extern unsigned int loopcounter; extern Bitmap *raw_saved_screen; extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES]; @@ -1306,7 +1305,7 @@ void ReadCharacterExtras_Aligned(Stream *in) void restore_game_palette(Stream *in) { - in->ReadArray(&palette[0],sizeof(color),256); + in->ReadArray(&palette[0],sizeof(RGB),256); } void restore_game_dialogs(Stream *in) diff --git a/Engine/ac/gamesetup.cpp b/Engine/ac/gamesetup.cpp index 9c8dcd4dd42..d9d9b56d242 100644 --- a/Engine/ac/gamesetup.cpp +++ b/Engine/ac/gamesetup.cpp @@ -11,8 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include "util/wgt2allg.h" // DIGI_AUTODETECT & MIDI_AUTODETECT #include "ac/gamesetup.h" GameSetup::GameSetup() diff --git a/Engine/ac/global_dynamicsprite.cpp b/Engine/ac/global_dynamicsprite.cpp index b77a3f3c7ac..42d4d827d78 100644 --- a/Engine/ac/global_dynamicsprite.cpp +++ b/Engine/ac/global_dynamicsprite.cpp @@ -11,9 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include "ac/global_dynamicsprite.h" -#include "util/wgt2allg.h" // Allegro RGB, PALETTE #include "ac/draw.h" #include "ac/dynamicsprite.h" #include "ac/path_helper.h" diff --git a/Engine/ac/global_game.cpp b/Engine/ac/global_game.cpp index 6b826a428a4..6038fcf91b6 100644 --- a/Engine/ac/global_game.cpp +++ b/Engine/ac/global_game.cpp @@ -13,8 +13,8 @@ //============================================================================= #include - #include "core/platform.h" +#include // file path functions #include "ac/audiocliptype.h" #include "ac/global_game.h" #include "ac/common.h" @@ -80,7 +80,7 @@ extern int gui_disabled_style; extern RoomStruct thisroom; extern int getloctype_index; extern IGraphicsDriver *gfxDriver; -extern color palette[256]; +extern RGB palette[256]; #if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID extern int psp_gfx_renderer; diff --git a/Engine/ac/global_overlay.cpp b/Engine/ac/global_overlay.cpp index d9525810342..bbaf77f1907 100644 --- a/Engine/ac/global_overlay.cpp +++ b/Engine/ac/global_overlay.cpp @@ -26,6 +26,7 @@ #include "ac/spritecache.h" #include "ac/system.h" #include "gfx/bitmap.h" +#include "util/wgt2allg.h" using namespace Common; using namespace Engine; diff --git a/Engine/ac/global_palette.cpp b/Engine/ac/global_palette.cpp index 89048897657..aff9aa480d1 100644 --- a/Engine/ac/global_palette.cpp +++ b/Engine/ac/global_palette.cpp @@ -17,10 +17,11 @@ #include "ac/gamesetupstruct.h" #include "ac/gamestate.h" #include "ac/global_palette.h" +#include "util/wgt2allg.h" extern GameSetupStruct game; extern GameState play; -extern color palette[256]; +extern RGB palette[256]; void CyclePalette(int strt,int eend) { diff --git a/Engine/ac/global_screen.cpp b/Engine/ac/global_screen.cpp index 2a77a129146..fc739b8a4c1 100644 --- a/Engine/ac/global_screen.cpp +++ b/Engine/ac/global_screen.cpp @@ -11,7 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include "ac/common.h" #include "ac/gamesetup.h" #include "ac/draw.h" @@ -36,7 +35,7 @@ extern GameSetupStruct game; extern RoomStruct thisroom; extern IGraphicsDriver *gfxDriver; extern AGSPlatformDriver *platform; -extern color palette[256]; +extern RGB palette[256]; extern unsigned int loopcounter; void FlipScreen(int amount) { diff --git a/Engine/ac/global_video.cpp b/Engine/ac/global_video.cpp index 1d63035b14d..4c41ebed040 100644 --- a/Engine/ac/global_video.cpp +++ b/Engine/ac/global_video.cpp @@ -11,8 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include #include "ac/gamesetup.h" #include "ac/gamestate.h" #include "ac/global_audio.h" diff --git a/Engine/ac/invwindow.cpp b/Engine/ac/invwindow.cpp index 27c6be38519..1e7b77355b0 100644 --- a/Engine/ac/invwindow.cpp +++ b/Engine/ac/invwindow.cpp @@ -36,6 +36,7 @@ #include "util/math.h" #include "media/audio/audio_system.h" #include "ac/timer.h" +#include "util/wgt2allg.h" using namespace AGS::Common; diff --git a/Engine/ac/listbox.cpp b/Engine/ac/listbox.cpp index c6fe065c9b1..b7433ca8452 100644 --- a/Engine/ac/listbox.cpp +++ b/Engine/ac/listbox.cpp @@ -11,8 +11,8 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include +#include // find files #include "ac/listbox.h" #include "ac/common.h" #include "ac/game.h" diff --git a/Engine/ac/movelist.h b/Engine/ac/movelist.h index 2f860dc3a81..069f3c4af5f 100644 --- a/Engine/ac/movelist.h +++ b/Engine/ac/movelist.h @@ -11,11 +11,9 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #ifndef __AC_MOVE_H #define __AC_MOVE_H - -#include "util/wgt2allg.h" // fixed type +#include // fixed math #include "game/savegame.h" // Forward declaration diff --git a/Engine/ac/region.cpp b/Engine/ac/region.cpp index 2578c2a0f71..315a506256a 100644 --- a/Engine/ac/region.cpp +++ b/Engine/ac/region.cpp @@ -29,7 +29,7 @@ extern RoomStruct thisroom; extern RoomStatus*croom; extern GameSetupStruct game; extern COLOR_MAP maincoltable; -extern color palette[256]; +extern RGB palette[256]; extern CCRegion ccDynamicRegion; diff --git a/Engine/ac/room.cpp b/Engine/ac/room.cpp index 05553b4fc86..89f98fc85c1 100644 --- a/Engine/ac/room.cpp +++ b/Engine/ac/room.cpp @@ -105,7 +105,7 @@ extern IDriverDependantBitmap* *actspsbmp; extern Bitmap **actspswb; extern IDriverDependantBitmap* *actspswbbmp; extern CachedActSpsData* actspswbcache; -extern color palette[256]; +extern RGB palette[256]; extern int mouse_z_was; extern Bitmap **guibg; @@ -1019,7 +1019,7 @@ void on_background_frame_change () { invalidate_cached_walkbehinds(); // get the new frame's palette - memcpy (palette, thisroom.BgFrames[play.bg_frame].Palette, sizeof(color) * 256); + memcpy (palette, thisroom.BgFrames[play.bg_frame].Palette, sizeof(RGB) * 256); // hi-colour, update the palette. It won't have an immediate effect // but will be drawn properly when the screen fades in diff --git a/Engine/ac/screen.cpp b/Engine/ac/screen.cpp index c28ea7f9a5b..073695a824e 100644 --- a/Engine/ac/screen.cpp +++ b/Engine/ac/screen.cpp @@ -51,7 +51,7 @@ void my_fade_in(PALETTE p, int speed) { } Bitmap *saved_viewport_bitmap = nullptr; -color old_palette[256]; +RGB old_palette[256]; void current_fade_out_effect () { if (pl_run_plugin_hooks(AGSE_TRANSITIONOUT, 0)) return; diff --git a/Engine/ac/sprite.cpp b/Engine/ac/sprite.cpp index 0ae47147a4a..92312c5ca22 100644 --- a/Engine/ac/sprite.cpp +++ b/Engine/ac/sprite.cpp @@ -30,7 +30,7 @@ using namespace AGS::Engine; extern GameSetupStruct game; extern SpriteCache spriteset; extern int our_eip, eip_guinum, eip_guiobj; -extern color palette[256]; +extern RGB palette[256]; extern IGraphicsDriver *gfxDriver; extern AGSPlatformDriver *platform; diff --git a/Engine/debug/debug.cpp b/Engine/debug/debug.cpp index 059fe2c0f39..ddbad57347f 100644 --- a/Engine/debug/debug.cpp +++ b/Engine/debug/debug.cpp @@ -14,8 +14,13 @@ #include #include -#include #include "core/platform.h" +#if AGS_PLATFORM_OS_WINDOWS +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP +#endif +#include #include "ac/common.h" #include "ac/gamesetupstruct.h" #include "ac/runtime_defines.h" @@ -37,10 +42,6 @@ #include "util/string_utils.h" #include "util/textstreamwriter.h" -#if AGS_PLATFORM_OS_WINDOWS -#include -#endif - using namespace AGS::Common; using namespace AGS::Engine; diff --git a/Engine/debug/filebasedagsdebugger.cpp b/Engine/debug/filebasedagsdebugger.cpp index 263798725e0..4a2d211402e 100644 --- a/Engine/debug/filebasedagsdebugger.cpp +++ b/Engine/debug/filebasedagsdebugger.cpp @@ -13,11 +13,11 @@ //============================================================================= #include +#include // file functions #include "debug/filebasedagsdebugger.h" #include "ac/file.h" // filelength() #include "util/stream.h" #include "util/textstreamwriter.h" -#include "util/wgt2allg.h" // exists() #include "platform/base/agsplatformdriver.h" using AGS::Common::Stream; diff --git a/Engine/device/mousew32.cpp b/Engine/device/mousew32.cpp index 32524b5c982..7a27efb07e0 100644 --- a/Engine/device/mousew32.cpp +++ b/Engine/device/mousew32.cpp @@ -43,7 +43,7 @@ static int disable_mgetgraphpos = 0; char ignore_bounds = 0; extern char alpha_blend_cursor ; Bitmap *mousecurs[MAXCURSORS]; -extern color palette[256]; +extern RGB palette[256]; extern volatile bool switched_away; namespace Mouse diff --git a/Engine/game/savegame_components.cpp b/Engine/game/savegame_components.cpp index bd9d6bf09a0..d96d9f24d7b 100644 --- a/Engine/game/savegame_components.cpp +++ b/Engine/game/savegame_components.cpp @@ -55,7 +55,7 @@ using namespace Common; extern GameSetupStruct game; -extern color palette[256]; +extern RGB palette[256]; extern DialogTopic *dialog; extern AnimatingGUIButton animbuts[MAX_ANIMATING_BUTTONS]; extern int numAnimButs; @@ -220,7 +220,7 @@ HSaveError WriteGameState(PStream out) game.WriteForSavegame(out); // Game palette // TODO: probably no need to save this for hi/true-res game - out->WriteArray(palette, sizeof(color), 256); + out->WriteArray(palette, sizeof(RGB), 256); if (loaded_game_file_version <= kGameVersion_272) { @@ -314,7 +314,7 @@ HSaveError ReadGameState(PStream in, int32_t cmp_ver, const PreservedParams &pp, // Game base game.ReadFromSavegame(in); // Game palette - in->ReadArray(palette, sizeof(color), 256); + in->ReadArray(palette, sizeof(RGB), 256); if (loaded_game_file_version <= kGameVersion_272) { diff --git a/Engine/gfx/blender.cpp b/Engine/gfx/blender.cpp index 1eea39853e9..a417bc9683f 100644 --- a/Engine/gfx/blender.cpp +++ b/Engine/gfx/blender.cpp @@ -11,23 +11,16 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include "core/types.h" #include "gfx/blender.h" -#include "util/wgt2allg.h" +#include +#include "core/types.h" extern "C" { unsigned long _blender_trans16(unsigned long x, unsigned long y, unsigned long n); unsigned long _blender_trans15(unsigned long x, unsigned long y, unsigned long n); } -// the allegro "inline" ones are not actually inline, so #define -// over them to speed it up -#define getr32(xx) ((xx >> _rgb_r_shift_32) & 0xFF) -#define getg32(xx) ((xx >> _rgb_g_shift_32) & 0xFF) -#define getb32(xx) ((xx >> _rgb_b_shift_32) & 0xFF) -#define geta32(xx) ((xx >> _rgb_a_shift_32) & 0xFF) -#define makeacol32(r,g,b,a) ((r << _rgb_r_shift_32) | (g << _rgb_g_shift_32) | (b << _rgb_b_shift_32) | (a << _rgb_a_shift_32)) + // Take hue and saturation of blend colour, luminance of image unsigned long _myblender_color15_light(unsigned long x, unsigned long y, unsigned long n) diff --git a/Engine/gfx/color_engine.cpp b/Engine/gfx/color_engine.cpp index 4946b2b4bf5..1c50f3c2b36 100644 --- a/Engine/gfx/color_engine.cpp +++ b/Engine/gfx/color_engine.cpp @@ -15,11 +15,8 @@ // Implementation from wgt2allg.cpp specific to Engine runtime // //============================================================================= - -#include "core/platform.h" - +#include #include "util/wgt2allg.h" -#include "gfx/bitmap.h" void __my_setcolor(int *ctset, int newcol, int wantColDep) { diff --git a/Engine/gfx/gfxdriverbase.cpp b/Engine/gfx/gfxdriverbase.cpp index 737d6a5071b..e41c9ce05a6 100644 --- a/Engine/gfx/gfxdriverbase.cpp +++ b/Engine/gfx/gfxdriverbase.cpp @@ -11,8 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include "util/wgt2allg.h" #include "gfx/ali3dexception.h" #include "gfx/bitmap.h" #include "gfx/gfxfilter.h" diff --git a/Engine/gfx/graphicsdriver.h b/Engine/gfx/graphicsdriver.h index f2d4e0d4759..4c61e06c8e2 100644 --- a/Engine/gfx/graphicsdriver.h +++ b/Engine/gfx/graphicsdriver.h @@ -15,11 +15,10 @@ // Graphics driver interface // //============================================================================= - #ifndef __AGS_EE_GFX__GRAPHICSDRIVER_H #define __AGS_EE_GFX__GRAPHICSDRIVER_H - #include +#include // RGB, PALETTE #include "gfx/gfxdefines.h" #include "gfx/gfxmodelist.h" #include "util/geometry.h" diff --git a/Engine/gfx/ogl_headers.h b/Engine/gfx/ogl_headers.h index 47d3e0bdfec..9bd2a76ebec 100644 --- a/Engine/gfx/ogl_headers.h +++ b/Engine/gfx/ogl_headers.h @@ -22,14 +22,14 @@ #if AGS_PLATFORM_OS_WINDOWS #include -#include -#include +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP #include "glad/glad.h" #include "glad/glad_wgl.h" #elif AGS_PLATFORM_OS_LINUX #include -#include #include "glad/glad.h" #include "glad/glad_glx.h" diff --git a/Engine/gui/cscidialog.cpp b/Engine/gui/cscidialog.cpp index 63753018bdc..7a2e0a85e1d 100644 --- a/Engine/gui/cscidialog.cpp +++ b/Engine/gui/cscidialog.cpp @@ -11,9 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include -#include "util/wgt2allg.h" #include "ac/common.h" #include "ac/draw.h" #include "ac/gamesetup.h" diff --git a/Engine/gui/guidialog.cpp b/Engine/gui/guidialog.cpp index 7baa314387b..8146ffe67fd 100644 --- a/Engine/gui/guidialog.cpp +++ b/Engine/gui/guidialog.cpp @@ -11,10 +11,9 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include +#include // find files #include "gui/guidialog.h" - #include "ac/common.h" #include "ac/draw.h" #include "ac/game.h" diff --git a/Engine/gui/mylistbox.cpp b/Engine/gui/mylistbox.cpp index 633ade75530..95cd8bab966 100644 --- a/Engine/gui/mylistbox.cpp +++ b/Engine/gui/mylistbox.cpp @@ -11,9 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include -#include "util/wgt2allg.h" #include "ac/common.h" #include "ac/gamesetup.h" #include "ac/keycode.h" diff --git a/Engine/gui/mypushbutton.cpp b/Engine/gui/mypushbutton.cpp index f23a0f3702e..4de586fcc91 100644 --- a/Engine/gui/mypushbutton.cpp +++ b/Engine/gui/mypushbutton.cpp @@ -11,9 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include -#include "util/wgt2allg.h" #include "ac/common.h" #include "ac/sys_events.h" #include "font/fonts.h" diff --git a/Engine/gui/mytextbox.cpp b/Engine/gui/mytextbox.cpp index 6c199f1bf2d..7c0fc1c233f 100644 --- a/Engine/gui/mytextbox.cpp +++ b/Engine/gui/mytextbox.cpp @@ -12,7 +12,6 @@ // //============================================================================= #include -#include "util/wgt2allg.h" #include "ac/keycode.h" #include "font/fonts.h" #include "gui/mytextbox.h" diff --git a/Engine/main/config.cpp b/Engine/main/config.cpp index 1e9777e018e..11f9aa4ae2a 100644 --- a/Engine/main/config.cpp +++ b/Engine/main/config.cpp @@ -16,8 +16,8 @@ // Game configuration // #include // toupper - #include "core/platform.h" +#include // file path functions #include "ac/gamesetup.h" #include "ac/gamesetupstruct.h" #include "ac/gamestate.h" diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index 704e1d7b5ec..8d35e91f028 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -22,6 +22,7 @@ #if AGS_PLATFORM_OS_WINDOWS #include // _spawnl #endif +#include // find file and path functions #include "main/mainheader.h" #include "ac/asset_helper.h" @@ -94,7 +95,7 @@ extern int numLipLines, curLipLine, curLipLinePhoneme; extern ScriptSystem scsystem; extern IGraphicsDriver *gfxDriver; extern Bitmap **actsps; -extern color palette[256]; +extern RGB palette[256]; extern CharacterExtras *charextra; extern CharacterInfo*playerchar; extern Bitmap **guibg; @@ -637,7 +638,7 @@ int engine_check_font_was_loaded() // Do the preload graphic if available void show_preload() { - color temppal[256]; + RGB temppal[256]; Bitmap *splashsc = BitmapHelper::CreateRawBitmapOwner( load_pcx("preload.pcx",temppal) ); if (splashsc != nullptr) { diff --git a/Engine/main/game_file.cpp b/Engine/main/game_file.cpp index 82973f51026..b0e2228b7cc 100644 --- a/Engine/main/game_file.cpp +++ b/Engine/main/game_file.cpp @@ -42,7 +42,6 @@ #include "ac/gamesetup.h" #include "game/main_game_file.h" #include "game/game_init.h" -#include "plugin/agsplugin.h" #include "script/script.h" using namespace AGS::Common; diff --git a/Engine/main/main.cpp b/Engine/main/main.cpp index ee0a47fad45..7a780f8b39b 100644 --- a/Engine/main/main.cpp +++ b/Engine/main/main.cpp @@ -24,8 +24,8 @@ #include "core/platform.h" #define AGS_PLATFORM_DEFINES_PSP_VARS (AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID) - #include +#include // allegro_exit #include "ac/common.h" #include "ac/gamesetup.h" #include "ac/gamestate.h" diff --git a/Engine/main/quit.cpp b/Engine/main/quit.cpp index 5e3667a9791..98a9647a0fe 100644 --- a/Engine/main/quit.cpp +++ b/Engine/main/quit.cpp @@ -15,9 +15,10 @@ // // Quit game procedure // - #include "core/platform.h" +#include // find files, allegro_exit #include "ac/cdaudio.h" +#include "ac/common.h" #include "ac/gamesetup.h" #include "ac/gamesetupstruct.h" #include "ac/roomstatus.h" @@ -202,8 +203,8 @@ void quit_release_data() void quit_delete_temp_files() { - al_ffblk dfb; - int dun = al_findfirst("~ac*.tmp",&dfb,FA_SEARCH); + al_ffblk dfb; + int dun = al_findfirst("~ac*.tmp", &dfb, FA_SEARCH); while (!dun) { ::remove(dfb.name); dun = al_findnext(&dfb); diff --git a/Engine/media/audio/audio.cpp b/Engine/media/audio/audio.cpp index 736a2db53e7..ae7aba8482b 100644 --- a/Engine/media/audio/audio.cpp +++ b/Engine/media/audio/audio.cpp @@ -11,11 +11,8 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include - #include "core/platform.h" -#include "util/wgt2allg.h" #include "media/audio/audio.h" #include "ac/audiocliptype.h" #include "ac/gamesetupstruct.h" diff --git a/Engine/media/audio/soundclip.cpp b/Engine/media/audio/soundclip.cpp index 13484db5766..45b6e4142ca 100644 --- a/Engine/media/audio/soundclip.cpp +++ b/Engine/media/audio/soundclip.cpp @@ -11,8 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include "util/wgt2allg.h" #include "media/audio/audio.h" #include "media/audio/audiodefines.h" #include "media/audio/soundclip.h" diff --git a/Engine/media/video/video.cpp b/Engine/media/video/video.cpp index 752a2e3e5bd..fd38eaa4d0a 100644 --- a/Engine/media/video/video.cpp +++ b/Engine/media/video/video.cpp @@ -111,7 +111,7 @@ extern "C" int fli_callback() { } void play_flc_file(int numb,int playflags) { - color oldpal[256]; + RGB oldpal[256]; // AGS 2.x: If the screen is faded out, fade in again when playing a movie. if (loaded_game_file_version <= kGameVersion_272) diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index 1d2cfc25897..d9cec9d1395 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -15,16 +15,13 @@ // AGS Platform-specific functions // //============================================================================= - #include -#include "util/wgt2allg.h" #include "platform/base/agsplatformdriver.h" #include "ac/common.h" #include "ac/runtime_defines.h" #include "util/string_utils.h" #include "util/stream.h" #include "gfx/bitmap.h" -#include "plugin/agsplugin.h" #include "ac/timer.h" #include "media/audio/audio_system.h" diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index b558687706f..42addf0ae7b 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -15,12 +15,10 @@ #include "core/platform.h" #if AGS_PLATFORM_OS_WINDOWS - -// ********* WINDOWS ********* - +#include #include -#include -#include +#include // find files +#include // prevents typename conflicts #include "ac/common.h" #include "ac/draw.h" #include "ac/gamesetup.h" @@ -55,7 +53,7 @@ extern GameSetupStruct game; extern GameSetup usetup; extern int our_eip; extern IGraphicsDriver *gfxDriver; -extern color palette[256]; +extern RGB palette[256]; #include #include diff --git a/Engine/platform/windows/debug/namedpipesagsdebugger.h b/Engine/platform/windows/debug/namedpipesagsdebugger.h index 2ee333ef19d..7073fac2567 100644 --- a/Engine/platform/windows/debug/namedpipesagsdebugger.h +++ b/Engine/platform/windows/debug/namedpipesagsdebugger.h @@ -16,7 +16,6 @@ #define __AC_NAMEDPIPESAGSDEBUGGER_H #include -#include #include "debug/agseditordebugger.h" struct NamedPipesAGSDebugger : IAGSEditorDebugger diff --git a/Engine/platform/windows/gfx/ali3dd3d.h b/Engine/platform/windows/gfx/ali3dd3d.h index a8cc442f0a6..ef5102a3adc 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.h +++ b/Engine/platform/windows/gfx/ali3dd3d.h @@ -26,9 +26,9 @@ #endif #include -#include -#include +#define BITMAP WINDOWS_BITMAP #include +#undef BITMAP #include "gfx/bitmap.h" #include "gfx/ddb.h" #include "gfx/gfxdriverfactorybase.h" diff --git a/Engine/platform/windows/media/video/acwavi.cpp b/Engine/platform/windows/media/video/acwavi.cpp index 7031dc2ff47..1f36c2cec5d 100644 --- a/Engine/platform/windows/media/video/acwavi.cpp +++ b/Engine/platform/windows/media/video/acwavi.cpp @@ -21,11 +21,9 @@ #include "core/platform.h" #if AGS_PLATFORM_OS_WINDOWS && ! defined (AGS_NO_VIDEO_PLAYER) - -//#define ALLEGRO_STATICLINK // already defined in project settings -#include -#include +#define BITMAP WINDOWS_BITMAP #include +#undef BITMAP #include #include #include // Multimedia stream interfaces diff --git a/Engine/platform/windows/media/video/acwavi3d.cpp b/Engine/platform/windows/media/video/acwavi3d.cpp index 64cba190195..5b097cd4a63 100644 --- a/Engine/platform/windows/media/video/acwavi3d.cpp +++ b/Engine/platform/windows/media/video/acwavi3d.cpp @@ -21,10 +21,6 @@ #if AGS_PLATFORM_OS_WINDOWS && ! defined (AGS_NO_VIDEO_PLAYER) -//#define ALLEGRO_STATICLINK // already defined in project settings -#include -#include -#include #include #include #define DWORD_PTR DWORD* diff --git a/Engine/platform/windows/setup/winsetup.cpp b/Engine/platform/windows/setup/winsetup.cpp index 4b70a242793..b39f2d8d701 100644 --- a/Engine/platform/windows/setup/winsetup.cpp +++ b/Engine/platform/windows/setup/winsetup.cpp @@ -11,12 +11,12 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include "core/platform.h" #if AGS_PLATFORM_OS_WINDOWS - +#define BITMAP WINDOWS_BITMAP #include +#undef BITMAP #include #include #include @@ -28,8 +28,6 @@ #include "ac/gamestructdefines.h" #undef RGB #undef PALETTE -#define RGB void* -#define PALETTE void* #include "gfx/gfxdriverfactory.h" #include "gfx/gfxfilter.h" #include "gfx/graphicsdriver.h" diff --git a/Engine/plugin/agsplugin.cpp b/Engine/plugin/agsplugin.cpp index 2fb2e3bbaff..a451ae7bdd5 100644 --- a/Engine/plugin/agsplugin.cpp +++ b/Engine/plugin/agsplugin.cpp @@ -11,13 +11,15 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include #include "core/platform.h" +#include #if AGS_PLATFORM_OS_WINDOWS -#include "platform/windows/winapi_exclusive.h" +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP #endif -#include "util/wgt2allg.h" +#include "plugin/agsplugin.h" #include "ac/common.h" #include "ac/view.h" #include "ac/charactercache.h" @@ -37,34 +39,35 @@ #include "ac/path_helper.h" #include "ac/roomstatus.h" #include "ac/string.h" +#include "ac/spritecache.h" #include "ac/dynobj/cc_dynamicobject_addr_and_manager.h" +#include "ac/dynobj/scriptstring.h" #include "font/fonts.h" -#include "util/string_compat.h" #include "debug/debug_log.h" #include "debug/debugger.h" +#include "debug/out.h" #include "device/mousew32.h" +#include "gfx/bitmap.h" +#include "gfx/graphicsdriver.h" +#include "gfx/gfx_util.h" +#include "gfx/gfxfilter.h" #include "gui/guidefines.h" #include "main/game_run.h" +#include "main/graphics_mode.h" #include "main/engine.h" -#include "plugin/agsplugin.h" +#include "media/audio/audio_system.h" #include "plugin/plugin_engine.h" #include "plugin/plugin_builtin.h" #include "plugin/pluginobjectreader.h" +#include "script/runtimescriptvalue.h" #include "script/script.h" #include "script/script_runtime.h" -#include "ac/spritecache.h" -#include "util/stream.h" -#include "gfx/bitmap.h" -#include "gfx/graphicsdriver.h" -#include "gfx/gfxfilter.h" -#include "script/runtimescriptvalue.h" -#include "debug/out.h" -#include "ac/dynobj/scriptstring.h" -#include "main/graphics_mode.h" -#include "gfx/gfx_util.h" -#include "util/memory.h" #include "util/filestream.h" -#include "media/audio/audio_system.h" +#include "util/library.h" +#include "util/memory.h" +#include "util/stream.h" +#include "util/string_compat.h" +#include "util/wgt2allg.h" using namespace AGS::Common; using namespace AGS::Common::Memory; @@ -98,7 +101,7 @@ extern ccInstance *gameinst, *roominst; extern CharacterCache *charcache; extern ObjectCache objcache[MAX_ROOM_OBJECTS]; extern MoveList *mls; -extern color palette[256]; +extern RGB palette[256]; extern PluginObjectReader pluginReaders[MAX_PLUGIN_OBJECT_READERS]; extern int numPluginReaders; extern RuntimeScriptValue GlobalReturnValue; @@ -107,11 +110,6 @@ extern ScriptString myScriptStringImpl; // **************** PLUGIN IMPLEMENTATION **************** -#include "util/library.h" - - - - struct EnginePlugin { char filename[PLUGIN_FILENAME_MAX+1]; AGS::Engine::Library library; @@ -430,7 +428,7 @@ AGSColor* IAGSEngine::GetPalette () { return (AGSColor*)&palette[0]; } void IAGSEngine::SetPalette (int32 start, int32 finish, AGSColor *cpl) { - set_palette_range((color*)cpl, start, finish, 0); + set_palette_range((RGB*)cpl, start, finish, 0); } int IAGSEngine::GetNumCharacters () { return game.numcharacters; diff --git a/Engine/util/library_windows.h b/Engine/util/library_windows.h index 7d4e5a7454e..907f9529c75 100644 --- a/Engine/util/library_windows.h +++ b/Engine/util/library_windows.h @@ -98,7 +98,7 @@ class WindowsLibrary : BaseLibrary } private: - HANDLE _library; + HMODULE _library; }; diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj b/Solutions/Common.Lib/Common.Lib.vcxproj index ee98ba3ef6a..920ee1dea94 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj +++ b/Solutions/Common.Lib/Common.Lib.vcxproj @@ -155,7 +155,7 @@ Disabled ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -174,7 +174,7 @@ Disabled ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -195,7 +195,7 @@ MaxSpeed true ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -214,7 +214,7 @@ MaxSpeed true ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -234,7 +234,7 @@ MaxSpeed true ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -252,7 +252,7 @@ Disabled ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index edf20b4c609..b2f720bcad2 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -118,7 +118,7 @@ Disabled ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -146,7 +146,7 @@ Disabled ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -176,7 +176,7 @@ MaxSpeed true ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -209,7 +209,7 @@ MaxSpeed true ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true From 8c74793f3b5717b195edd0d156cd498eac10a106 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Tue, 10 Nov 2020 08:32:47 +0300 Subject: [PATCH 26/41] Hide remaining allegro filepath functions, also remove unused code --- Common/util/misc.cpp | 4 ++++ Common/util/path.cpp | 17 +++++++++----- Common/util/path.h | 4 ++++ Engine/ac/file.cpp | 5 ++-- Engine/ac/game.cpp | 7 +++--- Engine/ac/global_game.cpp | 4 ++-- Engine/debug/filebasedagsdebugger.cpp | 13 +++++------ Engine/main/config.cpp | 31 +------------------------ Engine/main/engine.cpp | 8 +++---- Engine/platform/windows/acplwin.cpp | 33 +++++++-------------------- 10 files changed, 45 insertions(+), 81 deletions(-) diff --git a/Common/util/misc.cpp b/Common/util/misc.cpp index 51b403376ab..13d7adb8de0 100644 --- a/Common/util/misc.cpp +++ b/Common/util/misc.cpp @@ -57,6 +57,10 @@ using namespace AGS::Common; +// +// TODO: rewrite all this in a cleaner way perhaps, and move to our file or path utilities unit +// + #if !defined (AGS_CASE_SENSITIVE_FILESYSTEM) #include /* File Name Concatenator basically on Windows / DOS */ diff --git a/Common/util/path.cpp b/Common/util/path.cpp index bf42c684aff..69d85312f69 100644 --- a/Common/util/path.cpp +++ b/Common/util/path.cpp @@ -39,14 +39,14 @@ bool IsFileOrDir(const String &filename) return ags_path_exists(fixed_path.GetCStr()) != 0; } +String GetFilename(const String &path) +{ + return get_filename(path); +} + String GetFileExtension(const String &path) { - const auto pathComponents = path.Split('/'); - if (pathComponents.size() <= 0) { return ""; } - const String baseName = pathComponents[pathComponents.size() - 1]; - const int at = baseName.FindCharReverse('.'); - if (at < 0) { return ""; } - return baseName.Mid(at + 1); + return get_extension(path); } int ComparePaths(const String &path1, const String &path2) @@ -105,6 +105,11 @@ bool IsSameOrSubDir(const String &parent, const String &path) return true; } +bool IsRelativePath(const String &path) +{ + return is_relative_filename(path); +} + void FixupPath(String &path) { #if AGS_PLATFORM_OS_WINDOWS diff --git a/Common/util/path.h b/Common/util/path.h index 41d938975fc..28ee945eb08 100644 --- a/Common/util/path.h +++ b/Common/util/path.h @@ -34,6 +34,8 @@ namespace Path // Tells if the given path is file or directory; // may be used to check if it's valid to use bool IsFileOrDir(const String &filename); + // Returns filename part out of the longer path + String GetFilename(const String &path); // Returns file's extension; file may be a fully qualified path too String GetFileExtension(const String &path); @@ -50,6 +52,8 @@ namespace Path // Tells if the path points to the parent path's location or lower directory; // return FALSE if the path points to outside of the parent location. bool IsSameOrSubDir(const String &parent, const String &path); + // Tells if the path is relative. + bool IsRelativePath(const String &path); // Makes a path have only '/' slashes; this is to make it easier to work // with path, knowing it contains only one type of directory separators diff --git a/Engine/ac/file.cpp b/Engine/ac/file.cpp index d98b2ae8e4d..7d1624fe2eb 100644 --- a/Engine/ac/file.cpp +++ b/Engine/ac/file.cpp @@ -11,7 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= -#include // file path functions, PACKFILE #include "ac/asset_helper.h" #include "ac/audiocliptype.h" #include "ac/file.h" @@ -253,7 +252,7 @@ String FixSlashAfterToken(const String &path) String MakeSpecialSubDir(const String &sp_dir) { - if (is_relative_filename(sp_dir)) + if (Path::IsRelativePath(sp_dir)) return sp_dir; String full_path = sp_dir; if (full_path.GetLast() != '/' && full_path.GetLast() != '\\') @@ -277,7 +276,7 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath { rp = ResolvedPath(); - bool is_absolute = !is_relative_filename(orig_sc_path); + bool is_absolute = !Path::IsRelativePath(orig_sc_path); if (is_absolute && !read_only) { debug_script_warn("Attempt to access file '%s' denied (cannot write to absolute path)", orig_sc_path.GetCStr()); diff --git a/Engine/ac/game.cpp b/Engine/ac/game.cpp index f154daa8d47..012d0f61c1b 100644 --- a/Engine/ac/game.cpp +++ b/Engine/ac/game.cpp @@ -11,7 +11,6 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= -#include // file functions #include "ac/game.h" #include "ac/common.h" #include "ac/view.h" @@ -378,7 +377,7 @@ bool MakeSaveGameDir(const String &newFolder, ResolvedPath &rp) { rp = ResolvedPath(); // don't allow absolute paths - if (!is_relative_filename(newFolder)) + if (!Path::IsRelativePath(newFolder)) return false; String base_dir; @@ -1055,9 +1054,9 @@ long write_screen_shot_for_vista(Stream *out, Bitmap *screenshot) update_polled_stuff_if_runtime(); - if (exists(tempFileName)) + if (Path::IsFile(tempFileName)) { - fileSize = file_size_ex(tempFileName); + fileSize = File::GetFileSize(tempFileName); char *buffer = (char*)malloc(fileSize); Stream *temp_in = Common::File::OpenFileRead(tempFileName); diff --git a/Engine/ac/global_game.cpp b/Engine/ac/global_game.cpp index 6038fcf91b6..321a1f0befd 100644 --- a/Engine/ac/global_game.cpp +++ b/Engine/ac/global_game.cpp @@ -14,7 +14,6 @@ #include #include "core/platform.h" -#include // file path functions #include "ac/audiocliptype.h" #include "ac/global_game.h" #include "ac/common.h" @@ -58,6 +57,7 @@ #include "core/assetmanager.h" #include "main/config.h" #include "main/game_file.h" +#include "util/path.h" #include "util/string_utils.h" #include "media/audio/audio_system.h" #include "platform/base/sys_main.h" @@ -244,7 +244,7 @@ int RunAGSGame (const char *newgame, unsigned int mode, int data) { // need to copy, since the script gets destroyed get_install_dir_path(gamefilenamebuf, newgame); ResPaths.GamePak.Path = gamefilenamebuf; - ResPaths.GamePak.Name = get_filename(gamefilenamebuf); + ResPaths.GamePak.Name = Path::GetFilename(gamefilenamebuf); play.takeover_data = data; load_new_game_restore = -1; diff --git a/Engine/debug/filebasedagsdebugger.cpp b/Engine/debug/filebasedagsdebugger.cpp index 4a2d211402e..ae4ad2a559e 100644 --- a/Engine/debug/filebasedagsdebugger.cpp +++ b/Engine/debug/filebasedagsdebugger.cpp @@ -13,21 +13,20 @@ //============================================================================= #include -#include // file functions #include "debug/filebasedagsdebugger.h" -#include "ac/file.h" // filelength() +#include "util/file.h" +#include "util/path.h" #include "util/stream.h" #include "util/textstreamwriter.h" #include "platform/base/agsplatformdriver.h" -using AGS::Common::Stream; -using AGS::Common::TextStreamWriter; +using namespace AGS::Common; const char* SENT_MESSAGE_FILE_NAME = "dbgrecv.tmp"; bool FileBasedAGSDebugger::Initialize() { - if (exists(SENT_MESSAGE_FILE_NAME)) + if (Path::IsFile(SENT_MESSAGE_FILE_NAME)) { ::remove(SENT_MESSAGE_FILE_NAME); } @@ -40,7 +39,7 @@ void FileBasedAGSDebugger::Shutdown() bool FileBasedAGSDebugger::SendMessageToEditor(const char *message) { - while (exists(SENT_MESSAGE_FILE_NAME)) + while (Path::IsFile(SENT_MESSAGE_FILE_NAME)) { platform->YieldCPU(); } @@ -56,7 +55,7 @@ bool FileBasedAGSDebugger::SendMessageToEditor(const char *message) bool FileBasedAGSDebugger::IsMessageAvailable() { - return (exists("dbgsend.tmp") != 0); + return (Path::IsFile("dbgsend.tmp") != 0); } char* FileBasedAGSDebugger::GetNextMessage() diff --git a/Engine/main/config.cpp b/Engine/main/config.cpp index 11f9aa4ae2a..034b29732c8 100644 --- a/Engine/main/config.cpp +++ b/Engine/main/config.cpp @@ -17,7 +17,6 @@ // #include // toupper #include "core/platform.h" -#include // file path functions #include "ac/gamesetup.h" #include "ac/gamesetupstruct.h" #include "ac/gamestate.h" @@ -50,29 +49,6 @@ extern GameState play; // Filename of the default config file, the one found in the game installation const String DefaultConfigFileName = "acsetup.cfg"; -// Replace the filename part of complete path WASGV with INIFIL -// TODO: get rid of this and use proper lib path function instead -void INIgetdirec(char *wasgv, const char *inifil) { - int u = strlen(wasgv) - 1; - - for (u = strlen(wasgv) - 1; u >= 0; u--) { - if ((wasgv[u] == '\\') || (wasgv[u] == '/')) { - memcpy(&wasgv[u + 1], inifil, strlen(inifil) + 1); - break; - } - } - - if (u <= 0) { - // no slashes - either the path is just "f:acwin.exe" - if (strchr(wasgv, ':') != nullptr) - memcpy(strchr(wasgv, ':') + 1, inifil, strlen(inifil) + 1); - // or it's just "acwin.exe" (unlikely) - else - strcpy(wasgv, inifil); - } - -} - bool INIreaditem(const ConfigTree &cfg, const String §n, const String &item, String &value) { ConfigNode sec_it = cfg.find(sectn); @@ -233,12 +209,7 @@ String find_default_cfg_file(const char *alt_cfg_file) String filename = String::FromFormat("%s/%s", Directory::GetCurrentDirectory().GetCStr(), DefaultConfigFileName.GetCStr()); if (!Common::File::TestReadFile(filename)) { - char conffilebuf[512]; - strcpy(conffilebuf, alt_cfg_file); - fix_filename_case(conffilebuf); - fix_filename_slashes(conffilebuf); - INIgetdirec(conffilebuf, DefaultConfigFileName); - filename = conffilebuf; + filename = String::FromFormat("%s/%s", alt_cfg_file, DefaultConfigFileName.GetCStr()); } return filename; } diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index 8d35e91f028..141354927c8 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -22,7 +22,7 @@ #if AGS_PLATFORM_OS_WINDOWS #include // _spawnl #endif -#include // find file and path functions +#include // allegro_install and _exit #include "main/mainheader.h" #include "ac/asset_helper.h" @@ -538,7 +538,7 @@ void engine_init_directories() ResPaths.DataDir = usetup.data_files_dir; ResPaths.GamePak.Path = usetup.main_data_filepath; - ResPaths.GamePak.Name = get_filename(usetup.main_data_filepath); + ResPaths.GamePak.Name = Path::GetFilename(usetup.main_data_filepath); set_install_dir(usetup.install_dir, usetup.install_audio_dir, usetup.install_voice_dir); if (!usetup.install_dir.IsEmpty()) @@ -1049,11 +1049,11 @@ bool define_gamedata_location(const String &exe_path) // derive missing ones from available. if (usetup.main_data_filename.IsEmpty()) { - usetup.main_data_filename = get_filename(usetup.main_data_filepath); + usetup.main_data_filename = Path::GetFilename(usetup.main_data_filepath); } else if (usetup.main_data_filepath.IsEmpty()) { - if (usetup.data_files_dir.IsEmpty() || !is_relative_filename(usetup.main_data_filename)) + if (usetup.data_files_dir.IsEmpty() || !Path::IsRelativePath(usetup.main_data_filename)) usetup.main_data_filepath = usetup.main_data_filename; else usetup.main_data_filepath = Path::ConcatPaths(usetup.data_files_dir, usetup.main_data_filename); diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index 42addf0ae7b..1b93e8cdbf8 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -17,8 +17,14 @@ #if AGS_PLATFORM_OS_WINDOWS #include #include -#include // find files -#include // prevents typename conflicts +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP +#include +#include +#include +#include + #include "ac/common.h" #include "ac/draw.h" #include "ac/gamesetup.h" @@ -55,15 +61,6 @@ extern int our_eip; extern IGraphicsDriver *gfxDriver; extern RGB palette[256]; -#include -#include -#include -#include -#include -#include - -#include - #ifndef CSIDL_LOCAL_APPDATA #define CSIDL_LOCAL_APPDATA 0x001C @@ -369,20 +366,6 @@ void AGSWin32::add_game_to_game_explorer(IGameExplorer* pFwGameExplorer, GUID *g SysFreeString(bstrGameDirectory); } -#define FA_SEARCH -1 -void delete_files_in_directory(const char *directoryName, const char *fileMask) -{ - char srchBuffer[MAX_PATH]; - sprintf(srchBuffer, "%s\\%s", directoryName, fileMask); - al_ffblk dfb; - int dun = al_findfirst(srchBuffer, &dfb, FA_SEARCH); - while (!dun) { - ::remove(dfb.name); - dun = al_findnext(&dfb); - } - al_findclose(&dfb); -} - void AGSWin32::remove_game_from_game_explorer(IGameExplorer* pFwGameExplorer, GUID *guid, const char *guidAsText, bool allUsers) { HRESULT hr = pFwGameExplorer->RemoveGame(*guid); From 00627fdd7dfb67f736041429fdc071bf611245b5 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Tue, 10 Nov 2020 14:23:13 +0300 Subject: [PATCH 27/41] APEG: use OpenAL sound and SDL timers instead of Allegro's Based on the work of @sonneveld (Nick Sonneveld) with minor modifications and fixes. --- Engine/libsrc/apeg-1.2.1/CMakeLists.txt | 4 +- Engine/libsrc/apeg-1.2.1/adisplay.c | 1 - Engine/libsrc/apeg-1.2.1/apeg.h | 28 +- Engine/libsrc/apeg-1.2.1/audio/aaudio.c | 152 +++---- Engine/libsrc/apeg-1.2.1/audio/mpg123.c | 412 +----------------- Engine/libsrc/apeg-1.2.1/getbits.c | 2 - Engine/libsrc/apeg-1.2.1/gethdr.c | 1 - Engine/libsrc/apeg-1.2.1/getpic.c | 1 - Engine/libsrc/apeg-1.2.1/mpeg1dec.c | 304 +------------ Engine/libsrc/apeg-1.2.1/mpeg1dec.h | 12 +- Engine/libsrc/apeg-1.2.1/mpg123.h | 258 ----------- Engine/libsrc/apeg-1.2.1/ogg.c | 32 +- Engine/libsrc/apeg-1.2.1/openal_support.h | 13 + Engine/libsrc/apeg-1.2.1/recon.c | 1 - Solutions/Engine.App/Engine.App.vcxproj | 9 + .../Engine.App/Engine.App.vcxproj.filters | 27 ++ 16 files changed, 191 insertions(+), 1066 deletions(-) create mode 100644 Engine/libsrc/apeg-1.2.1/openal_support.h diff --git a/Engine/libsrc/apeg-1.2.1/CMakeLists.txt b/Engine/libsrc/apeg-1.2.1/CMakeLists.txt index dcc26b09010..d56d81f0171 100644 --- a/Engine/libsrc/apeg-1.2.1/CMakeLists.txt +++ b/Engine/libsrc/apeg-1.2.1/CMakeLists.txt @@ -36,8 +36,8 @@ target_sources(apeg # audio/vbrhead.c ) -target_compile_definitions(apeg PUBLIC DISABLE_MPEG_AUDIO) +target_compile_definitions(apeg PRIVATE DISABLE_MPEG_AUDIO) -target_link_libraries(apeg PUBLIC Allegro::Allegro Ogg::Ogg Vorbis::Vorbis Vorbis::VorbisFile Theora::TheoraDecoder) +target_link_libraries(apeg PUBLIC Allegro::Allegro Ogg::Ogg Vorbis::Vorbis Vorbis::VorbisFile Theora::TheoraDecoder External::OpenAL) add_library(Apeg::Apeg ALIAS apeg) diff --git a/Engine/libsrc/apeg-1.2.1/adisplay.c b/Engine/libsrc/apeg-1.2.1/adisplay.c index 0d22819dd97..1f183220c6a 100644 --- a/Engine/libsrc/apeg-1.2.1/adisplay.c +++ b/Engine/libsrc/apeg-1.2.1/adisplay.c @@ -13,7 +13,6 @@ #include #include -#include #include "apeg.h" #include "mpeg1dec.h" diff --git a/Engine/libsrc/apeg-1.2.1/apeg.h b/Engine/libsrc/apeg-1.2.1/apeg.h index c0bb9cea3ed..99b7c86daa4 100644 --- a/Engine/libsrc/apeg-1.2.1/apeg.h +++ b/Engine/libsrc/apeg-1.2.1/apeg.h @@ -1,7 +1,7 @@ #ifndef APEG_H #define APEG_H -#include +#include // BITMAP, PALETTE #define APEG_MAKE_VERSION(a, b, c) (((a)<<16) | ((b)<<8) | (c)) @@ -14,8 +14,8 @@ #define APEG_VERSION_STR "1.2.1" - -#define FPS_TO_TIMER(x) ((long)((float)TIMERS_PER_SECOND / (float)(x))) +/* times per 1000 milliseconds */ +#define FPS_TO_TIMER(x) ((long)((float)1000 / (float)(x))) #define APEG_OK (0) #define APEG_ERROR (-1) @@ -62,6 +62,7 @@ typedef struct APEG_STREAM { int sequence; + int sdl_timer_id; volatile int timer; int flags; @@ -76,25 +77,14 @@ typedef struct APEG_STREAM { #define APEG_HAS_AUDIO (APEG_MPG_AUDIO|APEG_VORBIS_AUDIO) -APEG_STREAM *apeg_open_stream(const char *filename); -APEG_STREAM *apeg_open_memory_stream(void *buffer, int length); APEG_STREAM *apeg_open_stream_ex(void *ptr); -int apeg_advance_stream(APEG_STREAM *stream, int loop); int apeg_reset_stream(APEG_STREAM *stream); void apeg_close_stream(APEG_STREAM *stream); - -int apeg_play_mpg(const char *filename, BITMAP *target, int loop, - int (*callback)(void)); -int apeg_play_memory_mpg(void *buffer, BITMAP *target, int loop, - int (*callback)(BITMAP*)); -int apeg_play_mpg_ex(void *ptr, BITMAP *target, int loop, - int (*callback)(BITMAP*)); int apeg_play_apeg_stream(APEG_STREAM *stream_to_play, BITMAP *bmp, int loop, int (*callback)(BITMAP*tempBuffer)); int apeg_ignore_video(int ignore); int apeg_ignore_audio(int ignore); -void apeg_set_memory_stream_size(int size); void apeg_set_stream_reader(int (*init)(void *ptr), int (*read)(void *buffer, int bytes, void *ptr), void (*skip)(int bytes, void *ptr)); @@ -107,7 +97,6 @@ void apeg_set_display_callbacks(int (*init)(APEG_STREAM *stream, int coded_w, void *ptr), void *ptr); void apeg_set_display_depth(int depth); -void apeg_set_quality(int quality); void apeg_enable_framedrop(int framedrop); void apeg_disable_length_detection(int skipdetect); @@ -116,12 +105,8 @@ void apeg_reset_colors(APEG_STREAM *stream); void apeg_get_video_size(APEG_STREAM *stream, int *w, int *h); -void apeg_set_stream_rate(APEG_STREAM *stream, float rate); - -SAMPLE *apeg_preload_audio(const char *filename); -int apeg_get_stream_voice(APEG_STREAM *stream); void apeg_set_audio_callbacks(int (*init)(APEG_STREAM *stream, int *channels, int *frequency, void *ptr), @@ -130,11 +115,6 @@ void apeg_set_audio_callbacks(int (*init)(APEG_STREAM *stream, int *channels, void *ptr), void *ptr); -int apeg_downsample_audio(int mode); -void apeg_downchannel_audio(int mode); - -int apeg_set_audio_bufsize(int size); - extern APEG_STREAM *apeg_stream; extern PALETTE apeg_palette; diff --git a/Engine/libsrc/apeg-1.2.1/audio/aaudio.c b/Engine/libsrc/apeg-1.2.1/audio/aaudio.c index 84b5c5f7ac4..824757ef146 100644 --- a/Engine/libsrc/apeg-1.2.1/audio/aaudio.c +++ b/Engine/libsrc/apeg-1.2.1/audio/aaudio.c @@ -1,22 +1,29 @@ #include +#include #include "apeg.h" #include "mpg123.h" #include "mpeg1dec.h" +#include "openal_support.h" + + int _apeg_audio_get_position(APEG_LAYER *layer) { - int np; + ALenum err; + ALint np; -#ifndef DISABLE_MPEG_AUDIO - if(layer->audio.rd.eof) - return -1; -#endif - if(!layer->audio.stream) + if(layer->audio.alSource <= 0) return 0; - np = layer->audio.pos; + alGetSourcei(layer->audio.alSource, AL_SAMPLE_OFFSET, &np); + err = alGetError(); + if (err) { + printf("_apeg_audio_get_position: alGetSourcei AL_SAMPLE_OFFSET error: %d\n", err); + return 0; + } + if(np < 0) { layer->audio.last_pos = np; @@ -30,21 +37,32 @@ int _apeg_audio_get_position(APEG_LAYER *layer) return np; } -void _apeg_audio_set_speed_multiple(APEG_LAYER *layer, float multiple) +#define check_al_error(X) { ALenum err = alGetError(); if (err) { printf("apeg: %s: " X " error: %d\n", __func__, err); return APEG_ERROR; } } + +static int _apeg_audio_unqueue_buffers(APEG_LAYER *layer) { - if(layer->audio.stream) - { - int newfreq = (float)layer->stream.audio.freq * multiple; - int voice = layer->audio.voice; + ALint processed = 0; + alGetSourcei(layer->audio.alSource, AL_BUFFERS_PROCESSED, &processed); + check_al_error("alGetSourcei AL_BUFFERS_PROCESSED") - if(newfreq > 0) - { - voice_set_frequency(voice, newfreq); - voice_start(voice); - } - else - voice_stop(voice); + while (processed > 0) { + ALuint bufid = 0; + alSourceUnqueueBuffers(layer->audio.alSource, 1, &bufid); + check_al_error("alSourceUnqueueBuffers") + + ALint processedBytes = 0; + alGetBufferi(bufid, AL_SIZE, &processedBytes); + check_al_error("alGetBufferi AL_SIZE") + + layer->audio.processedSamples += processedBytes / layer->stream.audio.channels / 2; + + alDeleteBuffers(1, &bufid); + check_al_error("alDeleteBuffers") + + processed--; } + + return APEG_OK; } @@ -55,79 +73,53 @@ int _apeg_audio_flush(APEG_LAYER *layer) int hs; int ret = APEG_OK; + /* clear */ alGetError(); + if(layer->audio.pcm.point < layer->audio.bufsize) { int count = layer->audio.pcm.point / 2; int samplesend = layer->audio.bufsize / 2; while(count < samplesend) - ((short*)buf)[count++] = 0x8000; + ((short*)buf)[count++] = 0; if(layer->audio.pcm.point == 0) ret = APEG_EOF; } - if(layer->audio.callback) - { - if(ret != APEG_OK) - return ret; - - ret = layer->audio.callback((APEG_STREAM*)layer, buf, - layer->audio.pcm.point, - layer->audio.callback_arg); - if(ret < 0) - return APEG_ERROR; - - if(ret > 0) - { - layer->audio.pos += ret / 2 / layer->stream.audio.channels; - layer->audio.pcm.point -= ret; - if(layer->audio.pcm.point > 0) - memmove(buf, buf+ret, layer->audio.pcm.point); - layer->stream.audio.flushed = TRUE; - - if(!(layer->stream.flags&APEG_HAS_VIDEO)) - layer->stream.pos = (double)layer->audio.pos / - (double)layer->stream.audio.freq; - } + if (_apeg_audio_unqueue_buffers(layer) == APEG_ERROR) { return APEG_ERROR; } - return APEG_OK; - } + ALint queued = 0; + alGetSourcei(layer->audio.alSource, AL_BUFFERS_QUEUED, &queued); + check_al_error("alGetSourcei AL_BUFFERS_QUEUED") - /* We need to test the stream buffer to see if it's ready for more audio - * yet. - */ - hs = layer->audio.stream->len/2; - if((layer->audio.buf_segment && - voice_get_position(layer->audio.voice) >= hs) || - (!layer->audio.buf_segment && - voice_get_position(layer->audio.voice) < hs)) + if (queued >= 4) { return ret; + } - voice_stop(layer->audio.voice); - data = layer->audio.stream->data; - data += layer->audio.buf_segment * hs * layer->stream.audio.channels * 2; + layer->audio.pos = -1; - /* Commit the buffer to the stream and update the time */ - memcpy(data, buf, layer->audio.bufsize); + if (layer->audio.pcm.point > 0) { + ALuint alBuffer; + alGenBuffers((ALuint)1, &alBuffer); + check_al_error("alGenBuffers") - voice_start(layer->audio.voice); - layer->audio.buf_segment ^= 1; + alBufferData(alBuffer, layer->stream.audio.channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, buf, layer->audio.pcm.point, layer->stream.audio.freq); + check_al_error("alBufferData") - layer->audio.pos += ((layer->audio.pcm.point >= layer->audio.bufsize) ? - layer->audio.samples_per_update : - (layer->audio.pcm.point/2/layer->stream.audio.channels)); - if(!(layer->stream.flags&APEG_HAS_VIDEO)) - layer->stream.pos = (double)layer->audio.pos / - (double)layer->stream.audio.freq; + alSourceQueueBuffers(layer->audio.alSource, 1, &alBuffer); + check_al_error("alSourceQueueBuffers") - /* Remove the old data and put the unused samples at the beginning */ - layer->audio.pcm.point -= layer->audio.bufsize; - if(layer->audio.pcm.point > 0) - memmove(buf, buf+layer->audio.bufsize, layer->audio.pcm.point); - else if(layer->audio.pcm.point < 0) - layer->audio.pcm.point = 0; + ALint state; + alGetSourcei(layer->audio.alSource,AL_SOURCE_STATE,&state); + check_al_error("alGetSourcei AL_SOURCE_STATE") + if (state != AL_PLAYING) { + alSourcePlay(layer->audio.alSource); + check_al_error("alSourcePlay") + } + } + layer->audio.pcm.point = 0; layer->stream.audio.flushed = TRUE; return ret; @@ -135,9 +127,19 @@ int _apeg_audio_flush(APEG_LAYER *layer) int _apeg_audio_close(APEG_LAYER *layer) { - if(layer->audio.stream) - destroy_sample(layer->audio.stream); - layer->audio.stream = NULL; + if (layer->audio.alSource > 0) { + alSourceStop(layer->audio.alSource); + check_al_error("alSourceStop") + + alSourcei(layer->audio.alSource, AL_BUFFER, 0); + check_al_error("alSourcei AL_BUFFER NULL") + + if (_apeg_audio_unqueue_buffers(layer) == APEG_ERROR) { return APEG_ERROR; } + + alDeleteSources(1, &layer->audio.alSource); + check_al_error("alDeleteSources") + } + layer->audio.alSource = 0; layer->audio.voice = -1; return 0; diff --git a/Engine/libsrc/apeg-1.2.1/audio/mpg123.c b/Engine/libsrc/apeg-1.2.1/audio/mpg123.c index 2643056c52c..947ab1733d6 100644 --- a/Engine/libsrc/apeg-1.2.1/audio/mpg123.c +++ b/Engine/libsrc/apeg-1.2.1/audio/mpg123.c @@ -12,6 +12,8 @@ #include #include +#include "openal_support.h" + #include "apeg.h" #include "mpg123.h" #include "mpeg1dec.h" @@ -27,7 +29,7 @@ int apeg_ignore_audio(int ignore) float equalizer[2][32]; -static int bufsize = 8192; +static int bufsize = 44100 * 2 * 2 * 200 / 1000; // 200ms seconds of buffer. static int down_sample = 0; static int down_channel = FALSE; @@ -44,32 +46,7 @@ void apeg_set_audio_callbacks(int (*callback_init)(APEG_STREAM*,int*,int*,void*) _audio_callback_arg = arg; } -int apeg_downsample_audio(int ds) -{ - if(ds >= 0) - { - if(ds > 2) - ds = 2; - down_sample = ds; - } - - return down_sample; -} - -void apeg_downchannel_audio(int dc) -{ - down_channel = !!dc; -} - - -int apeg_set_audio_bufsize(int size) -{ - if(size > 0) - bufsize = (size+255)&(~255); - - return bufsize; -} - +#define check_al_error(X) { ALenum err = alGetError(); if (err) { printf("apeg: %s: " X " error: %d\n", __func__, err); return APEG_ERROR; } } int _apeg_audio_reset_parameters(APEG_LAYER *layer) { @@ -91,66 +68,8 @@ int _apeg_audio_reset_parameters(APEG_LAYER *layer) } buffer_padding = 0; -#ifndef DISABLE_MPEG_AUDIO - if(layer->stream.audio.layer == 3) - buffer_padding = (128>>layer->stream.audio.down_sample) * SSLIMIT * - layer->stream.audio.channels; - if(layer->stream.audio.layer == 2) - buffer_padding = (128>>layer->stream.audio.down_sample) * 3 * - layer->stream.audio.channels; - if(layer->stream.audio.layer == 1) - buffer_padding = (128>>layer->stream.audio.down_sample) * SCALE_BLOCK * - layer->stream.audio.channels; -#endif - if(layer->audio.callback_init) - { - int channels = layer->stream.audio.channels; - int freq = layer->stream.audio.freq; - int ret; - - ret = layer->audio.callback_init((APEG_STREAM*)layer, &channels, &freq, - layer->audio.callback_arg); - if(ret < 0) - { - snprintf(apeg_error, sizeof(apeg_error), "Audio callback init failed (code: %d)", ret); - return APEG_ERROR; - } - - if(channels > layer->stream.audio.channels || channels <= 0 || - freq <= 0) - { - snprintf(apeg_error, sizeof(apeg_error), "Illegal audio mode requested (%dhz %d channels)", - freq, channels); - return APEG_ERROR; - } - - if(ret > 0) - layer->audio.bufsize = (ret+255)&(~255); - - free(layer->audio.pcm.samples); - layer->audio.pcm.samples = malloc(layer->audio.bufsize+buffer_padding); - if(!layer->audio.pcm.samples) - { - snprintf(apeg_error, sizeof(apeg_error), "Error allocating %d bytes for audio buffer", - layer->audio.bufsize+buffer_padding); - return APEG_ERROR; - } - - if(channels == 1 && layer->stream.audio.channels > 1) - layer->stream.audio.down_channel = TRUE; - - layer->stream.audio.channels = channels; - layer->stream.audio.freq = freq; - - layer->audio.samples_per_update = layer->audio.bufsize / 2 / - layer->stream.audio.channels; - - layer->audio.last_pos = -1; - layer->audio.pos = -layer->audio.samples_per_update*2; - return APEG_OK; - } free(layer->audio.pcm.samples); layer->audio.pcm.samples = malloc(layer->audio.bufsize+buffer_padding); @@ -167,65 +86,26 @@ int _apeg_audio_reset_parameters(APEG_LAYER *layer) layer->audio.samples_per_update = layer->audio.bufsize / 2 / layer->stream.audio.channels; + layer->audio.processedSamples = 0; + + /* clear */ alGetError(); + /* Start the audio stream */ - layer->audio.stream = create_sample(16, layer->stream.audio.channels != 1, - layer->stream.audio.freq, - layer->audio.samples_per_update*2); - if(layer->audio.stream) - { - int i; - for(i = 0;i < layer->audio.bufsize;++i) - ((short*)layer->audio.stream->data)[i] = 0x8000; - } - else - { - snprintf(apeg_error, sizeof(apeg_error), "Error starting stream playback"); - return APEG_ERROR; - } + alGenSources((ALuint)1, &layer->audio.alSource); + check_al_error("alGenSources") + + alSourceRewind(layer->audio.alSource); + check_al_error("alSourceRewind") - layer->audio.voice = play_sample(layer->audio.stream, 255, 127, 1000, TRUE); - voice_set_priority(layer->audio.voice, 255); + alSourcei(layer->audio.alSource, AL_BUFFER, 0); + check_al_error("alSourcei AL_BUFFER") layer->audio.last_pos = -1; layer->audio.pos = -layer->audio.samples_per_update*2; - _apeg_audio_set_speed_multiple(layer, layer->multiple); - return APEG_OK; } -#ifndef DISABLE_MPEG_AUDIO -/* - * play a frame read by read_frame(); - * (re)initialize audio if necessary. - */ -static void decode_frame(APEG_LAYER *layer, struct frame *fr, struct mpstr *mp) -{ - int clip; - - /* do the decoding */ - switch(fr->lay) - { - case 1: - clip = do_layer1(mp, fr, layer); - break; - case 2: - clip = do_layer2(mp, fr, layer); - break; - case 3: - clip = do_layer3(mp, fr, layer); - break; - default: - // Shouldn't get here... - clip = 1; - mp->return_later = FALSE; - } - - if(clip < 0) - apeg_error_jump("Error decoding audio frame"); -} -#endif - /* * The poll function. Checks if more data is needed, and decodes/plays if @@ -233,89 +113,12 @@ static void decode_frame(APEG_LAYER *layer, struct frame *fr, struct mpstr *mp) */ int _apeg_audio_poll(APEG_LAYER *layer) { -#ifndef DISABLE_MPEG_AUDIO - struct reader *rd = &(layer->audio.rd); - struct frame *fr = &(layer->audio.fr); - struct mpstr *mp = &(layer->audio.mp); - int ret = APEG_OK; -#endif - if(layer->multiple <= 0.0f) - return APEG_OK; if(layer->stream.flags & APEG_VORBIS_AUDIO) return alvorbis_update(layer); -#ifdef DISABLE_MPEG_AUDIO return APEG_ERROR; -#else - // Check if we actually need more data yet - while(!rd->eof && layer->audio.pcm.point < layer->audio.bufsize) - { - // Make sure we're not still in the process of decoding the previous - // frame - if(mp->return_later) - { - decode_frame(layer, fr, mp); - continue; - } - - ret = read_frame(layer, fr); - if(ret != ALMPA_OK) - { - // Stream ended, but check if there's still audio in the buffer - if(!layer->audio.pcm.point) - return ret; - - ret = APEG_OK; - break; - } - - /* TODO: for fast forwarding */ -/* if(stream->frame > layer->audio.frame) - { - if(fr->lay == 3) - set_pointer(mp, fr->sideInfoSize, 512); - goto do_again; - }*/ - - // Check for header change. This works, but it will introduce a jump - // if the frequency/channel count changes. - if(!layer->audio.inited) - { - int old_rate = layer->stream.audio.freq; - int old_channels = layer->stream.audio.channels; - - int newrate = freqs[fr->sampling_frequency] >> - layer->stream.audio.down_sample; - - layer->stream.audio.channels = (layer->stream.audio.down_channel?1: - fr->stereo); - layer->stream.audio.freq = newrate; - - layer->stream.audio.layer = fr->lay; - layer->stream.audio.kbps = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]; - fr->down_sample_sblimit = SBLIMIT>>layer->stream.audio.down_sample; - - if(layer->stream.audio.freq != old_rate || - layer->stream.audio.channels != old_channels) - { - if(fr->lay == 3) - init_layer3(layer->stream.audio.down_sample); - - if(_apeg_audio_reset_parameters(layer) != APEG_OK) - return APEG_ERROR; - } - - layer->audio.inited = TRUE; - } - - ++(layer->audio.frame); - decode_frame(layer, fr, mp); - } - - return _apeg_audio_flush(layer); -#endif } /* @@ -334,13 +137,6 @@ int _apeg_start_audio(APEG_LAYER *layer, int enable) _apeg_audio_close(layer); layer->stream.flags &= ~APEG_HAS_AUDIO; -#ifndef DISABLE_MPEG_AUDIO - memset(&(layer->audio.rd), 0, sizeof(layer->audio.rd)); - memset(&(layer->audio.fr), 0, sizeof(layer->audio.fr)); - memset(&(layer->audio.mp), 0, sizeof(layer->audio.mp)); - layer->audio.frame = 0; -#endif - layer->audio.inited = FALSE; } @@ -352,186 +148,14 @@ int _apeg_start_audio(APEG_LAYER *layer, int enable) layer->audio.voice = -1; layer->audio.buf_segment = 0; layer->audio.bufsize = bufsize; - layer->audio.callback_init = _audio_callback_init; - layer->audio.callback = _audio_callback; - layer->audio.callback_arg = _audio_callback_arg; + layer->audio.callback_init = 0; + layer->audio.callback = 0; + layer->audio.callback_arg = 0; if(!enable || _apeg_ignore_audio) return APEG_OK; -#ifdef DISABLE_MPEG_AUDIO return APEG_ERROR; -#else - layer->audio.mp.bo = 1; - - if(layer->system_stream_flag == OGG_SYSTEM) - return APEG_ERROR; - - if(layer->system_stream_flag == NO_SYSTEM && - (layer->stream.flags & APEG_MPG_VIDEO)) - return APEG_ERROR; - - if(sizeof(short) != 2) { - sprintf(apeg_error, "Ouch SHORT has size of %ud bytes (required: '2')", sizeof(short)); - return APEG_ERROR; - } - if(sizeof(long) < 4) { - sprintf(apeg_error, "Ouch LONG has size of %ud bytes (required: at least 4)", sizeof(long)); - return APEG_ERROR; - } - if(sizeof(int) != 4) { - sprintf(apeg_error, "Ouch INT has size of %ud bytes (required: '4')", sizeof(int)); - return APEG_ERROR; - } - - /* Open the stream */ - if(open_stream(layer) != ALMPA_OK) - { - memset(&(layer->audio.rd), 0, sizeof(layer->audio.rd)); - sprintf(apeg_error, "Error opening audio stream"); - return APEG_ERROR; - } - - layer->audio.mp.bsbuf = layer->audio.mp.bsspace[1]; - - make_decode_tables(); - init_layer2(); /* inits also shared tables with layer1 */ - init_layer3(down_sample); - - if(read_frame(layer, &(layer->audio.fr)) != APEG_OK) - { - _apeg_start_audio(layer, FALSE); - sprintf(apeg_error, "Error reading first audio frame"); - return APEG_ERROR; - } - - if(layer->audio.fr.stereo == 1) - layer->stream.audio.down_channel = FALSE; - layer->stream.audio.channels = (down_channel ? 1 : layer->audio.fr.stereo); - layer->stream.audio.freq = freqs[layer->audio.fr.sampling_frequency] >> - down_sample; - - layer->stream.audio.layer = layer->audio.fr.lay; - layer->stream.audio.kbps = tabsel_123[layer->audio.fr.lsf][layer->audio.fr.lay-1][layer->audio.fr.bitrate_index]; - layer->audio.fr.down_sample_sblimit = SBLIMIT >> down_sample; - - if(_apeg_audio_reset_parameters(layer) != APEG_OK) - { - _apeg_start_audio(layer, FALSE); - return APEG_ERROR; - } - - if(layer->audio.fr.lay == 3) - init_layer3(down_sample); - - layer->audio.inited = TRUE; - - ++(layer->audio.frame); - decode_frame(layer, &layer->audio.fr, &layer->audio.mp); - - layer->stream.flags |= APEG_MPG_AUDIO; - - return APEG_OK; -#endif } -int apeg_get_stream_voice(APEG_STREAM *stream) -{ - ASSERT(stream); - ASSERT(stream->flags & APEG_HAS_AUDIO); - return ((APEG_LAYER*)stream)->audio.voice; -} -struct smpl_bldr { - SAMPLE *smp; - unsigned int pos; -}; - -static int sample_capture_init(APEG_STREAM *stream, int *channels, int *freq, void *arg) -{ - struct smpl_bldr *sb = (struct smpl_bldr*)arg; - - if(sb->smp) - return -1; - - if(*channels > 2) - *channels = 2; - - sb->smp = create_sample(16, (*channels == 2), *freq, (*channels)*(*freq)); - if(!sb->smp) - return -1; - - sb->pos = 0; - return 0; - (void)stream; -} - -static int sample_capture(APEG_STREAM *stream, void *buf, int len, void *arg) -{ - struct smpl_bldr *sb = (struct smpl_bldr*)arg; - if(sb->pos+len > sb->smp->len*2) - { - unsigned int nlen = sb->smp->len*2 * 2; - void *tmp = realloc(sb->smp->data, nlen); - if(!tmp) - return -1; - sb->smp->data = tmp; - sb->smp->len = nlen/2; - } - - memcpy((char*)sb->smp->data+sb->pos, buf, len); - sb->pos += len; - return len; - (void)stream; -} - -SAMPLE *apeg_preload_audio(const char *filename) -{ - void *holder[3] = { _audio_callback_init, _audio_callback, - _audio_callback_arg }; - int ds = down_sample; - int dc = down_channel; - APEG_STREAM *stream = NULL; - struct smpl_bldr sb = { NULL, 0 }; - int old_ignore_audio = apeg_ignore_audio(FALSE); - int old_ignore_video = apeg_ignore_video(TRUE); - - down_sample = 0; - down_channel = 0; - apeg_set_audio_callbacks(sample_capture_init, sample_capture, &sb); - - stream = apeg_open_stream(filename); - - if(!stream || !(stream->flags & APEG_HAS_AUDIO)) - { - snprintf(apeg_error, sizeof(apeg_error), "Could not open file"); - goto done; - } - - while(apeg_advance_stream(stream, FALSE) == APEG_OK) - ; - - apeg_close_stream(stream); - - sb.smp->len = sb.pos/2; - sb.smp->loop_end = sb.smp->len; - sb.smp->data = realloc(sb.smp->data, sb.smp->len*2); - -done: - apeg_close_stream(stream); - - apeg_set_audio_callbacks(holder[0], holder[1], holder[2]); - down_channel = dc; - down_sample = ds; - - apeg_ignore_audio(old_ignore_audio); - apeg_ignore_video(old_ignore_video); - -#ifndef DISABLE_MPEG_AUDIO - // Eww.. rebuild the tables if we used a different downsampling mode. - if(down_sample) - init_layer3(down_sample); -#endif - - return sb.smp; -} diff --git a/Engine/libsrc/apeg-1.2.1/getbits.c b/Engine/libsrc/apeg-1.2.1/getbits.c index 6bed5948409..01f471d2f0c 100644 --- a/Engine/libsrc/apeg-1.2.1/getbits.c +++ b/Engine/libsrc/apeg-1.2.1/getbits.c @@ -9,8 +9,6 @@ #include #include -#include - #include "mpeg1dec.h" diff --git a/Engine/libsrc/apeg-1.2.1/gethdr.c b/Engine/libsrc/apeg-1.2.1/gethdr.c index a65de96f992..af912151da1 100644 --- a/Engine/libsrc/apeg-1.2.1/gethdr.c +++ b/Engine/libsrc/apeg-1.2.1/gethdr.c @@ -3,7 +3,6 @@ #include #include -#include #include "apeg.h" #include "mpeg1dec.h" diff --git a/Engine/libsrc/apeg-1.2.1/getpic.c b/Engine/libsrc/apeg-1.2.1/getpic.c index 404fbf5ed8d..7ed56859b61 100644 --- a/Engine/libsrc/apeg-1.2.1/getpic.c +++ b/Engine/libsrc/apeg-1.2.1/getpic.c @@ -3,7 +3,6 @@ #include #include -#include #include "apeg.h" #include "mpeg1dec.h" diff --git a/Engine/libsrc/apeg-1.2.1/mpeg1dec.c b/Engine/libsrc/apeg-1.2.1/mpeg1dec.c index 3ee8c5961e7..2094d2864f9 100644 --- a/Engine/libsrc/apeg-1.2.1/mpeg1dec.c +++ b/Engine/libsrc/apeg-1.2.1/mpeg1dec.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include "apeg.h" #include "mpeg1dec.h" @@ -190,9 +190,10 @@ static PACKFILE_VTABLE ext_vtable = // The timer.. increments the int pointed to by 'param' -static void timer_proc(void *param) +static Uint32 timer_proc(Uint32 interval, void *param) { ++(*(volatile int*)param); + return interval; } END_OF_STATIC_FUNCTION(timer_proc); @@ -216,9 +217,6 @@ static void Initialize_Decoder(void) // The default callback; requires Allegro's keyboard handler static int default_callback(BITMAP *tempBuffer) { - if(keypressed()) - return 1; - return 0; } static int (*callback_proc)(BITMAP* tempBuffer); @@ -248,7 +246,11 @@ void apeg_close_stream(APEG_STREAM *stream) { _apeg_start_audio(layer, FALSE); - remove_param_int(timer_proc, (void*)&(layer->stream.timer)); + if (layer->stream.sdl_timer_id > 0) + { + SDL_RemoveTimer(layer->stream.sdl_timer_id); + layer->stream.sdl_timer_id = 0; + } destroy_bitmap(layer->stream.bitmap); @@ -265,70 +267,6 @@ void apeg_close_stream(APEG_STREAM *stream) } -// Open an MPEG or Ogg file. Returns a structure for stream manipulation. -APEG_STREAM *apeg_open_stream(const char *filename) -{ - APEG_LAYER *layer; - - // Initialize the decoder - Initialize_Decoder(); - - // Create a new stream structure - layer = new_apeg_stream(); - if(!layer) - return NULL; - - // Set the jump position in case the decoder faults on opening. - if(setjmp(jmp_buffer)) - { - apeg_close_stream((APEG_STREAM*)layer); - return NULL; - } - - // Copy the filename so we can (re)open the file when the buffer - // gets initialized - layer->fname = strdup(filename); - if(!layer->fname) - apeg_error_jump("Couldn't duplicate filename"); - - // Set the buffer type and size - layer->buffer_type = DISK_BUFFER; - layer->buffer_size = F_BUF_SIZE; - - setup_stream(layer); - - return (APEG_STREAM*)layer; -} - -APEG_STREAM *apeg_open_memory_stream(void *mpeg_data, int data_len) -{ - APEG_LAYER *layer; - - Initialize_Decoder(); - - layer = new_apeg_stream(); - if(!layer) - return NULL; - - if(setjmp(jmp_buffer)) - { - apeg_close_stream((APEG_STREAM*)layer); - return NULL; - } - - layer->mem_data.buf = mpeg_data; - layer->mem_data.bytes_left = data_len; - layer->pf = pack_fopen_vtable(&mem_vtable, layer); - if(!layer->pf) - apeg_error_jump("Could not open stream"); - - layer->buffer_type = MEMORY_BUFFER; - layer->buffer_size = data_len; - - setup_stream(layer); - - return (APEG_STREAM*)layer; -} APEG_STREAM *apeg_open_stream_ex(void *ptr) { @@ -362,85 +300,6 @@ APEG_STREAM *apeg_open_stream_ex(void *ptr) } -int apeg_advance_stream(APEG_STREAM *stream, int loop) -{ - APEG_LAYER *layer = (APEG_LAYER*)stream; - int ret; - - // Set the jump buffer - if((ret = setjmp(jmp_buffer)) != 0) - return ret; - - layer->stream.frame_updated = -1; - layer->stream.audio.flushed = FALSE; - ret = APEG_OK; - - if((layer->stream.flags&APEG_HAS_AUDIO) && layer->multiple > 0.0) - { - ret = _apeg_audio_poll(layer); - if((layer->stream.flags&APEG_HAS_VIDEO)) - { - int t = _apeg_audio_get_position(layer); - if(t >= 0) - layer->stream.timer = (double)t*stream->frame_rate/ - (double)stream->audio.freq - - stream->frame; - } - } - - if((layer->stream.flags&APEG_HAS_VIDEO)) - { - if(!layer->picture) - { - if((layer->stream.flags&APEG_MPG_VIDEO)) - { - // Get the next MPEG header - if(apeg_get_header(layer) == 1) - { - // Decode the next picture - if(layer->picture_type != B_TYPE || - !framedrop || layer->stream.timer <= 1) - layer->picture = apeg_get_frame(layer); - } - // If end of stream, display the last frame - else if((!framedrop || layer->stream.timer <= 1) && - !layer->got_last) - { - layer->got_last = TRUE; - layer->picture = layer->backward_frame; - } - } - else - layer->picture = altheora_get_frame(layer); - - if(pack_feof(layer->pf) && (!(layer->stream.flags&APEG_HAS_AUDIO)|| - layer->multiple==0.0 || - ret!=APEG_OK)) - ret = APEG_EOF; - } - - if(layer->stream.timer > 0) - { - // Update frame and timer count - ++(layer->stream.frame); - --(layer->stream.timer); - - // If we're not behind, update the display frame - layer->stream.frame_updated = 0; - if(layer->picture && (!framedrop || layer->stream.timer == 0)) - apeg_display_frame(layer, layer->picture); - layer->picture = NULL; - } - if(layer->stream.frame_updated == 1 || layer->picture) - ret = APEG_OK; - } - - if(ret == APEG_EOF && loop) - ret = apeg_reset_stream((APEG_STREAM*)layer); - - return ret; -} - int apeg_reset_stream(APEG_STREAM *stream) { APEG_LAYER *layer = (APEG_LAYER*)stream; @@ -508,84 +367,8 @@ int apeg_play_apeg_stream(APEG_STREAM *stream_to_play, BITMAP *bmp, int loop, in return ret; } -int apeg_play_memory_mpg(void *mpeg_data, BITMAP *bmp, int loop, int (*callback)(BITMAP *tempBuffer)) -{ - int ret; - - Initialize_Decoder(); - - apeg_stream = apeg_open_memory_stream(mpeg_data, mem_buffer_size); - if(!apeg_stream) - return APEG_ERROR; - - if(bmp) - clear_to_color(bmp, makecol(0, 0, 0)); - - if(callback) - callback_proc = callback; - else - callback_proc = default_callback; - -restart_loop: - ret = decode_stream((APEG_LAYER*)apeg_stream, bmp); - if(loop && ret == APEG_OK) - { - apeg_reset_stream(apeg_stream); - goto restart_loop; - } - - apeg_close_stream(apeg_stream); - apeg_stream = NULL; - - return ret; -} - - -int apeg_play_mpg_ex(void *ptr, BITMAP *bmp, int loop, int (*callback)(BITMAP*)) -{ - int ret; - - Initialize_Decoder(); - - apeg_stream = apeg_open_stream_ex(ptr); - if(!apeg_stream) - return APEG_ERROR; - - if(bmp) - clear_to_color(bmp, makecol(0, 0, 0)); - - if(callback) - callback_proc = callback; - else - callback_proc = default_callback; -restart_loop: - ret = decode_stream((APEG_LAYER*)apeg_stream, bmp); - if(loop && ret == APEG_OK) - { - apeg_reset_stream(apeg_stream); - goto restart_loop; - } - - apeg_close_stream(apeg_stream); - apeg_stream = NULL; - return ret; -} - - -void apeg_set_disk_buffer_size(int size) -{ - (void)size; -} - -void apeg_set_memory_stream_size(int size) -{ - if(size < 4) - size = -1; - - mem_buffer_size = size; -} void apeg_set_stream_reader(int (*init_func)(void *ptr), int (*request_func)(void *bfr, int bytes, void *ptr), void (*skip_func)(int bytes, void *ptr)) { @@ -603,15 +386,7 @@ int apeg_ignore_video(int ignore) return last; } -void apeg_set_quality(int quality) -{ - if(quality == 0) - quality = 0; - else if(quality == 1) - quality = RECON_SUBPIXEL; - else - quality = RECON_SUBPIXEL | RECON_AVG_SUBPIXEL; -} + void apeg_get_video_size(APEG_STREAM *stream, int *w, int *h) { @@ -637,28 +412,6 @@ void apeg_get_video_size(APEG_STREAM *stream, int *w, int *h) } } -void apeg_set_stream_rate(APEG_STREAM *stream, float multiple) -{ - if(multiple < 0.0f) - return; - - if((stream->flags&APEG_HAS_AUDIO)) - _apeg_audio_set_speed_multiple((APEG_LAYER*)stream, multiple); - - if((stream->flags&APEG_HAS_VIDEO)) - { - // Make sure the multiple is large enough - float fps = stream->frame_rate * multiple; - if(fps > 0.0f) - install_param_int_ex(timer_proc, (void*)&(stream->timer), - FPS_TO_TIMER(fps)); - else - remove_param_int(timer_proc, (void*)&(stream->timer)); - } - - ((APEG_LAYER*)stream)->multiple = multiple; -} - void apeg_enable_framedrop(int enable) { @@ -696,16 +449,18 @@ static int decode_stream(APEG_LAYER *layer, BITMAP *target) layer->stream.audio.flushed = FALSE; ret = APEG_OK; - if((layer->stream.flags & APEG_HAS_AUDIO) && layer->multiple > 0.0) + if((layer->stream.flags & APEG_HAS_AUDIO)) { ret = _apeg_audio_poll(layer); if((layer->stream.flags & APEG_HAS_VIDEO)) { int t = _apeg_audio_get_position(layer); - if(t >= 0) - layer->stream.timer = (double)t*layer->stream.frame_rate/ - (double)layer->stream.audio.freq - - layer->stream.frame; + if(t >= 0) { + double audio_pos_secs = (double)t / (double)layer->stream.audio.freq; + double audio_frames = audio_pos_secs * layer->stream.frame_rate; + layer->stream.timer = audio_frames - layer->stream.frame; + // could be negative.. so will wait until 0 ? + } } } @@ -736,7 +491,7 @@ static int decode_stream(APEG_LAYER *layer, BITMAP *target) if(pack_feof(layer->pf) && (!(layer->stream.flags&APEG_HAS_AUDIO)|| - layer->multiple==0.0 || ret!=APEG_OK)) + ret!=APEG_OK)) ret = APEG_EOF; } @@ -765,7 +520,7 @@ static int decode_stream(APEG_LAYER *layer, BITMAP *target) break; if(layer->stream.frame_updated < 0 && !layer->stream.audio.flushed) - rest(1); + SDL_Delay(1); } } while(ret == APEG_OK); @@ -807,8 +562,9 @@ static void setup_stream(APEG_LAYER *layer) if(layer->stream.frame_rate <= 0.0) apeg_error_jump("Illegal frame rate in stream"); - install_param_int_ex(timer_proc, (void*)&(layer->stream.timer), - FPS_TO_TIMER(layer->stream.frame_rate)); + Uint32 interval_ms = FPS_TO_TIMER(layer->stream.frame_rate); + layer->stream.sdl_timer_id = + SDL_AddTimer(interval_ms, timer_proc, (void*)&(layer->stream.timer)); // Reset the timer and return the stream layer->stream.timer = -1; @@ -920,10 +676,6 @@ static void check_stream_type(APEG_LAYER *layer) apeg_error_jump("Error opening Ogg stream"); return; } -#ifndef DISABLE_MPEG_AUDIO - if(almpa_head_backcheck(show_bits32(layer))) - break; -#endif } /* no positive stream identified; recheck */ @@ -943,25 +695,11 @@ void _apeg_initialize_buffer(APEG_LAYER *layer) switch(layer->buffer_type) { - case DISK_BUFFER: - // (Re)open the file - if(layer->pf) - pack_fclose(layer->pf); - - layer->pf = pack_fopen(layer->fname, F_READ); - if(!layer->pf) - { - sprintf(apeg_error, "Couldn't open %s", layer->fname); - apeg_error_jump(NULL); - } - break; - case MEMORY_BUFFER: layer->mem_data.buf -= layer->buffer_size - layer->mem_data.bytes_left; layer->mem_data.bytes_left = layer->buffer_size; break; - case USER_BUFFER: if(!layer->ext_data.request || !layer->ext_data.skip || !layer->ext_data.init) diff --git a/Engine/libsrc/apeg-1.2.1/mpeg1dec.h b/Engine/libsrc/apeg-1.2.1/mpeg1dec.h index 91abac49068..58e4e66fc8c 100644 --- a/Engine/libsrc/apeg-1.2.1/mpeg1dec.h +++ b/Engine/libsrc/apeg-1.2.1/mpeg1dec.h @@ -204,20 +204,16 @@ typedef struct APEG_LAYER { float multiple; struct { -#ifndef DISABLE_MPEG_AUDIO - struct reader rd; - struct frame fr; - struct mpstr mp; - int frame; -#endif - int (*callback_init)(APEG_STREAM*, int*, int*, void*); int (*callback)(APEG_STREAM*, void*, int, void*); void *callback_arg; int buf_segment; int voice; - SAMPLE *stream; + + unsigned int alSource; + int processedSamples; + int bufsize; int samples_per_update; diff --git a/Engine/libsrc/apeg-1.2.1/mpg123.h b/Engine/libsrc/apeg-1.2.1/mpg123.h index 33a950067ab..0bd390a3aac 100644 --- a/Engine/libsrc/apeg-1.2.1/mpg123.h +++ b/Engine/libsrc/apeg-1.2.1/mpg123.h @@ -24,264 +24,6 @@ int _apeg_audio_flush(struct APEG_LAYER*); int _apeg_audio_reset_parameters(struct APEG_LAYER*); int _apeg_start_audio(struct APEG_LAYER*, int); -#ifndef DISABLE_MPEG_AUDIO - -#include -#include -#include - -#include - -#define ALMPA_OK 0 -#define ALMPA_ERROR (-1) -#define ALMPA_EOF (-2) - - -#ifndef M_PI -#define M_PI 3.14159265358979 -#endif - -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237 -#endif - - -#define SBLIMIT 32 -#define SCALE_BLOCK 12 -#define SSLIMIT 18 - -#define MPG_MD_STEREO 0 -#define MPG_MD_JOINT_STEREO 1 -#define MPG_MD_DUAL_CHANNEL 2 -#define MPG_MD_MONO 3 - -#define MAXFRAMESIZE 4096 - - -int almpa_head_backcheck(unsigned long); - -struct gr_info_s { - int scfsi; - unsigned int part2_3_length; - unsigned int big_values; - unsigned int scalefac_compress; - unsigned int block_type; - unsigned int mixed_block_flag; - unsigned int table_select[3]; - unsigned int subblock_gain[3]; - unsigned int maxband[3]; - unsigned int maxbandl; - unsigned int maxb; - unsigned int region1start; - unsigned int region2start; - unsigned int preflag; - unsigned int scalefac_scale; - unsigned int count1table_select; - float *full_gain[3]; - float *pow2gain; -}; - -struct III_sideinfo -{ - unsigned int main_data_begin; - unsigned int private_bits; - struct { - struct gr_info_s gr[2]; - } ch[2]; -}; - -struct al_table -{ - short bits; - short d; -}; - -extern int tabsel_123[2][3][16]; - -#define VBR_FRAMES_FLAG 0x0001 -#define VBR_BYTES_FLAG 0x0002 -#define VBR_TOC_FLAG 0x0004 -#define VBR_SCALE_FLAG 0x0008 - -struct vbrHeader { - unsigned long flags; - unsigned long frames; - unsigned long bytes; - unsigned long scale; - unsigned char toc[100]; -}; - -struct frame { - struct al_table *alloc; - int stereo; - int jsbound; - int II_sblimit; - int down_sample_sblimit; - int lsf; - int mpeg25; - int header_change; - int lay; - int error_protection; - int bitrate_index; - int sampling_frequency; - int padding; - int extension; - int mode; - int mode_ext; - int copyright; - int original; - int emphasis; - int framesize; /* computed framesize */ - int padsize; /* */ - - int sideInfoSize; /* Layer3 sideInfo Header size */ - - int vbr; - struct vbrHeader vbr_header; - - /* FIXME: move this to another place */ - unsigned long firsthead; - unsigned long thishead; - int freeformatsize; -}; - -struct bitstream_info { - int bitindex; - unsigned char *wordpointer; -}; - -struct mpstr { - int bsize; - int framesize; - int fsizeold; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - float hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - float synth_buffs[2][2][0x110]; - int synth_bo; - - struct bitstream_info bsi; - int bsbufend[2]; - int bsbufold_end; - unsigned char *bsbuf, *bsbufold; - - float buffs[2][2][0x110]; - int bo; - - float hybridIn [2][SBLIMIT][SSLIMIT]; - float hybridOut[2][SSLIMIT][SBLIMIT]; - unsigned int balloc[2*SBLIMIT]; - struct III_sideinfo sideinfo; - int scalefacs[192]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ - int gr, ss; - int return_later; -}; - -struct reader { - void *filept; - - unsigned int left_in_packet; - unsigned int filepos; - int eof; -}; - -void almpa_close(struct APEG_LAYER*); -int almpa_read_bytes(struct APEG_LAYER*, byte*, unsigned int); -void almpa_head_read(struct APEG_LAYER*, unsigned long*); -void almpa_head_shift(struct APEG_LAYER*, unsigned long*); -void almpa_skip_bytes(struct APEG_LAYER*, int); - - -extern void print_header(struct frame *); -extern void print_header_compact(struct frame *); -extern void print_id3_tag(unsigned char *buf); - -extern void set_pointer(struct mpstr*,int,long); - -extern int open_stream(struct APEG_LAYER *layer); -extern void read_frame_init (struct frame *fr); -extern int read_frame(struct APEG_LAYER *layer,struct frame *fr); -extern int do_layer3(struct mpstr*, struct frame*, struct APEG_LAYER*); -extern int do_layer2(struct mpstr*, struct frame*, struct APEG_LAYER*); -extern int do_layer1(struct mpstr*, struct frame*, struct APEG_LAYER*); - - -extern void synth_1to1(float*,int,unsigned char*,int*,float(*)[2][0x110],int*); -extern void synth_1to1_mono(float*,unsigned char*,int*,float(*)[2][0x110],int*); - -extern void synth_2to1(float*,int,unsigned char*,int*,float(*)[2][0x110],int*); -extern void synth_2to1_mono(float*,unsigned char*,int*,float(*)[2][0x110],int*); - -extern void synth_4to1(float*,int,unsigned char*,int*,float(*)[2][0x110],int*); -extern void synth_4to1_mono(float*,unsigned char*,int*,float(*)[2][0x110],int*); - -#define synth_mono(ds, a, b, c, d, e) \ -switch((ds)) \ -{ \ - case 2: \ - synth_4to1_mono((a), (b), (c), (d), (e)); \ - break; \ - case 1: \ - synth_2to1_mono((a), (b), (c), (d), (e)); \ - break; \ - case 0: \ - synth_1to1_mono((a), (b), (c), (d), (e)); \ - break; \ -} - -#define synth(ds, a, b, c, d, e, f) \ -switch((ds)) \ -{ \ - case 2: \ - synth_4to1((a), (b), (c), (d), (e), (f)); \ - break; \ - case 1: \ - synth_2to1((a), (b), (c), (d), (e), (f)); \ - break; \ - case 0: \ - synth_1to1((a), (b), (c), (d), (e), (f)); \ - break; \ -} - -extern void init_layer3(int); -extern void init_layer2(void); -extern void make_decode_tables(); - -extern void control_generic(struct mpstr *,struct frame *fr); - -extern int getVBRHeader(struct vbrHeader *head,unsigned char *buf, - struct frame *fr); - - -extern long freqs[10]; -extern float muls[27][64]; -extern float decwin[512+32]; -extern float *pnts[5]; - -extern float equalizer[2][32]; - -/* 486 optimizations */ -#define FIR_BUFFER_SIZE 128 -void dct64(float*,float*,float*); -void dct36(float*,float*,float*,float*,float*); - - -static INLINE void do_equalizer(float *bandPtr, int channel) -{ -#if 0 - int i; - for(i = 0;i < 32;++i) - bandPtr[i] *= equalizer[channel][i]; -#else - (void)bandPtr; - (void)channel; -#endif -} - -#endif #include "mpeg1dec.h" diff --git a/Engine/libsrc/apeg-1.2.1/ogg.c b/Engine/libsrc/apeg-1.2.1/ogg.c index 4fe384979c4..15f95cdb1e9 100644 --- a/Engine/libsrc/apeg-1.2.1/ogg.c +++ b/Engine/libsrc/apeg-1.2.1/ogg.c @@ -490,7 +490,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) /* if there's pending, decoded audio, grab it */ if((ret = vorbis_synthesis_pcmout(&info->vdsp, &pcm)) > 0) { - short *audiobuf = (short*)layer->audio.pcm.samples; + signed short *audiobuf = (signed short*)layer->audio.pcm.samples; int count = layer->audio.pcm.point / 2; int maxsamples = (layer->audio.bufsize-layer->audio.pcm.point) / 2 / layer->stream.audio.channels; @@ -528,7 +528,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) val += 65535; #endif - audiobuf[count++] = val; + audiobuf[count++] = val - 0x7fff; } } else @@ -547,31 +547,31 @@ static void alvorbis_get_data(APEG_LAYER *layer) int cval = ((pcm[info->vinfo.channels-1][i] >> 9) + 32768) * 0.70710678f; for(j = 0;j < 2;++j) { - audiobuf[count++] = (pcm[j][i] >> 9) + 32768 + cval; + audiobuf[count++] = (pcm[j][i] >> 9) + 32768 + cval - 0x7fff; } for(;j < layer->stream.audio.channels;++j) { - audiobuf[count++] = (pcm[j][i] >> 9) + 32768; + audiobuf[count++] = (pcm[j][i] >> 9) + 32768 - 0x7fff; } } else if((layer->stream.audio.channels&1)) { for(j = 0;j < layer->stream.audio.channels-1;++j) { - audiobuf[count++] = (pcm[j][i] >> 9) + 32768; + audiobuf[count++] = (pcm[j][i] >> 9) + 32768 - 0x7fff; } if((info->vinfo.channels&1)) { - audiobuf[count++] = (pcm[info->vinfo.channels-1][i] >> 9) + 32768; + audiobuf[count++] = (pcm[info->vinfo.channels-1][i] >> 9) + 32768 - 0x7fff; } else - audiobuf[count++] = 0x8000; + audiobuf[count++] = 0; } else { for(j = 0;j < layer->stream.audio.channels;++j) { - audiobuf[count++] = (pcm[j][i] >> 9) + 32768; + audiobuf[count++] = (pcm[j][i] >> 9) + 32768 - 0x7fff; } } } @@ -583,7 +583,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) for(j = 0;j < layer->stream.audio.channels;++j) { // Only this audio path is tested with libtremor - audiobuf[count++] = (pcm[j][i] >> 9) + 32768; + audiobuf[count++] = (pcm[j][i] >> 9) + 32768 - 0x7fff; } } } @@ -606,7 +606,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) val -= 65535; val &= val >> 31; val += 65535; - audiobuf[count++] = val; + audiobuf[count++] = val - 0x7fff; } for(;j < layer->stream.audio.channels;++j) { @@ -615,7 +615,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) val -= 65535; val &= val >> 31; val += 65535; - audiobuf[count++] = val; + audiobuf[count++] = val - 0x7fff; } } else if((layer->stream.audio.channels&1)) @@ -627,7 +627,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) val -= 65535; val &= val >> 31; val += 65535; - audiobuf[count++] = val; + audiobuf[count++] = val - 0x7fff; } if((info->vinfo.channels&1)) { @@ -637,10 +637,10 @@ static void alvorbis_get_data(APEG_LAYER *layer) cval -= 65535; cval &= cval >> 31; cval += 65535; - audiobuf[count++] = cval; + audiobuf[count++] = cval - 0x7fff; } else - audiobuf[count++] = 0x8000; + audiobuf[count++] = 0; } else { @@ -651,7 +651,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) val -= 65535; val &= val >> 31; val += 65535; - audiobuf[count++] = val; + audiobuf[count++] = val - 0x7fff; } } } @@ -667,7 +667,7 @@ static void alvorbis_get_data(APEG_LAYER *layer) val -= 65535; val &= val >> 31; val += 65535; - audiobuf[count++] = val; + audiobuf[count++] = val - 0x7fff; } } } diff --git a/Engine/libsrc/apeg-1.2.1/openal_support.h b/Engine/libsrc/apeg-1.2.1/openal_support.h new file mode 100644 index 00000000000..f5a5e5927d7 --- /dev/null +++ b/Engine/libsrc/apeg-1.2.1/openal_support.h @@ -0,0 +1,13 @@ +#ifndef APEG_OPENAL_SUPPORT_H__ +#define APEG_OPENAL_SUPPORT_H__ + +#ifdef __APPLE__ + #include +#else + #include "AL/al.h" + #include "AL/alc.h" + // [sonneveld] disabled until I add extension detection + // #include "AL/alext.h" +#endif + +#endif diff --git a/Engine/libsrc/apeg-1.2.1/recon.c b/Engine/libsrc/apeg-1.2.1/recon.c index fc11ee45713..826a825dcd2 100644 --- a/Engine/libsrc/apeg-1.2.1/recon.c +++ b/Engine/libsrc/apeg-1.2.1/recon.c @@ -3,7 +3,6 @@ #include #include -#include #include "mpeg1dec.h" /* private prototypes */ diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index b2f720bcad2..60bb7750500 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -698,6 +698,15 @@ + + + + + + + + + diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index 001b9dc4bec..c4f377265ba 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -1727,6 +1727,33 @@ Header Files\gfx + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + + + Library Sources\apeg + From c5105469f644fccf8ec2b4b60740ba9cc380f48d Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 12 Nov 2020 01:43:26 +0300 Subject: [PATCH 28/41] Cut out Windows-only video playback support based on DirectShow --- Engine/ac/global_video.cpp | 7 +- Engine/gfx/ali3dsw.cpp | 18 - Engine/gfx/ali3dsw.h | 3 - Engine/gfx/graphicsdriver.h | 1 - Engine/media/video/VMR9Graph.h | 150 --- Engine/platform/base/agsplatformdriver.cpp | 1 - Engine/platform/base/agsplatformdriver.h | 1 - Engine/platform/windows/acplwin.cpp | 61 -- Engine/platform/windows/gfx/ali3dd3d.cpp | 22 - Engine/platform/windows/gfx/ali3dd3d.h | 3 - .../platform/windows/media/video/acwavi.cpp | 420 -------- .../platform/windows/media/video/acwavi3d.cpp | 958 ------------------ Solutions/Engine.App/Engine.App.vcxproj | 3 - .../Engine.App/Engine.App.vcxproj.filters | 9 - 14 files changed, 3 insertions(+), 1654 deletions(-) delete mode 100644 Engine/media/video/VMR9Graph.h delete mode 100644 Engine/platform/windows/media/video/acwavi.cpp delete mode 100644 Engine/platform/windows/media/video/acwavi3d.cpp diff --git a/Engine/ac/global_video.cpp b/Engine/ac/global_video.cpp index 4c41ebed040..9cc889405ce 100644 --- a/Engine/ac/global_video.cpp +++ b/Engine/ac/global_video.cpp @@ -18,6 +18,7 @@ #include "ac/global_video.h" #include "ac/path_helper.h" #include "debug/debugger.h" +#include "debug/debug_log.h" #include "media/video/video.h" #include "media/audio/audio_system.h" #include "platform/base/agsplatformdriver.h" @@ -57,10 +58,8 @@ void pause_sound_if_necessary_and_play_video(const char *name, int skip, int fla } else { - char videoFilePath[MAX_PATH]; - get_install_dir_path(videoFilePath, name); - - platform->PlayVideo(videoFilePath, skip, flags); + debug_script_warn("PlayVideo: file '%s' is an unsupported format.", name); + return; } if (flags < 10) diff --git a/Engine/gfx/ali3dsw.cpp b/Engine/gfx/ali3dsw.cpp index 0749cd1e786..9b47b06a03a 100644 --- a/Engine/gfx/ali3dsw.cpp +++ b/Engine/gfx/ali3dsw.cpp @@ -21,10 +21,6 @@ #include "platform/base/sys_main.h" #include "ac/timer.h" -#ifndef AGS_NO_VIDEO_PLAYER -extern int dxmedia_play_video (const char*, bool, int, int); -#endif - namespace AGS { namespace Engine @@ -785,20 +781,6 @@ void SDLRendererGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int de } // end fading routines -#ifndef AGS_NO_VIDEO_PLAYER - -bool SDLRendererGraphicsDriver::PlayVideo(const char *filename, bool useAVISound, VideoSkipType skipType, bool stretchToFullScreen) -{ -#if AGS_PLATFORM_OS_WINDOWS - int result = dxmedia_play_video(filename, useAVISound, skipType, stretchToFullScreen ? 1 : 0); - return (result == 0); -#else - return 0; -#endif -} - -#endif - // add the alpha values together, used for compositing alpha images // TODO: why is this here, move to gfx/blender? check if there's already similar function there static unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned long n) diff --git a/Engine/gfx/ali3dsw.h b/Engine/gfx/ali3dsw.h index d988ca0f8c8..89146cdfd6f 100644 --- a/Engine/gfx/ali3dsw.h +++ b/Engine/gfx/ali3dsw.h @@ -176,9 +176,6 @@ class SDLRendererGraphicsDriver : public GraphicsDriverBase void FadeOut(int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) override; void FadeIn(int speed, PALETTE pal, int targetColourRed, int targetColourGreen, int targetColourBlue) override; void BoxOutEffect(bool blackingOut, int speed, int delay) override; -#ifndef AGS_NO_VIDEO_PLAYER - bool PlayVideo(const char *filename, bool useAVISound, VideoSkipType skipType, bool stretchToFullScreen) override; -#endif bool SupportsGammaControl() override ; void SetGamma(int newGamma) override; void UseSmoothScaling(bool enabled) override { } diff --git a/Engine/gfx/graphicsdriver.h b/Engine/gfx/graphicsdriver.h index 4c61e06c8e2..3f754420efa 100644 --- a/Engine/gfx/graphicsdriver.h +++ b/Engine/gfx/graphicsdriver.h @@ -163,7 +163,6 @@ class IGraphicsDriver virtual void FadeIn(int speed, PALETTE p, int targetColourRed, int targetColourGreen, int targetColourBlue) = 0; // Runs box-out animation in a blocking manner. virtual void BoxOutEffect(bool blackingOut, int speed, int delay) = 0; - virtual bool PlayVideo(const char *filename, bool useAVISound, VideoSkipType skipType, bool stretchToFullScreen) { return false; } virtual void UseSmoothScaling(bool enabled) = 0; virtual bool SupportsGammaControl() = 0; virtual void SetGamma(int newGamma) = 0; diff --git a/Engine/media/video/VMR9Graph.h b/Engine/media/video/VMR9Graph.h deleted file mode 100644 index 4b91ac02ff3..00000000000 --- a/Engine/media/video/VMR9Graph.h +++ /dev/null @@ -1,150 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= -// -// VMR9Graph.h: interface for the CVMR9Graph class. -// -//============================================================================= - -#if !defined(AFX_VMR9GRAPH_H__449FDB5B_6719_4134_B5A7_B651C08D109E__INCLUDED_) -#define AFX_VMR9GRAPH_H__449FDB5B_6719_4134_B5A7_B651C08D109E__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include -#include - -//#pragma comment( lib, "strmiids.lib" ) -//#pragma comment( lib, "Quartz.lib" ) -//#pragma comment( lib, "d3d9.lib" ) -//#pragma comment( lib, "d3dx9.lib" ) - -#define WM_MEDIA_NOTIF (WM_APP + 777) - -class CVMR9Graph -{ - // Constructor / destructor -public: - CVMR9Graph(); - CVMR9Graph(HWND MediaWindow, IDirect3DDevice9 *device, int NumberOfStream = 4); - ~CVMR9Graph(); - - // Methods -public: - // Graph configuration - void SetNumberOfLayer(int nNumberOfLayer); - BOOL SetMediaWindow(HWND MediaWindow); - BOOL SetMediaFile(const char* pszFileName, bool withSound, int nLayer = 0); - BOOL PreserveAspectRatio(BOOL bPreserve = TRUE); - IBaseFilter* AddFilter(const char* pszName, const GUID& clsid); - - // Graph control - BOOL PlayGraph(); - BOOL StopGraph(); - BOOL ResetGraph(); - OAFilterState GetState(); - IMediaEvent* GetPtrMediaEvent(); - IMediaControl* GetPtrMediaControl(); - IMediaSeeking* GetPtrMediaSeeking(); - IBasicAudio* GetPtrBasicAudio(); - - - // Layer control - BOOL GetVideoRect(LPRECT pRect); - int GetAlphaLayer(int nLayer); - BOOL SetAlphaLayer(int nLayer, int nAlpha); - DWORD GetLayerZOrder(int nLayer); - BOOL SetLayerZOrder(int nLayer, DWORD dwZOrder); - BOOL SetLayerRect(int nLayer, RECT layerRect); - - // Bitmap control - BOOL SetBitmapParams(int nAlpha, COLORREF cTransColor, RECT bitmapRect); - - // Reflected from window - BOOL Repaint(); - BOOL Resize(); - - // helper - LPCTSTR GetLastError(); - - // Internal - BOOL BuildAndRenderGraph(bool withSound); - -protected: - // INIT helper methods - void InitDefaultValues(); - void ReleaseAllInterfaces(); - - // GRAPH methods - BOOL BuildFilterGraph(bool withSound); - BOOL BuildVMR(); - BOOL BuildSoundRenderer(); - BOOL RenderGraph(); - - // DIRECT3D methods - BOOL BuildDirect3d(); - - - // LAYER helper methods - BOOL IsValidLayer(int nLayer); - VMR9NormalizedRect NormalizeRect(LPRECT pRect); - - // DSOW helper methods - HRESULT AddToRot(IUnknown *pUnkGraph); - void RemoveFromRot(); - IPin* GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir); - void ReportError(const char* pszError, HRESULT hrCode); - HRESULT GetNextFilter(IBaseFilter *pFilter, PIN_DIRECTION Dir, IBaseFilter **ppNext); - BOOL RemoveFilterChain(IBaseFilter* pFilter, IBaseFilter* pStopFilter); - HRESULT AddFilterByClsid(IGraphBuilder *pGraph, LPCWSTR wszName, const GUID& clsid, IBaseFilter **ppF); - - // Attributes -public: - bool UseAVISound; - -protected: - DWORD m_dwRotId; - char m_pszErrorDescription[1024+MAX_ERROR_TEXT_LEN]; - int m_nNumberOfStream; - const char* m_pszFileName; - long m_oldWndProc; - // MEDIA WINDOW - HWND m_hMediaWindow; - // SRC interfaces array - IBaseFilter* m_srcFilterArray[10]; - // SOUND interfaces - IBaseFilter* m_pDirectSoundFilter; - // GRAPH interfaces - IUnknown* m_pGraphUnknown; - IGraphBuilder* m_pGraphBuilder; - IFilterGraph* m_pFilterGraph; - IFilterGraph2* m_pFilterGraph2; - IMediaControl* m_pMediaControl; - IMediaSeeking* m_pMediaSeeking; - //IMediaEvent* m_pMediaEvent; - IMediaEventEx* m_pMediaEventEx; - // VMR9 interfaces - IBaseFilter* m_pVMRBaseFilter; - IVMRFilterConfig9* m_pVMRFilterConfig; - IVMRMixerBitmap9* m_pVMRMixerBitmap; - IVMRMixerControl9* m_pVMRMixerControl; - IVMRMonitorConfig9* m_pVMRMonitorConfig; - IVMRWindowlessControl9* m_pVMRWindowlessControl; - // DIRECT3D interfaces - //IDirect3DDevice9* m_pD3DDevice; - IDirect3DSurface9* m_pD3DSurface; -}; - -#endif // !defined(AFX_VMR9GRAPH_H__449FDB5B_6719_4134_B5A7_B651C08D109E__INCLUDED_) diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index d9cec9d1395..a33afe15fd7 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -49,7 +49,6 @@ void AGSPlatformDriver::PauseApplication() { } void AGSPlatformDriver::ResumeApplication() { } void AGSPlatformDriver::RegisterGameWithGameExplorer() { } void AGSPlatformDriver::UnRegisterGameWithGameExplorer() { } -void AGSPlatformDriver::PlayVideo(const char* name, int skip, int flags) {} const char* AGSPlatformDriver::GetAllegroFailUserHint() { diff --git a/Engine/platform/base/agsplatformdriver.h b/Engine/platform/base/agsplatformdriver.h index f1f6f76e8e7..0aa4eb2985b 100644 --- a/Engine/platform/base/agsplatformdriver.h +++ b/Engine/platform/base/agsplatformdriver.h @@ -81,7 +81,6 @@ struct AGSPlatformDriver virtual const char* GetAllegroFailUserHint(); virtual eScriptSystemOSID GetSystemOSID() = 0; virtual void GetSystemTime(ScriptDateTime*); - virtual void PlayVideo(const char* name, int skip, int flags); virtual void PostAllegroInit(bool windowed); virtual void PostAllegroExit() = 0; virtual SetupReturnValue RunSetup(const Common::ConfigTree &cfg_in, Common::ConfigTree &cfg_out); diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index 1b93e8cdbf8..dbfd19eab93 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -45,13 +45,6 @@ #include "util/string_compat.h" #include "media/audio/audio_system.h" -#ifndef AGS_NO_VIDEO_PLAYER -extern void dxmedia_abort_video(); -extern void dxmedia_pause_video(); -extern void dxmedia_resume_video(); -extern char lastError[200]; -#endif - using namespace AGS::Common; using namespace AGS::Engine; @@ -122,11 +115,6 @@ struct AGSWin32 : AGSPlatformDriver { virtual void UnRegisterGameWithGameExplorer(); virtual void ValidateWindowSize(int &x, int &y, bool borderless) const; -#ifndef AGS_NO_VIDEO_PLAYER - virtual void PlayVideo(const char* name, int skip, int flags); -#endif - - private: void add_game_to_game_explorer(IGameExplorer* pFwGameExplorer, GUID *guid, const char *guidAsText, bool allUsers); void remove_game_from_game_explorer(IGameExplorer* pFwGameExplorer, GUID *guid, const char *guidAsText, bool allUsers); @@ -703,16 +691,10 @@ const char *AGSWin32::GetGraphicsTroubleshootingText() void AGSWin32::PauseApplication() { -#ifndef AGS_NO_VIDEO_PLAYER - dxmedia_pause_video(); -#endif } void AGSWin32::ResumeApplication() { -#ifndef AGS_NO_VIDEO_PLAYER - dxmedia_resume_video(); -#endif } int AGSWin32::CDPlayerCommand(int cmdd, int datt) { @@ -817,51 +799,8 @@ int AGSWin32::InitializeCDPlayer() { #endif } -#ifndef AGS_NO_VIDEO_PLAYER - -void AGSWin32::PlayVideo(const char *name, int skip, int flags) { - - char useloc[250]; - sprintf(useloc, "%s\\%s", ResPaths.DataDir.GetCStr(), name); - - bool useSound = true; - if (flags >= 10) { - flags -= 10; - useSound = false; - } - else { - } - - bool isError = false; - if (Common::File::TestReadFile(useloc)) - { - isError = (gfxDriver->PlayVideo(useloc, useSound, (VideoSkipType)skip, (flags > 0)) == 0); - } - else - { - isError = true; - sprintf(lastError, "File not found: %s", useloc); - } - - if (isError) { - // turn "Always display as speech" off, to make sure error - // gets displayed correctly - int oldalways = game.options[OPT_ALWAYSSPCH]; - game.options[OPT_ALWAYSSPCH] = 0; - Display("Video playing error: %s", lastError); - game.options[OPT_ALWAYSSPCH] = oldalways; - } - - set_palette_range(palette, 0, 255, 0); -} - -#endif - void AGSWin32::AboutToQuitGame() { -#ifndef AGS_NO_VIDEO_PLAYER - dxmedia_abort_video(); -#endif } void AGSWin32::PostAllegroExit() { diff --git a/Engine/platform/windows/gfx/ali3dd3d.cpp b/Engine/platform/windows/gfx/ali3dd3d.cpp index fa57218ea02..23a0c942bde 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.cpp +++ b/Engine/platform/windows/gfx/ali3dd3d.cpp @@ -32,11 +32,6 @@ #include "platform/base/sys_main.h" #include "util/library.h" -#ifndef AGS_NO_VIDEO_PLAYER -extern int dxmedia_play_video_3d(const char*filename, IDirect3DDevice9 *device, bool useAVISound, int canskip, int stretch); -extern void dxmedia_shutdown_3d(); -#endif - using namespace AGS::Common; // Necessary to update textures from 8-bit bitmaps @@ -878,11 +873,6 @@ PGfxFilter D3DGraphicsDriver::GetGraphicsFilter() const void D3DGraphicsDriver::UnInit() { -#ifndef AGS_NO_VIDEO_PLAYER - // TODO: this should not be done inside the graphics driver! - dxmedia_shutdown_3d(); -#endif - OnUnInit(); ReleaseDisplayMode(); @@ -1837,18 +1827,6 @@ void D3DGraphicsDriver::BoxOutEffect(bool blackingOut, int speed, int delay) ResetFxPool(); } -#ifndef AGS_NO_VIDEO_PLAYER - -bool D3DGraphicsDriver::PlayVideo(const char *filename, bool useAVISound, VideoSkipType skipType, bool stretchToFullScreen) -{ - direct3ddevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.5f, 0); - - int result = dxmedia_play_video_3d(filename, direct3ddevice, useAVISound, skipType, stretchToFullScreen ? 1 : 0); - return (result == 0); -} - -#endif - void D3DGraphicsDriver::SetScreenFade(int red, int green, int blue) { D3DBitmap *ddb = static_cast(MakeFx(red, green, blue)); diff --git a/Engine/platform/windows/gfx/ali3dd3d.h b/Engine/platform/windows/gfx/ali3dd3d.h index ef5102a3adc..cf19c8b2db3 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.h +++ b/Engine/platform/windows/gfx/ali3dd3d.h @@ -199,9 +199,6 @@ class D3DGraphicsDriver : public VideoMemoryGraphicsDriver void FadeOut(int speed, int targetColourRed, int targetColourGreen, int targetColourBlue) override; void FadeIn(int speed, PALETTE p, int targetColourRed, int targetColourGreen, int targetColourBlue) override; void BoxOutEffect(bool blackingOut, int speed, int delay) override; -#ifndef AGS_NO_VIDEO_PLAYER - bool PlayVideo(const char *filename, bool useSound, VideoSkipType skipType, bool stretchToFullScreen) override; -#endif bool SupportsGammaControl() override; void SetGamma(int newGamma) override; void UseSmoothScaling(bool enabled) override { _smoothScaling = enabled; } diff --git a/Engine/platform/windows/media/video/acwavi.cpp b/Engine/platform/windows/media/video/acwavi.cpp deleted file mode 100644 index 1f36c2cec5d..00000000000 --- a/Engine/platform/windows/media/video/acwavi.cpp +++ /dev/null @@ -1,420 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= -// -// AVI/MPG player for AGS -// Adapted from MS DirectX Media example program to work with allegro -// 2002 Chris Jones -// -//============================================================================= - -#include "core/platform.h" - -#if AGS_PLATFORM_OS_WINDOWS && ! defined (AGS_NO_VIDEO_PLAYER) -#define BITMAP WINDOWS_BITMAP -#include -#undef BITMAP -#include -#include -#include // Multimedia stream interfaces -#include // DirectDraw multimedia stream interfaces -#include // Defines DEFINE_GUID macro and enables GUID initialization -#include "ac/draw.h" -#include "ac/keycode.h" -#include "gfx/bitmap.h" -#include "gfx/graphicsdriver.h" -#include "main/game_run.h" -#include "platform/base/agsplatformdriver.h" -#include "platform/base/sys_main.h" - -using namespace AGS::Common; -using namespace AGS::Engine; - -//link with the following libraries under project/settings/link... -//amstrmid.lib quartz.lib strmbase.lib ddraw.lib - -extern void update_audio_system_on_game_loop(); -extern void update_polled_stuff_if_runtime(); -extern int ags_mgetbutton(); -extern volatile char want_exit; -extern IGraphicsDriver *gfxDriver; -//int errno; -char lastError[300]; - -//Global variables -HWND ghWnd; -BOOL g_bAppactive = FALSE; // The window is active -bool useSound = true; -volatile bool currentlyPlaying = false; -volatile bool currentlyPaused = false; - -//DirectDrawEx Global interfaces -extern "C" extern LPDIRECTDRAW2 directdraw; -//extern "C" extern IUnknown* directsound; -extern "C" extern BITMAP *gfx_directx_create_system_bitmap(int width, int height); - -//Global MultiMedia streaming interfaces -IMultiMediaStream *g_pMMStream=NULL; -IMediaStream *g_pPrimaryVidStream=NULL; -IDirectDrawMediaStream *g_pDDStream=NULL; -IDirectDrawStreamSample *g_pSample=NULL; - -Bitmap *vscreen = NULL; -Bitmap *vsMemory = NULL; - -//Function prototypes -HRESULT RenderFileToMMStream(LPCTSTR szFilename); -HRESULT InitRenderToSurface(); -void RenderToSurface(); - -void ExitCode() { - //Release MultiMedia streaming Objects - if (g_pMMStream != NULL) { - g_pMMStream->Release(); - g_pMMStream= NULL; - } - if (g_pSample != NULL) { - g_pSample->Release(); - g_pSample = NULL; - } - if (g_pDDStream != NULL) { - g_pDDStream->Release(); - g_pDDStream= NULL; - } - if (g_pPrimaryVidStream != NULL) { - g_pPrimaryVidStream->Release(); - g_pPrimaryVidStream= NULL; - } -} - -typedef struct BMP_EXTRA_INFO { - LPDIRECTDRAWSURFACE2 surf; - struct BMP_EXTRA_INFO *next; - struct BMP_EXTRA_INFO *prev; - int flags; - int lock_nesting; -} BMP_EXTRA_INFO; - -LPDIRECTDRAWSURFACE get_bitmap_surface (Bitmap *bmp) { - BMP_EXTRA_INFO *bei = (BMP_EXTRA_INFO*)((BITMAP*)bmp->GetAllegroBitmap())->extra; - - // convert the DDSurface2 back to a standard DDSurface - return (LPDIRECTDRAWSURFACE)bei->surf; -} -LPDIRECTDRAWSURFACE2 get_bitmap_surface2 (Bitmap *bmp) { - BMP_EXTRA_INFO *bei = (BMP_EXTRA_INFO*)((BITMAP*)bmp->GetAllegroBitmap())->extra; - - return bei->surf; -} - -//Create the stream sample which will be used to call updates on the video -HRESULT InitRenderToSurface() { - - HRESULT hr; - DDSURFACEDESC ddsd; - - //Use the multimedia stream to get the primary video media stream - hr = g_pMMStream->GetMediaStream(MSPID_PrimaryVideo, &g_pPrimaryVidStream); - if (FAILED(hr)) { - strcpy (lastError, "MMStream::GetMediaStream failed to create the primary video stream."); - return E_FAIL; - } - - //Use the media stream to get the IDirectDrawMediaStream - hr = g_pPrimaryVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&g_pDDStream); - if (FAILED(hr)) { - strcpy(lastError, "The video stream does not support the IDirectDrawMediaStream interface; ensure you have the latest DirectX version installed."); - return E_FAIL; - } - - //Must set dwSize before calling GetFormat - ddsd.dwSize = sizeof(ddsd); - hr = g_pDDStream->GetFormat(&ddsd, NULL, NULL, NULL); - if (FAILED(hr)) { - strcpy(lastError, "IDirectDrawMediaStream::GetFormat failed"); - return E_FAIL; - } - - RECT rect; - rect.top = rect.left = 0; - // these are the width and height of the video - rect.bottom = ddsd.dwHeight; - rect.right = ddsd.dwWidth; - - if (vscreen == NULL) - vscreen = BitmapHelper::CreateRawBitmapOwner(gfx_directx_create_system_bitmap(ddsd.dwWidth, ddsd.dwHeight)); - - if (vscreen == NULL) { - strcpy(lastError, "Unable to create the DX Video System Bitmap"); - return E_FAIL; - } - - vsMemory = BitmapHelper::CreateBitmap(vscreen->GetWidth(), vscreen->GetHeight(), vscreen->GetColorDepth()); - - IDirectDrawSurface *g_pDDSOffscreen; - g_pDDSOffscreen = get_bitmap_surface (vscreen); - - //Create the stream sample - hr = g_pDDStream->CreateSample(g_pDDSOffscreen, &rect, 0, &g_pSample); - if (FAILED(hr)) { - strcpy (lastError, "VideoStream::CreateSample failed"); - return E_FAIL; - } - - return NOERROR; -} - -//Renders a file to a multimedia stream -HRESULT RenderFileToMMStream(LPCTSTR szFilename) { - HRESULT hr; - IAMMultiMediaStream *pAMStream=NULL; - - //Convert filename to Unicode - WCHAR wFile[MAX_PATH]; - MultiByteToWideChar(CP_ACP, 0, szFilename, -1, wFile, - sizeof(wFile)/sizeof(wFile[0])); - - //Create the AMMultiMediaStream object - hr = CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, - IID_IAMMultiMediaStream, (void **)&pAMStream); - - if (FAILED(hr)) { - strcpy(lastError, "Could not create a CLSID_MultiMediaStream object. " - "Make sure you have the latest version of DirectX installed."); - return E_FAIL; - } - - //Initialize stream - hr = pAMStream->Initialize(STREAMTYPE_READ, 0, NULL); - if (FAILED(hr)) { - strcpy(lastError, "AMStream::Initialize failed."); - return E_FAIL; - } - //Add primary video stream - hr = pAMStream->AddMediaStream(directdraw, &MSPID_PrimaryVideo, 0, NULL); - if (FAILED(hr)) { - strcpy(lastError, "AddMediaStream failed."); - return E_FAIL; - } - //Add primary audio stream - if (useSound) { - //hr = pAMStream->AddMediaStream(directsound, &MSPID_PrimaryAudio, 0, NULL); - hr = pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL); - if (FAILED(hr)) { - strcpy(lastError, "AddMediaStream failed."); - return E_FAIL; - } - } - //Opens and automatically creates a filter graph for the specified media file - hr = pAMStream->OpenFile(wFile, 0); - if (FAILED(hr)) { - pAMStream->Release(); - sprintf(lastError, "File not found or format not supported: %s", szFilename); - return E_FAIL; - } - - //save the local stream to the global variable - g_pMMStream = pAMStream; - // Add a reference to the file - //pAMStream->AddRef(); - - return NOERROR; -} - -int newWidth, newHeight; - -//Perform frame by frame updates and blits. Set the stream -//state to STOP if there are no more frames to update. -void RenderToSurface(Bitmap *vscreen) { - //update each frame - if (g_pSample->Update(0, NULL, NULL, 0) != S_OK) { - g_bAppactive = FALSE; - g_pMMStream->SetState(STREAMSTATE_STOP); - } - else { - g_bAppactive = TRUE; - // TODO: don't render on virtual screen, use gfxDriver->DrawSprite instead! - Bitmap *screen_bmp = gfxDriver->GetMemoryBackBuffer(); - // Because vscreen is a DX Video Bitmap, it can be stretched - // onto the video bitmap but not onto a memory - // bitmap (which is what "screen" is when using backbuffer) - vsMemory->Blit(vscreen, 0, 0, 0, 0, vscreen->GetWidth(), vscreen->GetHeight()); - screen_bmp->StretchBlt(vsMemory, - RectWH(0, 0, vscreen->GetWidth(), vscreen->GetHeight()), - RectWH(screen_bmp->GetWidth() / 2 - newWidth / 2, - screen_bmp->GetHeight() / 2 - newHeight / 2, - newWidth, newHeight)); - // if we're not playing AVI sound, poll the audio system - if (!useSound) - update_audio_system_on_game_loop(); - - render_to_screen(); - } -} - -void dxmedia_pause_video() { - - if (currentlyPlaying) { - currentlyPaused = true; - g_pMMStream->SetState(STREAMSTATE_STOP); - } - -} - -void dxmedia_resume_video() { - - if (currentlyPlaying) { - currentlyPaused = false; - g_pMMStream->SetState(STREAMSTATE_RUN); - } - -} - -void dxmedia_abort_video() { - - if (currentlyPlaying) { - - currentlyPlaying = false; - g_pMMStream->SetState(STREAMSTATE_STOP); - - ExitCode(); - CoUninitialize(); - delete vscreen; - vscreen = NULL; - if (vsMemory != NULL) - { - delete vsMemory; - vsMemory = NULL; - } - strcpy (lastError, "Played successfully."); - } - -} - -int dxmedia_play_video(const char* filename, bool pUseSound, int canskip, int stretch) { - HRESULT hr; - - useSound = pUseSound; - ghWnd = (HWND)sys_win_get_window(); - - CoInitialize(NULL); - - if (!useSound) - update_polled_stuff_if_runtime(); - - hr = RenderFileToMMStream(filename); - if (FAILED(hr)) { - ExitCode(); - CoUninitialize(); - return -1; - } - - if (!useSound) - update_polled_stuff_if_runtime(); - - hr = InitRenderToSurface(); - if (FAILED(hr)) { - ExitCode(); - CoUninitialize(); - return -1; - } - - newWidth = vscreen->GetWidth(); - newHeight = vscreen->GetHeight(); - - Bitmap *screen_bmp = gfxDriver->GetMemoryBackBuffer(); - - if ((stretch == 1) || - (vscreen->GetWidth() > screen_bmp->GetWidth()) || - (vscreen->GetHeight() > screen_bmp->GetHeight())) { - // If they want to stretch, or if it's bigger than the screen, then stretch - float widthRatio = (float)vscreen->GetWidth() / (float)screen_bmp->GetWidth(); - float heightRatio = (float)vscreen->GetHeight() / (float)screen_bmp->GetHeight(); - - if (widthRatio > heightRatio) { - newWidth = vscreen->GetWidth() / widthRatio; - newHeight = vscreen->GetHeight() / widthRatio; - } - else { - newWidth = vscreen->GetWidth() / heightRatio; - newHeight = vscreen->GetHeight() / heightRatio; - } - } - - //Now set the multimedia stream to RUN - hr = g_pMMStream->SetState(STREAMSTATE_RUN); - g_bAppactive = TRUE; - - if (FAILED(hr)) { - sprintf(lastError, "Unable to play stream: 0x%08X", hr); - ExitCode(); - CoUninitialize(); - delete vscreen; - return -1; - } - // in case we're not full screen, clear the background - screen_bmp->Clear(); - - currentlyPlaying = true; - - gfxDriver->ClearDrawLists(); - - while ((g_bAppactive) && (!want_exit)) { - - while (currentlyPaused) { - platform->YieldCPU(); - } - - RenderToSurface(vscreen); - //Sleep(0); - int key, mbut, mwheelz; - if (run_service_key_controls(key)) { - if ((canskip == 1) && (key == eAGSKeyCodeEscape)) - break; - if (canskip >= 2) - break; - } - if (run_service_mb_controls(mbut, mwheelz) && mbut >= 0 && (canskip == 3)) - break; - } - - dxmedia_abort_video(); - - return 0; -} - -#if 0 - -int WINAPI WinMain( - HINSTANCE hInstance, // handle to current instance - HINSTANCE hPrevInstance, // handle to previous instance - LPSTR lpCmdLine, // pointer to command line - int nCmdShow) { - - install_allegro(SYSTEM_AUTODETECT, &errno, atexit); - - install_keyboard(); - - set_color_depth(16); - set_gfx_mode (GFX_DIRECTX_WIN, 640, 480, 0,0); - - set_display_switch_mode(SWITCH_BACKGROUND); - - dxmedia_play_video ("f:\\download\\Seinfeld S05E04 - The Sniffing Accountant.mpg", 1, 1); - dxmedia_play_video ("f:\\download\\Family Guy S02E16 - There's Something About Paulie.mpg", 2, 1); - - return 0; -} -#endif - -#endif // AGS_PLATFORM_OS_WINDOWS \ No newline at end of file diff --git a/Engine/platform/windows/media/video/acwavi3d.cpp b/Engine/platform/windows/media/video/acwavi3d.cpp deleted file mode 100644 index 5b097cd4a63..00000000000 --- a/Engine/platform/windows/media/video/acwavi3d.cpp +++ /dev/null @@ -1,958 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= -// -// AVI/MPG player for AGS -// VMR9-based player to work with D3D -// -//============================================================================= - -#include "core/platform.h" - -#if AGS_PLATFORM_OS_WINDOWS && ! defined (AGS_NO_VIDEO_PLAYER) - -#include -#include -#define DWORD_PTR DWORD* -#define LONG_PTR LONG* -#define LPD3DVECTOR D3DVECTOR* -#define _D3DTYPES_H_ -#define _STRSAFE_H_INCLUDED_ -typedef float D3DVALUE, *LPD3DVALUE; -#include "ac/common.h" -#include "ac/keycode.h" -#include "main/game_run.h" -#include "media/video/VMR9Graph.h" -#include "platform/base/sys_main.h" -#include "media/audio/audio_system.h" - -#define USES_CONVERSION int _convert = 0; _convert; UINT _acp = CP_ACP; _acp; LPCWSTR _lpw = NULL; _lpw; LPCSTR _lpa = NULL; _lpa - -inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp) -{ - // verify that no illegal character present - // since lpw was allocated based on the size of lpa - // don't worry about the number of chars - lpw[0] = '\0'; - MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); - return lpw; -} -inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars) -{ - return AtlA2WHelper(lpw, lpa, nChars, CP_ACP); -} -#define ATLA2WHELPER AtlA2WHelper - - #define A2W(lpa) (\ - ((_lpa = lpa) == NULL) ? NULL : (\ - _convert = (lstrlenA(_lpa)+1),\ - ATLA2WHELPER((LPWSTR) alloca(_convert*2), _lpa, _convert))) - - -// Interface from main game - -extern int ags_mgetbutton(); -extern void update_audio_system_on_game_loop(); -extern volatile char want_exit; -extern char lastError[300]; -CVMR9Graph *graph = NULL; - -void dxmedia_shutdown_3d() -{ - if (graph != NULL) - { - delete graph; - graph = NULL; - } -} - -int dxmedia_play_video_3d(const char* filename, IDirect3DDevice9 *device, bool useAVISound, int canskip, int stretch) -{ - HWND gameWindow = (HWND)sys_win_get_window(); - - if (graph == NULL) - { - graph = new CVMR9Graph(gameWindow, device); - } - - if (!useAVISound) - update_audio_system_on_game_loop(); - - if (!graph->SetMediaFile(filename, useAVISound)) - { - dxmedia_shutdown_3d(); - return -1; - } - graph->SetLayerZOrder(0, 0); - - if (!useAVISound) - update_audio_system_on_game_loop(); - - if (!graph->PlayGraph()) - { - dxmedia_shutdown_3d(); - return -1; - } - - - OAFilterState filterState = State_Running; - while ((filterState != State_Stopped) && (!want_exit)) - { - WaitForNextFrame(); - - if (!useAVISound) - update_audio_system_on_game_loop(); - - filterState = graph->GetState(); - - int key, mbut, mwheelz; - if (run_service_key_controls(key)) { - if ((canskip == 1) && (key == eAGSKeyCodeEscape)) - break; - if (canskip >= 2) - break; - } - if (run_service_mb_controls(mbut, mwheelz) && mbut >= 0 && (canskip == 3)) - break; - - //device->Present(NULL, NULL, 0, NULL); - } - - graph->StopGraph(); - - dxmedia_shutdown_3d(); - return 0; -} - - -// VMR9Graph.cpp: implementation of the CVMR9Graph class. -// -////////////////////////////////////////////////////////////////////// - - -//#include - -#if AGS_PLATFORM_DEBUG -#undef THIS_FILE -static char THIS_FILE[]=__FILE__; -#define new DEBUG_NEW -#endif - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -// Function name : CVMR9Graph::CVMR9Graph -// Description : constructor -// Return type : -CVMR9Graph::CVMR9Graph() -{ - InitDefaultValues(); -} - - -// Function name : CVMR9Graph -// Description : constructor -// Return type : -// Argument : HWND MediaWindow -// Argument : int NumberOfStream -CVMR9Graph::CVMR9Graph(HWND MediaWindow, IDirect3DDevice9 *device, int NumberOfStream) -{ - InitDefaultValues(); - - if (MediaWindow != NULL) - { - m_hMediaWindow = MediaWindow; - } - - if (NumberOfStream > 0 && NumberOfStream < 11) { - m_nNumberOfStream = NumberOfStream; - } - - //m_pD3DDevice = device; - m_oldWndProc = GetWindowLong(m_hMediaWindow, GWL_WNDPROC); -} - -// Function name : CVMR9Graph::~CVMR9Graph -// Description : destructor -// Return type : -CVMR9Graph::~CVMR9Graph() -{ - ReleaseAllInterfaces(); - long newProc = GetWindowLong(m_hMediaWindow, GWL_WNDPROC); -} - - -// Function name : CVMR9Graph::InitDefaultValues -// Description : initialize all default values -// Return type : void -void CVMR9Graph::InitDefaultValues() -{ - ZeroMemory(m_pszErrorDescription, 1024); - m_dwRotId = -1; - m_nNumberOfStream = 4; // default VMR9 config - m_hMediaWindow = NULL; - // SRC interfaces - for (int i=0; i<10; i++) { - m_srcFilterArray[i] = NULL; - } - // SOUND interface - m_pDirectSoundFilter = NULL; - // GRAPH interfaces - m_pGraphUnknown = NULL; - m_pGraphBuilder = NULL; - m_pFilterGraph = NULL; - m_pFilterGraph2 = NULL; - m_pMediaControl = NULL; - m_pMediaSeeking = NULL; - //m_pMediaEvent = NULL; - m_pMediaEventEx = NULL; - // VMR9 interfaces - m_pVMRBaseFilter = NULL; - m_pVMRFilterConfig = NULL; - m_pVMRMixerBitmap = NULL; - m_pVMRMixerControl = NULL; - m_pVMRMonitorConfig = NULL; - m_pVMRWindowlessControl = NULL; - // DIRECT3D interfaces - m_pD3DSurface = NULL; -} - -// Function name : CVMR9Graph::ReleaseAllInterfaces -// Description : release all of the graph interfaces -// Return type : void -void CVMR9Graph::ReleaseAllInterfaces() -{ - // CALLBACK handle - /*if (m_pMediaEventEx != NULL) { - m_pMediaEventEx->SetNotifyWindow(NULL, WM_MEDIA_NOTIF, NULL); - }*/ - // SRC interfaces - for (int i=0; i<10; i++) { - IBaseFilter* pSrcFilter = m_srcFilterArray[i]; - if (pSrcFilter != NULL) { - pSrcFilter->Release(); - m_srcFilterArray[i] = NULL; - } - } - // SOUND interfaces - if (m_pDirectSoundFilter != NULL) { - m_pDirectSoundFilter->Release(); - m_pDirectSoundFilter = NULL; - } - // VMR9 interfaces - if (m_pVMRFilterConfig != NULL) { - m_pVMRFilterConfig->Release(); - m_pVMRFilterConfig = NULL; - } - if (m_pVMRMixerBitmap != NULL) { - m_pVMRMixerBitmap->Release(); - m_pVMRMixerBitmap = NULL; - } - if (m_pVMRMixerControl != NULL) { - m_pVMRMixerControl->Release(); - m_pVMRMixerControl = NULL; - } - if (m_pVMRMonitorConfig != NULL) { - m_pVMRMonitorConfig->Release(); - m_pVMRMonitorConfig = NULL; - } - if (m_pVMRWindowlessControl != NULL) { - m_pVMRWindowlessControl->Release(); - m_pVMRWindowlessControl = NULL; - } - if (m_pVMRBaseFilter != NULL) { - m_pVMRBaseFilter->Release(); - m_pVMRBaseFilter = NULL; - } - // GRAPH interfaces - if (m_pGraphBuilder != NULL) { - m_pGraphBuilder->Release(); - m_pGraphBuilder = NULL; - } - if (m_pFilterGraph != NULL) { - m_pFilterGraph->Release(); - m_pFilterGraph = NULL; - } - if (m_pFilterGraph2 != NULL) { - m_pFilterGraph2->Release(); - m_pFilterGraph2 = NULL; - } - if (m_pMediaControl != NULL) { - m_pMediaControl->Release(); - m_pMediaControl = NULL; - } - if (m_pMediaSeeking!= NULL) { - m_pMediaSeeking->Release(); - m_pMediaSeeking = NULL; - } - /*if (m_pMediaEvent != NULL) { - m_pMediaEvent->Release(); - m_pMediaEvent = NULL; - }*/ - /*if (m_pMediaEventEx != NULL) { - m_pMediaEventEx->Release(); - m_pMediaEventEx = NULL; - }*/ - if (m_pGraphUnknown != NULL) { - m_pGraphUnknown->Release(); - m_pGraphUnknown = NULL; - } - // DIRECT3D interfaces - if (m_pD3DSurface != NULL) { - m_pD3DSurface->Release(); - m_pD3DSurface = NULL; - } -} - -////////////////////////////////////////////////////////////////////// -// Helper Functions -////////////////////////////////////////////////////////////////////// - - -// Function name : CVMR9Graph::GetLastError -// Description : get the last error description -// Return type : LPCTSTR -LPCTSTR CVMR9Graph::GetLastError() -{ - return (const char*)m_pszErrorDescription; -} - - -// Function name : CVMR9Graph::AddToRot -// Description : let the graph instance be accessible from graphedit -// Return type : HRESULT -// Argument : IUnknown *pUnkGraph -// Argument : DWORD *pdwRegister -HRESULT CVMR9Graph::AddToRot(IUnknown *pUnkGraph) -{ - if (pUnkGraph == NULL) { - return E_INVALIDARG; - } - - IMoniker * pMoniker; - IRunningObjectTable *pROT; - if (FAILED(GetRunningObjectTable(0, &pROT))) { - return E_FAIL; - } - WCHAR wsz[256]; - wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId()); - HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker); - if (SUCCEEDED(hr)) { - hr = pROT->Register(0, pUnkGraph, pMoniker, &m_dwRotId); - pMoniker->Release(); - } - pROT->Release(); - - return hr; -} - - -// Function name : CVMR9Graph::RemoveFromRot -// Description : remove the graph instance accessibility from graphedit -// Return type : void -void CVMR9Graph::RemoveFromRot() -{ - if (m_dwRotId != -1) { - IRunningObjectTable *pROT; - if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) { - pROT->Revoke(m_dwRotId); - m_dwRotId = -1; - pROT->Release(); - } - } -} - - -// Function name : CVMR9Graph::GetPin -// Description : return the desired pin -// Return type : IPin* -// Argument : IBaseFilter *pFilter -// Argument : PIN_DIRECTION PinDir -IPin* CVMR9Graph::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir) -{ - BOOL bFound = FALSE; - IEnumPins *pEnum; - IPin *pPin; - - pFilter->EnumPins(&pEnum); - while(pEnum->Next(1, &pPin, 0) == S_OK) { - PIN_DIRECTION PinDirThis; - pPin->QueryDirection(&PinDirThis); - if (PinDir == PinDirThis) - { - IPin *pTmp = 0; - if (SUCCEEDED(pPin->ConnectedTo(&pTmp))) // Already connected, not the pin we want. - { - pTmp->Release(); - } - else // Unconnected, this is the pin we want. - { - bFound = true; - break; - } - } - pPin->Release(); - } - pEnum->Release(); - - return (bFound ? pPin : 0); -} - - -// Function name : CVMR9Graph::ReportError -// Description : report an error in the dump device -// Return type : void -// Argument : const char* pszError -// Argument : HRESULT hrCode -void CVMR9Graph::ReportError(const char* pszError, HRESULT hrCode) -{ - TCHAR szErr[MAX_ERROR_TEXT_LEN]; - DWORD res = AMGetErrorText(hrCode, szErr, MAX_ERROR_TEXT_LEN); - if (res != 0) { - sprintf(m_pszErrorDescription, "[ERROR in %s, line %d] %s : COM Error 0x%x, %s", __FILE__, __LINE__, pszError, hrCode, szErr); - } else { - sprintf(m_pszErrorDescription, "[ERROR in %s, line %d] %s : COM Error 0x%x", __FILE__, __LINE__, pszError, hrCode); - } - strcpy(lastError, m_pszErrorDescription); - //TRACE("%s \r\n", m_pszErrorDescription); -} - - -// Function name : CVMR9Graph::GetNextFilter -// Description : -// Return type : HRESULT -// Argument : IBaseFilter *pFilter -// Argument : PIN_DIRECTION Dir -// Argument : IBaseFilter **ppNext -HRESULT CVMR9Graph::GetNextFilter(IBaseFilter *pFilter, PIN_DIRECTION Dir, IBaseFilter **ppNext) -{ - if (!pFilter || !ppNext) return E_POINTER; - - IEnumPins *pEnum = 0; - IPin *pPin = 0; - HRESULT hr = pFilter->EnumPins(&pEnum); - if (FAILED(hr)) return hr; - while (S_OK == pEnum->Next(1, &pPin, 0)) { - // See if this pin matches the specified direction. - PIN_DIRECTION ThisPinDir; - hr = pPin->QueryDirection(&ThisPinDir); - if (FAILED(hr)) { - // Something strange happened. - hr = E_UNEXPECTED; - pPin->Release(); - break; - } - if (ThisPinDir == Dir) { - // Check if the pin is connected to another pin. - IPin *pPinNext = 0; - hr = pPin->ConnectedTo(&pPinNext); - if (SUCCEEDED(hr)) - { - // Get the filter that owns that pin. - PIN_INFO PinInfo; - hr = pPinNext->QueryPinInfo(&PinInfo); - pPinNext->Release(); - pPin->Release(); - pEnum->Release(); - if (FAILED(hr) || (PinInfo.pFilter == NULL)) - { - // Something strange happened. - return E_UNEXPECTED; - } - // This is the filter we're looking for. - *ppNext = PinInfo.pFilter; // Client must release. - return S_OK; - } - } - pPin->Release(); - } - pEnum->Release(); - // Did not find a matching filter. - return E_FAIL; -} - - -// Function name : CVMR9Graph::RemoveFilterChain -// Description : remove a chain of filter, stopping at pStopFilter -// Return type : BOOL -// Argument : IBaseFilter* pFilter -// Argument : IBaseFilter* pStopFilter -BOOL CVMR9Graph::RemoveFilterChain(IBaseFilter* pFilter, IBaseFilter* pStopFilter) -{ - HRESULT hr; - - IBaseFilter* pFilterFound = NULL; - - hr = GetNextFilter(pFilter, PINDIR_OUTPUT, &pFilterFound); - if (SUCCEEDED(hr) && pFilterFound != pStopFilter) { - RemoveFilterChain(pFilterFound, pStopFilter); - pFilterFound->Release(); - } - - m_pFilterGraph->RemoveFilter(pFilter); - - return TRUE; -} - - -// Function name : CVMR9Graph::AddFilterByClsid -// Description : add a filter in the chain -// Return type : HRESULT -// Argument : IGraphBuilder *pGraph -// Argument : LPCWSTR wszName -// Argument : const GUID& clsid -// Argument : IBaseFilter **ppF -HRESULT CVMR9Graph::AddFilterByClsid(IGraphBuilder *pGraph, LPCWSTR wszName, const GUID& clsid, IBaseFilter **ppF) -{ - *ppF = NULL; - HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)ppF); - if (SUCCEEDED(hr)) - { - hr = pGraph->AddFilter((*ppF), wszName); - } - return hr; -} - - -////////////////////////////////////////////////////////////////////// -// Layer helper methods -////////////////////////////////////////////////////////////////////// - - -// Function name : CVMR9Graph::IsValidLayer -// Description : check for valid layer -// Return type : BOOL -// Argument : int nLayer -BOOL CVMR9Graph::IsValidLayer(int nLayer) -{ - if (nLayer > 9 || nLayer < 0) return FALSE; - - IBaseFilter* pBaseFilter = m_srcFilterArray[nLayer]; - if (pBaseFilter == NULL) - return FALSE; - else - return TRUE; -} - - - -////////////////////////////////////////////////////////////////////// -// Graph Construction / Render -////////////////////////////////////////////////////////////////////// - - -// We need this because the filter graph must be built -// on the D3D thread -static int wndproc_build_filter_graph() -{ - return graph->BuildAndRenderGraph(graph->UseAVISound); -} - -BOOL CVMR9Graph::BuildAndRenderGraph(bool withSound) -{ - USES_CONVERSION; - - int nLayer = 0; - HRESULT hr; - - // ENSURE that a valid graph builder is available - if (m_pGraphBuilder == NULL) { - BOOL bRet = BuildFilterGraph(withSound); - if (!bRet) return bRet; - } - - // ENSURE that the filter graph is in a stop state - OAFilterState filterState; - m_pMediaControl->GetState(500, &filterState); - if (filterState != State_Stopped) { - m_pMediaControl->Stop(); - } - - // CHECK a source filter availaibility for the layer - if (m_srcFilterArray[nLayer] == NULL) { - char pszFilterName[10]; - sprintf(pszFilterName, "SRC%02d", nLayer); - IBaseFilter* pBaseFilter = NULL; - hr = m_pGraphBuilder->AddSourceFilter(A2W(m_pszFileName), A2W(pszFilterName), &pBaseFilter); - if (FAILED(hr)) { - ReportError("Could not find a source filter for this file", hr); - return FALSE; - } - m_srcFilterArray[nLayer] = pBaseFilter; - } else { - // suppress the old src filter - IBaseFilter* pBaseFilter = m_srcFilterArray[nLayer]; - RemoveFilterChain(pBaseFilter, m_pVMRBaseFilter); - pBaseFilter->Release(); - m_srcFilterArray[nLayer] = NULL; - // create a new src filter - char pszFilterName[10]; - sprintf(pszFilterName, "SRC%02d", nLayer); - hr = m_pGraphBuilder->AddSourceFilter(A2W(m_pszFileName), A2W(pszFilterName), &pBaseFilter); - m_srcFilterArray[nLayer] = pBaseFilter; - if (FAILED(hr)) { - m_srcFilterArray[nLayer] = NULL; - ReportError("Could not load the file", hr); - return FALSE; - } - } - - // RENDER the graph - BOOL bRet = RenderGraph(); - if (!bRet) return bRet; - - return TRUE; -} - -// Function name : CVMR9Graph::SetMediaFile -// Description : set a media source -// Return type : BOOL -// Argument : const char* pszFileName -// Argument : int nLayer = 0 -BOOL CVMR9Graph::SetMediaFile(const char* pszFileName, bool withSound, int nLayer) -{ - - if (pszFileName == NULL) { - ReportError("Could not load a file with an empty file name", E_INVALIDARG); - return FALSE; - } - - UseAVISound = withSound; - m_pszFileName = pszFileName; - - if (!wndproc_build_filter_graph()) - return FALSE; - - - return TRUE; -} - -// Function name : CVMR9Graph::BuildFilterGraph -// Description : construct the filter graph -// Return type : BOOL -BOOL CVMR9Graph::BuildFilterGraph(bool withSound) -{ - HRESULT hr; - - ReleaseAllInterfaces(); - RemoveFromRot(); - - // BUILD the filter graph - hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IUnknown, (void**) &m_pGraphUnknown); - if (FAILED(hr)) { - ReportError("Could not build the graph", hr); - return FALSE; - } - // QUERY the filter graph interfaces - hr = m_pGraphUnknown->QueryInterface(IID_IGraphBuilder, (void**) &m_pGraphBuilder); - hr = m_pGraphUnknown->QueryInterface(IID_IFilterGraph, (void**) &m_pFilterGraph); - hr = m_pGraphUnknown->QueryInterface(IID_IFilterGraph2, (void**) &m_pFilterGraph2); - hr = m_pGraphUnknown->QueryInterface(IID_IMediaControl, (void**) & m_pMediaControl); - hr = m_pGraphUnknown->QueryInterface(IID_IMediaSeeking, (void**) & m_pMediaSeeking); - //hr = m_pGraphUnknown->QueryInterface(IID_IMediaEvent, (void**) &m_pMediaEvent); - //hr = m_pGraphUnknown->QueryInterface(IID_IMediaEventEx, (void**) &m_pMediaEventEx); - -/* // SET the graph state window callback - if (m_pMediaEventEx != NULL) { - m_pMediaEventEx->SetNotifyWindow((OAHWND)m_hMediaWindow, WM_MEDIA_NOTIF, NULL); - //m_pMediaEventEx->SetNotifyWindow(NULL, NULL, NULL); - }*/ - - if (withSound) - BuildSoundRenderer(); - -// Don't known what's wrong... but RenderEx crash when playing whith graphedit build 021204 ... - //do we need this?? - //AddToRot(m_pGraphUnknown); - - return BuildVMR(); -} - - -// Function name : CVMR9Graph::BuildVMR -// Description : construct and add the VMR9 renderer to the graph -// Return type : BOOL -BOOL CVMR9Graph::BuildVMR() -{ - HRESULT hr; - - if (m_hMediaWindow == NULL) { - ReportError("Could not operate without a Window", E_FAIL); - return FALSE; - } - - if (m_pGraphBuilder == NULL) { - ReportError("Could not build the VMR, the graph isn't valid", E_FAIL); - return FALSE; - } - - // BUILD the VMR9 - IBaseFilter *pVmr = NULL; - hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &m_pVMRBaseFilter); - if (FAILED(hr)) { - ReportError("Could not create an instance ofthe VMR9", hr); - return FALSE; - } - - // ADD the VMR9 to the graph - hr = m_pGraphBuilder->AddFilter(m_pVMRBaseFilter, L"VMR9"); - if (FAILED(hr)) { - ReportError("Could not add the VMR9 to the Graph", hr); - return FALSE; - } - - // DIRECT3D - //BOOL bD3D = BuildDirect3d(); - - // QUERY the VMR9 interfaces - hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRFilterConfig9, (void**) &m_pVMRFilterConfig); - if (SUCCEEDED(hr)) { - // CONFIGURE the VMR9 - m_pVMRFilterConfig->SetRenderingMode(VMR9Mode_Windowless); - m_pVMRFilterConfig->SetNumberOfStreams(m_nNumberOfStream); - } - - hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRWindowlessControl9, (void**) &m_pVMRWindowlessControl); - if (SUCCEEDED(hr)) { - // CONFIGURE the VMR9 - m_pVMRWindowlessControl->SetVideoClippingWindow(m_hMediaWindow); - m_pVMRWindowlessControl->SetAspectRatioMode(VMR9ARMode_LetterBox); - } - - hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRMixerBitmap9, (void**) &m_pVMRMixerBitmap); - hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRMixerControl9, (void**) &m_pVMRMixerControl); - hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRMonitorConfig9, (void**) &m_pVMRMonitorConfig); - - return TRUE; -} - - -// Function name : CVMR9Graph::BuildSoundRendered -// Description : build the DirectSound renderer -// Return type : BOOL -BOOL CVMR9Graph::BuildSoundRenderer() -{ - HRESULT hr; - - hr = AddFilterByClsid(m_pGraphBuilder, L"DirectSound", CLSID_DSoundRender, &m_pDirectSoundFilter); - if (FAILED(hr)) { - ReportError("Could not add the DirectSoundRenderer", hr); - return FALSE; - } - return TRUE; -} - -// Function name : CVMR9Graph::RenderGraph -// Description : render the graph -// Return type : BOOL -BOOL CVMR9Graph::RenderGraph() -{ - HRESULT hr; - - if (m_pFilterGraph2 == NULL) { - ReportError("Could not render the graph because it is not fully constructed", E_FAIL); - return FALSE; - } - - for (int i=0; i<10; i++) { - IBaseFilter* pBaseFilter = m_srcFilterArray[i]; - if (pBaseFilter != NULL) { - IPin* pPin; - while ((pPin = GetPin(pBaseFilter, PINDIR_OUTPUT)) != NULL) - { - hr = m_pFilterGraph2->RenderEx(pPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); - if (FAILED(hr)) - { - ReportError("Unable to render the pin", hr); - return FALSE; - } - } - } - } - return TRUE; -} - - -// Function name : CVMR9Graph::PreserveAspectRatio -// Description : set aspect ratio mode -// Return type : BOOL -// Argument : BOOL bPreserve -BOOL CVMR9Graph::PreserveAspectRatio(BOOL bPreserve) -{ - if (m_pVMRWindowlessControl == NULL) { - ReportError("Can't set aspect ratio, no VMR", E_FAIL); - return FALSE; - } - - if (bPreserve) - m_pVMRWindowlessControl->SetAspectRatioMode(VMR9ARMode_LetterBox); - else - m_pVMRWindowlessControl->SetAspectRatioMode(VMR9ARMode_None); - - return TRUE; -} - - -// Function name : CVMR9Graph::AddFilter -// Description : manually add a filter in the graph -// Return type : IBaseFilter* : caller responsible of release -// Argument : const char* pszName -// Argument : const GUID& clsid -IBaseFilter* CVMR9Graph::AddFilter(const char* pszName, const GUID& clsid) -{ - USES_CONVERSION; - - HRESULT hr; - - IBaseFilter* pBaseFilter = NULL; - - if (pszName == NULL) { - ReportError("Can't add filter, no valid name", E_INVALIDARG); - return NULL; - } - - hr = AddFilterByClsid(m_pGraphBuilder, A2W(pszName), clsid, &pBaseFilter); - if (FAILED(hr)) { - ReportError("Can't add filter", hr); - return NULL; - } - - return pBaseFilter; -} - -// Function name : CVMR9Graph::PlayGraph -// Description : run the graph -// Return type : BOOL -BOOL CVMR9Graph::PlayGraph() -{ - if (m_pMediaControl == NULL) { - ReportError("Can't play, no graph", E_FAIL); - return FALSE; - } - if (m_pVMRWindowlessControl == NULL) { - ReportError("Can't play, no VMR", E_FAIL); - return FALSE; - } - - // MEDIA SIZE - LONG Width; - LONG Height; - LONG ARWidth; - LONG ARHeight; - m_pVMRWindowlessControl->GetNativeVideoSize(&Width, &Height, &ARWidth, &ARHeight); - - RECT mediaRect; - mediaRect.left = 0; - mediaRect.top = 0; - mediaRect.right = Width; - mediaRect.bottom = Height; - - RECT wndRect; - GetClientRect(m_hMediaWindow, &wndRect); - - m_pVMRWindowlessControl->SetVideoPosition(&mediaRect, &wndRect); - - // RUN - m_pMediaControl->Run(); - - return TRUE; -} - - -// Function name : CVMR9Graph::StopGraph -// Description : stop the graph -// Return type : BOOL -BOOL CVMR9Graph::StopGraph() -{ - if (m_pMediaControl == NULL) { - ReportError("Can't stop, no graph", E_FAIL); - return FALSE; - } - - m_pMediaControl->Stop(); - - return TRUE; -} - -OAFilterState CVMR9Graph::GetState() -{ - OAFilterState filterState; - m_pMediaControl->GetState(500, &filterState); - if (filterState == State_Running) - { - LONGLONG curPos; - m_pMediaSeeking->GetCurrentPosition(&curPos); - LONGLONG length; - m_pMediaSeeking->GetDuration(&length); - - if (curPos >= length) - { - filterState = State_Stopped; - } - } - - return filterState; -} - - -// Function name : CVMR9Graph::ResetGraph -// Description : reset the graph - clean interfaces -// Return type : BOOL -BOOL CVMR9Graph::ResetGraph() -{ - // STOP the graph - if (m_pMediaControl != NULL) { - m_pMediaControl->Stop(); - } - - try { - ReleaseAllInterfaces(); - } catch(...) { - ReportError("Can't reset graph, we have serious bugs...", E_FAIL); - return FALSE; - } - - return TRUE; -} - - -// Function name : SetLayerZOrder -// Description : set z order of the layer -// Return type : BOOL -// Argument : int nLayer -// Argument : DWORD dwZOrder : bigger is away -BOOL CVMR9Graph::SetLayerZOrder(int nLayer, DWORD dwZOrder) -{ - HRESULT hr; - - if (!IsValidLayer(nLayer)) { - ReportError("Can't set order, incorect layer", E_INVALIDARG); - return FALSE; - } - - if (m_pVMRMixerControl == NULL) { - ReportError("Can't set order, no VMR", E_FAIL); - return FALSE; - } - - hr = m_pVMRMixerControl->SetZOrder(nLayer, dwZOrder); - if (FAILED(hr)) { - ReportError("Can't set ZOrder", hr); - return FALSE; - } - - return TRUE; -} - -#endif // AGS_PLATFORM_OS_WINDOWS diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 60bb7750500..e04d038ffd5 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -446,8 +446,6 @@ - - @@ -733,7 +731,6 @@ - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index c4f377265ba..e766f920c72 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -642,12 +642,6 @@ Source Files\media\audio - - Source Files\media\video - - - Source Files\media\video - Source Files\media\video @@ -1391,9 +1385,6 @@ Header Files\media\video - - Header Files\media\video - Header Files\debug From 92f71468e088ac0e911850782668cb013b26de5d Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 12 Nov 2020 01:49:56 +0300 Subject: [PATCH 29/41] Deprecated Windows-only plugin API --- Engine/platform/windows/acplwin.cpp | 40 ++++++++--------------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index dbfd19eab93..5eec6713aee 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -60,20 +60,6 @@ extern RGB palette[256]; #define CSIDL_COMMON_APPDATA 0x0023 #endif -typedef struct BMP_EXTRA_INFO { - LPDIRECTDRAWSURFACE2 surf; - struct BMP_EXTRA_INFO *next; - struct BMP_EXTRA_INFO *prev; - int flags; - int lock_nesting; -} BMP_EXTRA_INFO; - -// from Allegro DDraw driver -extern "C" extern LPDIRECTDRAW2 directdraw; -extern "C" extern LPDIRECTSOUND directsound; -extern "C" extern LPDIRECTINPUTDEVICE mouse_dinput_device; -extern "C" extern LPDIRECTINPUTDEVICE key_dinput_device; - char win32SavedGamesDirectory[MAX_PATH] = "\0"; char win32AppDataDirectory[MAX_PATH] = "\0"; String win32OutputDirectory; @@ -892,34 +878,28 @@ HWND IAGSEngine::GetWindowHandle () { return (HWND)sys_win_get_window(); } LPDIRECTDRAW2 IAGSEngine::GetDirectDraw2 () { - if (directdraw == NULL) - quit("!This plugin requires DirectDraw based graphics driver (software driver)."); - - return directdraw; + quit("!IAGSEngine::GetDirectDraw2() is deprecated and not supported anymore."); + return nullptr; } LPDIRECTDRAWSURFACE2 IAGSEngine::GetBitmapSurface (BITMAP *bmp) { - if (directdraw == NULL) - quit("!This plugin requires DirectDraw based graphics driver (software driver)."); - - BMP_EXTRA_INFO *bei = (BMP_EXTRA_INFO*)bmp->extra; - - if (bmp == gfxDriver->GetMemoryBackBuffer()->GetAllegroBitmap()) - invalidate_screen(); - - return bei->surf; + quit("!IAGSEngine::GetBitmapSurface() is deprecated and not supported anymore."); + return nullptr; } LPDIRECTSOUND IAGSEngine::GetDirectSound() { - return directsound; + quit("!IAGSEngine::GetDirectSound() is deprecated and not supported anymore."); + return nullptr; } LPDIRECTINPUTDEVICE IAGSEngine::GetDirectInputKeyboard() { - return key_dinput_device; + quit("!IAGSEngine::GetDirectInputKeyboard() is deprecated and not supported anymore."); + return nullptr; } LPDIRECTINPUTDEVICE IAGSEngine::GetDirectInputMouse() { - return mouse_dinput_device; + quit("!IAGSEngine::GetDirectInputMouse() is deprecated and not supported anymore."); + return nullptr; } #endif From ae8b7369e92e2091180e27fae2cfa7dfa8a1bb0a Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 13 Nov 2020 17:09:03 +0300 Subject: [PATCH 30/41] Imported stripped Allegro source, link in MSVS project AGS still uses following from Allegro lib: * bitmaps, drawing, blending and palette functions; * functions for loading/saving bitmaps and pcx; * playing FLIC; * PACKFILE (used in limited situations, e.g. FLIC); * fixed math functions; * file path and find-file functions; * unicode functions; --- Solutions/Common.Lib/Common.Lib.vcxproj | 98 +- .../Common.Lib/Common.Lib.vcxproj.filters | 168 + Solutions/Engine.App/Engine.App.vcxproj | 25 +- libsrc/allegro/include/allegro.h | 51 + libsrc/allegro/include/allegro/base.h | 102 + libsrc/allegro/include/allegro/color.h | 149 + libsrc/allegro/include/allegro/datafile.h | 114 + libsrc/allegro/include/allegro/debug.h | 49 + libsrc/allegro/include/allegro/draw.h | 91 + libsrc/allegro/include/allegro/file.h | 178 + libsrc/allegro/include/allegro/fixed.h | 39 + libsrc/allegro/include/allegro/fli.h | 62 + libsrc/allegro/include/allegro/fmaths.h | 46 + libsrc/allegro/include/allegro/gfx.h | 312 ++ .../allegro/include/allegro/inline/color.inl | 179 + .../allegro/include/allegro/inline/draw.inl | 408 +++ libsrc/allegro/include/allegro/inline/fix.inl | 254 ++ .../allegro/include/allegro/inline/fmaths.inl | 234 ++ libsrc/allegro/include/allegro/inline/gfx.inl | 260 ++ .../include/allegro/internal/aintern.h | 596 ++++ .../include/allegro/internal/alconfig.h | 414 +++ libsrc/allegro/include/allegro/palette.h | 42 + .../include/allegro/platform/alandcfg.h | 55 + .../include/allegro/platform/alioscfg.h | 58 + .../allegro/include/allegro/platform/almsvc.h | 91 + .../include/allegro/platform/alosxcfg.h | 60 + .../allegro/include/allegro/platform/alucfg.h | 56 + .../include/allegro/platform/astdint.h | 37 + libsrc/allegro/include/allegro/system.h | 68 + libsrc/allegro/include/allegro/unicode.h | 116 + libsrc/allegro/include/winalleg.h | 93 + libsrc/allegro/src/allegro.c | 593 +++ libsrc/allegro/src/blit.c | 760 ++++ libsrc/allegro/src/bmp.c | 873 +++++ libsrc/allegro/src/c/cblit.h | 184 + libsrc/allegro/src/c/cblit16.c | 27 + libsrc/allegro/src/c/cblit24.c | 27 + libsrc/allegro/src/c/cblit32.c | 27 + libsrc/allegro/src/c/cblit8.c | 27 + libsrc/allegro/src/c/cdefs15.h | 102 + libsrc/allegro/src/c/cdefs16.h | 103 + libsrc/allegro/src/c/cdefs24.h | 102 + libsrc/allegro/src/c/cdefs32.h | 98 + libsrc/allegro/src/c/cdefs8.h | 97 + libsrc/allegro/src/c/cgfx.h | 264 ++ libsrc/allegro/src/c/cgfx15.c | 28 + libsrc/allegro/src/c/cgfx16.c | 28 + libsrc/allegro/src/c/cgfx24.c | 28 + libsrc/allegro/src/c/cgfx32.c | 28 + libsrc/allegro/src/c/cgfx8.c | 28 + libsrc/allegro/src/c/cmisc.c | 50 + libsrc/allegro/src/c/cspr.h | 567 +++ libsrc/allegro/src/c/cspr15.c | 28 + libsrc/allegro/src/c/cspr16.c | 28 + libsrc/allegro/src/c/cspr24.c | 28 + libsrc/allegro/src/c/cspr32.c | 28 + libsrc/allegro/src/c/cspr8.c | 28 + libsrc/allegro/src/c/cstretch.c | 460 +++ libsrc/allegro/src/colblend.c | 446 +++ libsrc/allegro/src/color.c | 889 +++++ libsrc/allegro/src/dataregi.c | 71 + libsrc/allegro/src/dither.c | 90 + libsrc/allegro/src/file.c | 1663 +++++++++ libsrc/allegro/src/fli.c | 1053 ++++++ libsrc/allegro/src/flood.c | 278 ++ libsrc/allegro/src/gfx.c | 719 ++++ libsrc/allegro/src/graphics.c | 539 +++ libsrc/allegro/src/inline.c | 28 + libsrc/allegro/src/libc.c | 176 + libsrc/allegro/src/math.c | 367 ++ libsrc/allegro/src/pcx.c | 346 ++ libsrc/allegro/src/polygon.c | 274 ++ libsrc/allegro/src/quantize.c | 522 +++ libsrc/allegro/src/readbmp.c | 250 ++ libsrc/allegro/src/rotate.c | 896 +++++ libsrc/allegro/src/unicode.c | 3166 +++++++++++++++++ libsrc/allegro/src/unix/ufile.c | 467 +++ libsrc/allegro/src/vtable.c | 57 + libsrc/allegro/src/vtable15.c | 100 + libsrc/allegro/src/vtable16.c | 100 + libsrc/allegro/src/vtable24.c | 99 + libsrc/allegro/src/vtable32.c | 99 + libsrc/allegro/src/vtable8.c | 100 + libsrc/allegro/src/win/gdi.c | 660 ++++ libsrc/allegro/src/win/wfile.c | 362 ++ 85 files changed, 22937 insertions(+), 26 deletions(-) create mode 100644 libsrc/allegro/include/allegro.h create mode 100644 libsrc/allegro/include/allegro/base.h create mode 100644 libsrc/allegro/include/allegro/color.h create mode 100644 libsrc/allegro/include/allegro/datafile.h create mode 100644 libsrc/allegro/include/allegro/debug.h create mode 100644 libsrc/allegro/include/allegro/draw.h create mode 100644 libsrc/allegro/include/allegro/file.h create mode 100644 libsrc/allegro/include/allegro/fixed.h create mode 100644 libsrc/allegro/include/allegro/fli.h create mode 100644 libsrc/allegro/include/allegro/fmaths.h create mode 100644 libsrc/allegro/include/allegro/gfx.h create mode 100644 libsrc/allegro/include/allegro/inline/color.inl create mode 100644 libsrc/allegro/include/allegro/inline/draw.inl create mode 100644 libsrc/allegro/include/allegro/inline/fix.inl create mode 100644 libsrc/allegro/include/allegro/inline/fmaths.inl create mode 100644 libsrc/allegro/include/allegro/inline/gfx.inl create mode 100644 libsrc/allegro/include/allegro/internal/aintern.h create mode 100644 libsrc/allegro/include/allegro/internal/alconfig.h create mode 100644 libsrc/allegro/include/allegro/palette.h create mode 100644 libsrc/allegro/include/allegro/platform/alandcfg.h create mode 100644 libsrc/allegro/include/allegro/platform/alioscfg.h create mode 100644 libsrc/allegro/include/allegro/platform/almsvc.h create mode 100644 libsrc/allegro/include/allegro/platform/alosxcfg.h create mode 100644 libsrc/allegro/include/allegro/platform/alucfg.h create mode 100644 libsrc/allegro/include/allegro/platform/astdint.h create mode 100644 libsrc/allegro/include/allegro/system.h create mode 100644 libsrc/allegro/include/allegro/unicode.h create mode 100644 libsrc/allegro/include/winalleg.h create mode 100644 libsrc/allegro/src/allegro.c create mode 100644 libsrc/allegro/src/blit.c create mode 100644 libsrc/allegro/src/bmp.c create mode 100644 libsrc/allegro/src/c/cblit.h create mode 100644 libsrc/allegro/src/c/cblit16.c create mode 100644 libsrc/allegro/src/c/cblit24.c create mode 100644 libsrc/allegro/src/c/cblit32.c create mode 100644 libsrc/allegro/src/c/cblit8.c create mode 100644 libsrc/allegro/src/c/cdefs15.h create mode 100644 libsrc/allegro/src/c/cdefs16.h create mode 100644 libsrc/allegro/src/c/cdefs24.h create mode 100644 libsrc/allegro/src/c/cdefs32.h create mode 100644 libsrc/allegro/src/c/cdefs8.h create mode 100644 libsrc/allegro/src/c/cgfx.h create mode 100644 libsrc/allegro/src/c/cgfx15.c create mode 100644 libsrc/allegro/src/c/cgfx16.c create mode 100644 libsrc/allegro/src/c/cgfx24.c create mode 100644 libsrc/allegro/src/c/cgfx32.c create mode 100644 libsrc/allegro/src/c/cgfx8.c create mode 100644 libsrc/allegro/src/c/cmisc.c create mode 100644 libsrc/allegro/src/c/cspr.h create mode 100644 libsrc/allegro/src/c/cspr15.c create mode 100644 libsrc/allegro/src/c/cspr16.c create mode 100644 libsrc/allegro/src/c/cspr24.c create mode 100644 libsrc/allegro/src/c/cspr32.c create mode 100644 libsrc/allegro/src/c/cspr8.c create mode 100644 libsrc/allegro/src/c/cstretch.c create mode 100644 libsrc/allegro/src/colblend.c create mode 100644 libsrc/allegro/src/color.c create mode 100644 libsrc/allegro/src/dataregi.c create mode 100644 libsrc/allegro/src/dither.c create mode 100644 libsrc/allegro/src/file.c create mode 100644 libsrc/allegro/src/fli.c create mode 100644 libsrc/allegro/src/flood.c create mode 100644 libsrc/allegro/src/gfx.c create mode 100644 libsrc/allegro/src/graphics.c create mode 100644 libsrc/allegro/src/inline.c create mode 100644 libsrc/allegro/src/libc.c create mode 100644 libsrc/allegro/src/math.c create mode 100644 libsrc/allegro/src/pcx.c create mode 100644 libsrc/allegro/src/polygon.c create mode 100644 libsrc/allegro/src/quantize.c create mode 100644 libsrc/allegro/src/readbmp.c create mode 100644 libsrc/allegro/src/rotate.c create mode 100644 libsrc/allegro/src/unicode.c create mode 100644 libsrc/allegro/src/unix/ufile.c create mode 100644 libsrc/allegro/src/vtable.c create mode 100644 libsrc/allegro/src/vtable15.c create mode 100644 libsrc/allegro/src/vtable16.c create mode 100644 libsrc/allegro/src/vtable24.c create mode 100644 libsrc/allegro/src/vtable32.c create mode 100644 libsrc/allegro/src/vtable8.c create mode 100644 libsrc/allegro/src/win/gdi.c create mode 100644 libsrc/allegro/src/win/wfile.c diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj b/Solutions/Common.Lib/Common.Lib.vcxproj index 920ee1dea94..39cce34a2f0 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj +++ b/Solutions/Common.Lib/Common.Lib.vcxproj @@ -91,7 +91,6 @@ - @@ -154,8 +153,8 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -165,6 +164,7 @@ 4996;%(DisableSpecificWarnings) true 4013; 4150; 4477 + $(IntDir)%(Filename)%(Extension).obj $(OutDir)$(TargetName)$(TargetExt) @@ -173,8 +173,8 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -185,6 +185,7 @@ 4996;%(DisableSpecificWarnings) true 4013; 4150; 4477 + $(IntDir)%(Filename)%(Extension).obj $(OutDir)$(TargetName)$(TargetExt) @@ -194,8 +195,8 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -204,6 +205,7 @@ 4996;%(DisableSpecificWarnings) true 4013; 4150; 4477 + $(IntDir)%(Filename)%(Extension).obj $(OutDir)$(TargetName)$(TargetExt) @@ -213,8 +215,8 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -224,6 +226,7 @@ 4996;%(DisableSpecificWarnings) true 4013; 4150; 4477 + $(IntDir)%(Filename)%(Extension).obj $(OutDir)$(TargetName)$(TargetExt) @@ -233,8 +236,8 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -243,6 +246,7 @@ 4996;%(DisableSpecificWarnings) true 4013; 4150; 4477 + $(IntDir)%(Filename)%(Extension).obj $(OutDir)$(TargetName)$(TargetExt) @@ -251,8 +255,8 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Common\libsrc\freetype-2.1.3\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -262,6 +266,7 @@ 4996;%(DisableSpecificWarnings) true 4013; 4150; 4477 + $(IntDir)%(Filename)%(Extension).obj $(OutDir)$(TargetName)$(TargetExt) @@ -359,6 +364,65 @@ + + + $(IntDir)al_file.obj + $(IntDir)al_file.obj + $(IntDir)al_file.obj + $(IntDir)al_file.obj + $(IntDir)al_file.obj + $(IntDir)al_file.obj + + + $(IntDir)al_math.obj + $(IntDir)al_math.obj + $(IntDir)al_math.obj + $(IntDir)al_math.obj + $(IntDir)al_math.obj + $(IntDir)al_math.obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -449,6 +513,14 @@ + + + + + + + + diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj.filters b/Solutions/Common.Lib/Common.Lib.vcxproj.filters index 0f54eb4a586..208a6d57583 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj.filters +++ b/Solutions/Common.Lib/Common.Lib.vcxproj.filters @@ -84,6 +84,15 @@ {4b4e728b-ae08-436a-aeaa-9e342f323611} + + {2328eaaa-6acc-42b4-af0d-75c3e91c0e85} + + + {925a0e71-4cf9-478c-bf82-26aa4cf4ee9a} + + + {15c601a4-df1d-48e4-ad00-8a22d9761e2b} + @@ -359,6 +368,141 @@ Source Files\ac + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\win + + + Library Sources\allegro\win + + + Library Sources\allegro + + + Library Sources\allegro + @@ -625,5 +769,29 @@ Header Files\ac + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + + + Library Sources\allegro\c + \ No newline at end of file diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index e04d038ffd5..fd7f90c7e9c 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -73,7 +73,6 @@ - @@ -117,8 +116,8 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\allegro\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -130,7 +129,7 @@ 4013; 4150; 4477 - Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common_d.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) @@ -145,8 +144,8 @@ Disabled - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\allegro\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -159,7 +158,7 @@ 4013; 4150; 4477 - Common_d.lib;alleg-debug-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common_d.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) @@ -175,8 +174,8 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\allegro\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -187,7 +186,7 @@ 4013; 4150; 4477 - Common.lib;alleg-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) @@ -208,8 +207,8 @@ MaxSpeed true - ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;WINDOWS_VERSION;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) + ..\..\Common;..\..\Common\libinclude;..\..\Common\libsrc\alfont-2.0.9;..\..\Engine;..\..\Engine\libsrc\apeg-1.2.1;..\..\Engine\libsrc\glad\include;..\..\Engine\libsrc\libcda-0.5;..\..\Plugins;..\..\libsrc\allegro\include;..\..\libsrc\mojoAL;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;ALLEGRO_STATICLINK;ALLEGRO_NO_COMPATIBILITY;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_FIX_CLASS;ALLEGRO_NO_MAGIC_MAIN;DISABLE_MPEG_AUDIO;AGS_HAS_CD_AUDIO;%(PreprocessorDefinitions) MultiThreaded true @@ -221,7 +220,7 @@ 4013; 4150; 4477 - Common.lib;alleg-static-mt.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;ddraw.lib;dinput.lib;dsound.lib;dxguid.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) + Common.lib;SDL2.lib;SDL2main.lib;SDL_sound.lib;d3d9.lib;amstrmid.lib;quartz.lib;shlwapi.lib;winmm.lib;opengl32.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;libtheora_static.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)\.lib\$(Configuration);%(AdditionalLibraryDirectories) LIBC;LIBCD;msvcrt;%(IgnoreSpecificDefaultLibraries) diff --git a/libsrc/allegro/include/allegro.h b/libsrc/allegro/include/allegro.h new file mode 100644 index 00000000000..5f34ed8a0b8 --- /dev/null +++ b/libsrc/allegro/include/allegro.h @@ -0,0 +1,51 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Main header file for the entire Allegro library. + * (separate modules can be included from the allegro/ directory) + * + * By Shawn Hargreaves. + * + * Vincent Penquerc'h split the original allegro.h into separate headers. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_H +#define ALLEGRO_H + +#include "allegro/base.h" + +#include "allegro/system.h" +#include "allegro/debug.h" + +#include "allegro/unicode.h" + +#include "allegro/palette.h" +#include "allegro/gfx.h" +#include "allegro/color.h" +#include "allegro/draw.h" + +#include "allegro/fli.h" + +#include "allegro/file.h" +#include "allegro/datafile.h" + +#include "allegro/fixed.h" +#include "allegro/fmaths.h" + +#ifdef ALLEGRO_EXTRA_HEADER + #include ALLEGRO_EXTRA_HEADER +#endif + +#endif /* ifndef ALLEGRO_H */ + + diff --git a/libsrc/allegro/include/allegro/base.h b/libsrc/allegro/include/allegro/base.h new file mode 100644 index 00000000000..5cc1d8ca027 --- /dev/null +++ b/libsrc/allegro/include/allegro/base.h @@ -0,0 +1,102 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Base header, defines basic stuff needed by pretty much + * everything else. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_BASE_H +#define ALLEGRO_BASE_H + +#ifndef ALLEGRO_NO_STD_HEADERS + #include + #include + #include + #include + #include + #include + #include +#endif + +#if (defined DEBUGMODE) && (defined FORTIFY) + #include +#endif + +#if (defined DEBUGMODE) && (defined DMALLOC) + #include +#endif + +#include "internal/alconfig.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define ALLEGRO_VERSION 4 +#define ALLEGRO_SUB_VERSION 4 +#define ALLEGRO_WIP_VERSION 3 +#define ALLEGRO_VERSION_STR "4.4.3" +#define ALLEGRO_DATE_STR "2019" +#define ALLEGRO_DATE 20190202 /* yyyymmdd */ + +/*******************************************/ +/************ Some global stuff ************/ +/*******************************************/ + + +/* Asm build disabled as of 4.3.10+. */ +#ifndef ALLEGRO_NO_ASM + #define ALLEGRO_NO_ASM +#endif + +#ifndef TRUE + #define TRUE -1 + #define FALSE 0 +#endif + +#undef MIN +#undef MAX +#undef MID + +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) + +/* Returns the median of x, y, z */ +#define MID(x,y,z) ((x) > (y) ? ((y) > (z) ? (y) : ((x) > (z) ? \ + (z) : (x))) : ((y) > (z) ? ((z) > (x) ? (z) : \ + (x)): (y))) + +/* Optimized version of MID for when x <= z. */ +#define CLAMP(x,y,z) MAX((x), MIN((y), (z))) + +#undef ABS +#define ABS(x) (((x) >= 0) ? (x) : (-(x))) + +#undef SGN +#define SGN(x) (((x) >= 0) ? 1 : -1) + +#define AL_PI 3.14159265358979323846 + +#define AL_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) + +AL_VAR(int *, allegro_errno); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_BASE_H */ + + diff --git a/libsrc/allegro/include/allegro/color.h b/libsrc/allegro/include/allegro/color.h new file mode 100644 index 00000000000..2271d34e0c7 --- /dev/null +++ b/libsrc/allegro/include/allegro/color.h @@ -0,0 +1,149 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Color manipulation routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_COLOR_H +#define ALLEGRO_COLOR_H + +#include "base.h" +#include "palette.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +AL_VAR(PALETTE, black_palette); +AL_VAR(PALETTE, desktop_palette); +AL_VAR(PALETTE, default_palette); + +typedef struct { + unsigned char data[32][32][32]; +} RGB_MAP; + +typedef struct { + unsigned char data[PAL_SIZE][PAL_SIZE]; +} COLOR_MAP; + +AL_VAR(RGB_MAP *, rgb_map); +AL_VAR(COLOR_MAP *, color_map); + +AL_VAR(PALETTE, _current_palette); + +AL_VAR(int, _rgb_r_shift_15); +AL_VAR(int, _rgb_g_shift_15); +AL_VAR(int, _rgb_b_shift_15); +AL_VAR(int, _rgb_r_shift_16); +AL_VAR(int, _rgb_g_shift_16); +AL_VAR(int, _rgb_b_shift_16); +AL_VAR(int, _rgb_r_shift_24); +AL_VAR(int, _rgb_g_shift_24); +AL_VAR(int, _rgb_b_shift_24); +AL_VAR(int, _rgb_r_shift_32); +AL_VAR(int, _rgb_g_shift_32); +AL_VAR(int, _rgb_b_shift_32); +AL_VAR(int, _rgb_a_shift_32); + +AL_ARRAY(int, _rgb_scale_5); +AL_ARRAY(int, _rgb_scale_6); + +#define MASK_COLOR_8 0 +#define MASK_COLOR_15 0x7C1F +#define MASK_COLOR_16 0xF81F +#define MASK_COLOR_24 0xFF00FF +#define MASK_COLOR_32 0xFF00FF + +AL_VAR(int *, palette_color); + +AL_FUNC(void, set_color, (int idx, AL_CONST RGB *p)); +AL_FUNC(void, set_palette, (AL_CONST PALETTE p)); +AL_FUNC(void, set_palette_range, (AL_CONST PALETTE p, int from, int to, int retracesync)); + +AL_FUNC(void, get_color, (int idx, RGB *p)); +AL_FUNC(void, get_palette, (PALETTE p)); +AL_FUNC(void, get_palette_range, (PALETTE p, int from, int to)); + +AL_FUNC(void, fade_interpolate, (AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to)); + +AL_FUNC(void, select_palette, (AL_CONST PALETTE p)); +AL_FUNC(void, unselect_palette, (void)); + +AL_FUNC(void, generate_332_palette, (PALETTE pal)); +AL_FUNC(int, generate_optimized_palette, (struct BITMAP *image, PALETTE pal, AL_CONST signed char rsvdcols[256])); + +AL_FUNC(void, create_rgb_table, (RGB_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_light_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_trans_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_color_table, (COLOR_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, blend, (AL_CONST PALETTE pal, int x, int y, RGB *rgb)), AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_blender_table, (COLOR_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos)))); + +typedef AL_METHOD(unsigned long, BLENDER_FUNC, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(void, set_blender_mode, (BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, int r, int g, int b, int a)); +AL_FUNC(void, set_blender_mode_ex, (BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, BLENDER_FUNC b32, BLENDER_FUNC b15x, BLENDER_FUNC b16x, BLENDER_FUNC b24x, int r, int g, int b, int a)); + +AL_FUNC(void, set_alpha_blender, (void)); +AL_FUNC(void, set_write_alpha_blender, (void)); +AL_FUNC(void, set_trans_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_add_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_burn_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_color_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_difference_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_dissolve_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_dodge_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_hue_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_invert_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_luminance_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_multiply_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_saturation_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_screen_blender, (int r, int g, int b, int a)); + +AL_FUNC(void, hsv_to_rgb, (float h, float s, float v, int *r, int *g, int *b)); +AL_FUNC(void, rgb_to_hsv, (int r, int g, int b, float *h, float *s, float *v)); + +AL_FUNC(int, bestfit_color, (AL_CONST PALETTE pal, int r, int g, int b)); + +AL_FUNC(int, makecol, (int r, int g, int b)); +AL_FUNC(int, makecol8, (int r, int g, int b)); +AL_FUNC(int, makecol_depth, (int color_depth, int r, int g, int b)); + +AL_FUNC(int, makeacol, (int r, int g, int b, int a)); +AL_FUNC(int, makeacol_depth, (int color_depth, int r, int g, int b, int a)); + +AL_FUNC(int, makecol15_dither, (int r, int g, int b, int x, int y)); +AL_FUNC(int, makecol16_dither, (int r, int g, int b, int x, int y)); + +AL_FUNC(int, getr, (int c)); +AL_FUNC(int, getg, (int c)); +AL_FUNC(int, getb, (int c)); +AL_FUNC(int, geta, (int c)); + +AL_FUNC(int, getr_depth, (int color_depth, int c)); +AL_FUNC(int, getg_depth, (int color_depth, int c)); +AL_FUNC(int, getb_depth, (int color_depth, int c)); +AL_FUNC(int, geta_depth, (int color_depth, int c)); + +#ifdef __cplusplus + } +#endif + +#include "inline/color.inl" + +#endif /* ifndef ALLEGRO_COLOR_H */ + + diff --git a/libsrc/allegro/include/allegro/datafile.h b/libsrc/allegro/include/allegro/datafile.h new file mode 100644 index 00000000000..86640f68ecf --- /dev/null +++ b/libsrc/allegro/include/allegro/datafile.h @@ -0,0 +1,114 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Datafile access routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DATAFILE_H +#define ALLEGRO_DATAFILE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; +struct PACKFILE; +struct RGB; + +#define DAT_ID(a,b,c,d) AL_ID(a,b,c,d) + +#define DAT_MAGIC DAT_ID('A','L','L','.') +#define DAT_FILE DAT_ID('F','I','L','E') +#define DAT_DATA DAT_ID('D','A','T','A') +#define DAT_FONT DAT_ID('F','O','N','T') +#define DAT_SAMPLE DAT_ID('S','A','M','P') +#define DAT_MIDI DAT_ID('M','I','D','I') +#define DAT_PATCH DAT_ID('P','A','T',' ') +#define DAT_FLI DAT_ID('F','L','I','C') +#define DAT_BITMAP DAT_ID('B','M','P',' ') +#define DAT_RLE_SPRITE DAT_ID('R','L','E',' ') +#define DAT_C_SPRITE DAT_ID('C','M','P',' ') +#define DAT_XC_SPRITE DAT_ID('X','C','M','P') +#define DAT_PALETTE DAT_ID('P','A','L',' ') +#define DAT_PROPERTY DAT_ID('p','r','o','p') +#define DAT_NAME DAT_ID('N','A','M','E') +#define DAT_END -1 + + +typedef struct DATAFILE_PROPERTY +{ + char *dat; /* pointer to the data */ + int type; /* property type */ +} DATAFILE_PROPERTY; + + +typedef struct DATAFILE +{ + void *dat; /* pointer to the data */ + int type; /* object type */ + long size; /* size of the object */ + DATAFILE_PROPERTY *prop; /* object properties */ +} DATAFILE; + + +typedef struct DATAFILE_INDEX +{ + char *filename; /* datafile name (path) */ + long *offset; /* list of offsets */ +} DATAFILE_INDEX; + + +AL_FUNC(DATAFILE *, load_datafile, (AL_CONST char *filename)); +AL_FUNC(DATAFILE *, load_datafile_callback, (AL_CONST char *filename, AL_METHOD(void, callback, (DATAFILE *)))); +AL_FUNC(DATAFILE_INDEX *, create_datafile_index, (AL_CONST char *filename)); +AL_FUNC(void, unload_datafile, (DATAFILE *dat)); +AL_FUNC(void, destroy_datafile_index, (DATAFILE_INDEX *index)); + +AL_FUNC(DATAFILE *, load_datafile_object, (AL_CONST char *filename, AL_CONST char *objectname)); +AL_FUNC(DATAFILE *, load_datafile_object_indexed, (AL_CONST DATAFILE_INDEX *index, int item)); +AL_FUNC(void, unload_datafile_object, (DATAFILE *dat)); + +AL_FUNC(DATAFILE *, find_datafile_object, (AL_CONST DATAFILE *dat, AL_CONST char *objectname)); +AL_FUNC(AL_CONST char *, get_datafile_property, (AL_CONST DATAFILE *dat, int type)); +AL_FUNC(void, register_datafile_object, (int id_, AL_METHOD(void *, load, (struct PACKFILE *f, long size)), AL_METHOD(void, destroy, (void *data)))); + +AL_FUNC(void, fixup_datafile, (DATAFILE *data)); + +AL_FUNC(struct BITMAP *, load_bitmap, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_bmp, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_bmp_pf, (PACKFILE *f, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_lbm, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_pcx, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_pcx_pf, (PACKFILE *f, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_tga, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_tga_pf, (PACKFILE *f, struct RGB *pal)); + +AL_FUNC(int, save_bitmap, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_bmp, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_bmp_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_pcx, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_pcx_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_tga, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_tga_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); + +AL_FUNC(void, register_bitmap_file_type, (AL_CONST char *ext, AL_METHOD(struct BITMAP *, load, (AL_CONST char *filename, struct RGB *pal)), AL_METHOD(int, save, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)))); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DATAFILE_H */ diff --git a/libsrc/allegro/include/allegro/debug.h b/libsrc/allegro/include/allegro/debug.h new file mode 100644 index 00000000000..80d4d76590c --- /dev/null +++ b/libsrc/allegro/include/allegro/debug.h @@ -0,0 +1,49 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Debug facilities. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DEBUG_H +#define ALLEGRO_DEBUG_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(void, al_assert, (AL_CONST char *file, int linenr)); +AL_PRINTFUNC(void, al_trace, (AL_CONST char *msg, ...), 1, 2); + +AL_FUNC(void, register_assert_handler, (AL_METHOD(int, handler, (AL_CONST char *msg)))); +AL_FUNC(void, register_trace_handler, (AL_METHOD(int, handler, (AL_CONST char *msg)))); + + +#ifdef DEBUGMODE + #define ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } + #define TRACE al_trace +#else + #define ASSERT(condition) + #define TRACE 1 ? (void) 0 : al_trace +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DEBUG_H */ + + diff --git a/libsrc/allegro/include/allegro/draw.h b/libsrc/allegro/include/allegro/draw.h new file mode 100644 index 00000000000..ef52a8a16fe --- /dev/null +++ b/libsrc/allegro/include/allegro/draw.h @@ -0,0 +1,91 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Drawing and sprite routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DRAW_H +#define ALLEGRO_DRAW_H + +#include "base.h" +#include "fixed.h" +#include "gfx.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define DRAW_MODE_SOLID 0 /* flags for drawing_mode() */ +#define DRAW_MODE_XOR 1 +#define DRAW_MODE_COPY_PATTERN 2 +#define DRAW_MODE_SOLID_PATTERN 3 +#define DRAW_MODE_MASKED_PATTERN 4 +#define DRAW_MODE_TRANS 5 + +AL_FUNC(void, drawing_mode, (int mode, struct BITMAP *pattern, int x_anchor, int y_anchor)); +AL_FUNC(void, xor_mode, (int on)); +AL_FUNC(void, solid_mode, (void)); +AL_FUNC(void, do_line, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_triangle, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color)); +AL_FUNC(void, _soft_polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); +AL_FUNC(void, _soft_rect, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, do_circle, (struct BITMAP *bmp, int x, int y, int radius, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); +AL_FUNC(void, _soft_circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); +AL_FUNC(void, do_ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); +AL_FUNC(void, _soft_ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); +AL_FUNC(void, do_arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); +AL_FUNC(void, calc_spline, (AL_CONST int points[8], int npts, int *x, int *y)); +AL_FUNC(void, _soft_spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); +AL_FUNC(void, _soft_floodfill, (struct BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, stretch_blit, (struct BITMAP *s, struct BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h)); +AL_FUNC(void, masked_stretch_blit, (struct BITMAP *s, struct BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h)); +AL_FUNC(void, stretch_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int w, int h)); +AL_FUNC(void, _soft_draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); + +/* rotate+trans */ +AL_FUNC(void, rotate_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle)); +AL_FUNC(void, rotate_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle)); +AL_FUNC(void, rotate_scaled_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale)); +AL_FUNC(void, rotate_scaled_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale)); +AL_FUNC(void, pivot_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle)); +AL_FUNC(void, pivot_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle)); +AL_FUNC(void, pivot_scaled_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale)); +AL_FUNC(void, pivot_scaled_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale)); +/* rotate+lit */ +AL_FUNC(void, rotate_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, int color)); +AL_FUNC(void, rotate_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, int color)); +AL_FUNC(void, rotate_scaled_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale, int color)); +AL_FUNC(void, rotate_scaled_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale, int color)); +AL_FUNC(void, pivot_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, int color)); +AL_FUNC(void, pivot_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, int color)); +AL_FUNC(void, pivot_scaled_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale, int color)); +AL_FUNC(void, pivot_scaled_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale, int color)); + + + +#ifdef __cplusplus + } +#endif + +#include "inline/draw.inl" + +#endif /* ifndef ALLEGRO_DRAW_H */ + + diff --git a/libsrc/allegro/include/allegro/file.h b/libsrc/allegro/include/allegro/file.h new file mode 100644 index 00000000000..70c306d288a --- /dev/null +++ b/libsrc/allegro/include/allegro/file.h @@ -0,0 +1,178 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * File I/O. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FILE_H +#define ALLEGRO_FILE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(char *, fix_filename_case, (char *path)); +AL_FUNC(char *, fix_filename_slashes, (char *path)); +AL_FUNC(char *, canonicalize_filename, (char *dest, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_absolute_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_relative_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(int, is_relative_filename, (AL_CONST char *filename)); +AL_FUNC(char *, replace_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, replace_extension, (char *dest, AL_CONST char *filename, AL_CONST char *ext, int size)); +AL_FUNC(char *, append_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, get_filename, (AL_CONST char *path)); +AL_FUNC(char *, get_extension, (AL_CONST char *filename)); +AL_FUNC(void, put_backslash, (char *filename)); +AL_FUNC(int, file_exists, (AL_CONST char *filename, int attrib, int *aret)); +AL_FUNC(int, exists, (AL_CONST char *filename)); +AL_FUNC(uint64_t, file_size_ex, (AL_CONST char *filename)); +AL_FUNC(time_t, file_time, (AL_CONST char *filename)); +AL_FUNC(int, delete_file, (AL_CONST char *filename)); +AL_FUNC(int, for_each_file_ex, (AL_CONST char *name, int in_attrib, int out_attrib, AL_METHOD(int, callback, (AL_CONST char *filename, int attrib, void *param)), void *param)); + +struct al_ffblk /* file info block for the al_find*() routines */ +{ + int attrib; /* actual attributes of the file found */ + time_t time; /* modification time of file */ + long size; /* size of file */ + char name[512]; /* name of file */ + void *ff_data; /* private hook */ +}; + +AL_FUNC(uint64_t, al_ffblk_get_size, (struct al_ffblk *info)); + +AL_FUNC(int, al_findfirst, (AL_CONST char *pattern, struct al_ffblk *info, int attrib)); +AL_FUNC(int, al_findnext, (struct al_ffblk *info)); +AL_FUNC(void, al_findclose, (struct al_ffblk *info)); + +#ifndef EOF + #define EOF (-1) +#endif + +#define F_READ "r" +#define F_WRITE "w" +#define F_READ_PACKED "rp" +#define F_WRITE_PACKED "wp" +#define F_WRITE_NOPACK "w!" + +#define F_BUF_SIZE 4096 /* 4K buffer for caching data */ +#define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ +#define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ +#define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ + +#define PACKFILE_FLAG_WRITE 1 /* the file is being written */ +#define PACKFILE_FLAG_PACK 2 /* data is compressed */ +#define PACKFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ +#define PACKFILE_FLAG_EOF 8 /* reached the end-of-file */ +#define PACKFILE_FLAG_ERROR 16 /* an error has occurred */ +#define PACKFILE_FLAG_OLD_CRYPT 32 /* backward compatibility mode */ +#define PACKFILE_FLAG_EXEDAT 64 /* reading from our executable */ + + +typedef struct PACKFILE_VTABLE PACKFILE_VTABLE; +typedef struct PACKFILE PACKFILE; + +struct LZSS_PACK_DATA; +struct LZSS_UNPACK_DATA; + + +struct _al_normal_packfile_details +{ + int hndl; /* DOS file handle */ + int flags; /* PACKFILE_FLAG_* constants */ + unsigned char *buf_pos; /* position in buffer */ + int buf_size; /* number of bytes in the buffer */ + long todo; /* number of bytes still on the disk */ + struct PACKFILE *parent; /* nested, parent file */ + struct LZSS_PACK_DATA *pack_data; /* for LZSS compression */ + struct LZSS_UNPACK_DATA *unpack_data; /* for LZSS decompression */ + char *filename; /* name of the file */ + char *passdata; /* encryption key data */ + char *passpos; /* current key position */ + unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ +}; + + +struct PACKFILE /* our very own FILE structure... */ +{ + AL_CONST PACKFILE_VTABLE *vtable; + void *userdata; + int is_normal_packfile; + + /* The following is only to be used for the "normal" PACKFILE vtable, + * i.e. what is implemented by Allegro itself. If is_normal_packfile is + * false then the following is not even allocated. This must be the last + * member in the structure. + */ + struct _al_normal_packfile_details normal; +}; + + +struct PACKFILE_VTABLE +{ + AL_METHOD(int, pf_fclose, (void *userdata)); + AL_METHOD(int, pf_getc, (void *userdata)); + AL_METHOD(int, pf_ungetc, (int c, void *userdata)); + AL_METHOD(long, pf_fread, (void *p, long n, void *userdata)); + AL_METHOD(int, pf_putc, (int c, void *userdata)); + AL_METHOD(long, pf_fwrite, (AL_CONST void *p, long n, void *userdata)); + AL_METHOD(int, pf_fseek, (void *userdata, int offset)); + AL_METHOD(int, pf_feof, (void *userdata)); + AL_METHOD(int, pf_ferror, (void *userdata)); +}; + + +#define uconvert_tofilename(s, buf) uconvert(s, U_CURRENT, buf, get_filename_encoding(), sizeof(buf)) + +AL_FUNC(void, set_filename_encoding, (int encoding)); +AL_FUNC(int, get_filename_encoding, (void)); + +AL_FUNC(void, packfile_password, (AL_CONST char *password)); +AL_FUNC(PACKFILE *, pack_fopen, (AL_CONST char *filename, AL_CONST char *mode)); +AL_FUNC(PACKFILE *, pack_fopen_vtable, (AL_CONST PACKFILE_VTABLE *vtable, void *userdata)); +AL_FUNC(int, pack_fclose, (PACKFILE *f)); +AL_FUNC(int, pack_fseek, (PACKFILE *f, int offset)); +AL_FUNC(PACKFILE *, pack_fopen_chunk, (PACKFILE *f, int pack)); +AL_FUNC(PACKFILE *, pack_fclose_chunk, (PACKFILE *f)); +AL_FUNC(int, pack_getc, (PACKFILE *f)); +AL_FUNC(int, pack_putc, (int c, PACKFILE *f)); +AL_FUNC(int, pack_feof, (PACKFILE *f)); +AL_FUNC(int, pack_ferror, (PACKFILE *f)); +AL_FUNC(int, pack_igetw, (PACKFILE *f)); +AL_FUNC(long, pack_igetl, (PACKFILE *f)); +AL_FUNC(int, pack_iputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_iputl, (long l, PACKFILE *f)); +AL_FUNC(int, pack_mgetw, (PACKFILE *f)); +AL_FUNC(long, pack_mgetl, (PACKFILE *f)); +AL_FUNC(int, pack_mputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_mputl, (long l, PACKFILE *f)); +AL_FUNC(long, pack_fread, (void *p, long n, PACKFILE *f)); +AL_FUNC(long, pack_fwrite, (AL_CONST void *p, long n, PACKFILE *f)); +AL_FUNC(int, pack_ungetc, (int c, PACKFILE *f)); +AL_FUNC(char *, pack_fgets, (char *p, int max, PACKFILE *f)); +AL_FUNC(int, pack_fputs, (AL_CONST char *p, PACKFILE *f)); +AL_FUNC(void *, pack_get_userdata, (PACKFILE *f)); + + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FILE_H */ + + diff --git a/libsrc/allegro/include/allegro/fixed.h b/libsrc/allegro/include/allegro/fixed.h new file mode 100644 index 00000000000..8504100a33f --- /dev/null +++ b/libsrc/allegro/include/allegro/fixed.h @@ -0,0 +1,39 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point type. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FIXED_H +#define ALLEGRO_FIXED_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef int32_t fixed; + +AL_VAR(AL_CONST fixed, fixtorad_r); +AL_VAR(AL_CONST fixed, radtofix_r); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FIXED_H */ + + diff --git a/libsrc/allegro/include/allegro/fli.h b/libsrc/allegro/include/allegro/fli.h new file mode 100644 index 00000000000..5760789ffd3 --- /dev/null +++ b/libsrc/allegro/include/allegro/fli.h @@ -0,0 +1,62 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * FLI/FLC routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FLI_H +#define ALLEGRO_FLI_H + +#include "base.h" +#include "file.h" +#include "palette.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +#define FLI_OK 0 /* FLI player return values */ +#define FLI_EOF -1 +#define FLI_ERROR -2 +#define FLI_NOT_OPEN -3 + +AL_FUNC(int, open_fli, (AL_CONST char *filename)); +AL_FUNC(int, open_fli_pf, (PACKFILE *pf)); +AL_FUNC(int, open_memory_fli, (void *fli_data)); +AL_FUNC(void, close_fli, (void)); +AL_FUNC(int, next_fli_frame, (int loop)); +AL_FUNC(void, reset_fli_variables, (void)); + +AL_VAR(struct BITMAP *, fli_bitmap); /* current frame of the FLI */ +AL_VAR(PALETTE, fli_palette); /* current FLI palette */ + +AL_VAR(int, fli_bmp_dirty_from); /* what part of fli_bitmap is dirty */ +AL_VAR(int, fli_bmp_dirty_to); +AL_VAR(int, fli_pal_dirty_from); /* what part of fli_palette is dirty */ +AL_VAR(int, fli_pal_dirty_to); + +AL_VAR(int, fli_frame); /* current frame number */ + +AL_VAR(volatile int, fli_timer); /* for timing FLI playback */ + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FLI_H */ + + diff --git a/libsrc/allegro/include/allegro/fmaths.h b/libsrc/allegro/include/allegro/fmaths.h new file mode 100644 index 00000000000..853b288a17f --- /dev/null +++ b/libsrc/allegro/include/allegro/fmaths.h @@ -0,0 +1,46 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point math routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FMATH_H +#define ALLEGRO_FMATH_H + +#include "base.h" +#include "fixed.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(fixed, fixsqrt, (fixed x)); +AL_FUNC(fixed, fixhypot, (fixed x, fixed y)); +AL_FUNC(fixed, fixatan, (fixed x)); +AL_FUNC(fixed, fixatan2, (fixed y, fixed x)); + +AL_ARRAY(fixed, _cos_tbl); +AL_ARRAY(fixed, _tan_tbl); +AL_ARRAY(fixed, _acos_tbl); + +#ifdef __cplusplus + } +#endif + +#include "inline/fmaths.inl" + +#endif /* ifndef ALLEGRO_FMATH_H */ + + diff --git a/libsrc/allegro/include/allegro/gfx.h b/libsrc/allegro/include/allegro/gfx.h new file mode 100644 index 00000000000..48192feec9d --- /dev/null +++ b/libsrc/allegro/include/allegro/gfx.h @@ -0,0 +1,312 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Basic graphics support routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GFX_H +#define ALLEGRO_GFX_H + +#include "base.h" +#include "fixed.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct RLE_SPRITE; +struct FONT_GLYPH; +struct RGB; + +/* drawing modes for draw_sprite_ex() */ +#define DRAW_SPRITE_NORMAL 0 +#define DRAW_SPRITE_LIT 1 +#define DRAW_SPRITE_TRANS 2 + +/* flipping modes for draw_sprite_ex() */ +#define DRAW_SPRITE_NO_FLIP 0x0 +#define DRAW_SPRITE_H_FLIP 0x1 +#define DRAW_SPRITE_V_FLIP 0x2 +#define DRAW_SPRITE_VH_FLIP 0x3 + +/* Blender mode defines, for the gfx_driver->set_blender_mode() function */ +#define blender_mode_none 0 +#define blender_mode_trans 1 +#define blender_mode_add 2 +#define blender_mode_burn 3 +#define blender_mode_color 4 +#define blender_mode_difference 5 +#define blender_mode_dissolve 6 +#define blender_mode_dodge 7 +#define blender_mode_hue 8 +#define blender_mode_invert 9 +#define blender_mode_luminance 10 +#define blender_mode_multiply 11 +#define blender_mode_saturation 12 +#define blender_mode_screen 13 +#define blender_mode_alpha 14 + + + +typedef struct GFX_VTABLE /* functions for drawing onto bitmaps */ +{ + int color_depth; + int mask_color; + void *unwrite_bank; /* C function on some machines, asm on i386 */ + AL_METHOD(void, set_clip, (struct BITMAP *bmp)); + AL_METHOD(void, acquire, (struct BITMAP *bmp)); + AL_METHOD(void, release, (struct BITMAP *bmp)); + AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); + AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); + AL_METHOD(int, getpixel, (struct BITMAP *bmp, int x, int y)); + AL_METHOD(void, putpixel, (struct BITMAP *bmp, int x, int y, int color)); + AL_METHOD(void, vline, (struct BITMAP *bmp, int x, int y_1, int y2, int color)); + AL_METHOD(void, hline, (struct BITMAP *bmp, int x1, int y, int x2, int color)); + AL_METHOD(void, hfill, (struct BITMAP *bmp, int x1, int y, int x2, int color)); + AL_METHOD(void, line, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, fastline, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, rectfill, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, triangle, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color)); + AL_METHOD(void, draw_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_256_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_sprite_v_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_sprite_h_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_sprite_vh_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_trans_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_trans_rgba_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color)); + AL_METHOD(void, draw_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); + AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); + AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); + AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); + AL_METHOD(void, draw_character, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)); + AL_METHOD(void, draw_glyph, (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg)); + AL_METHOD(void, blit_from_memory, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_memory, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_self, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_self_forward, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_self_backward, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_between_formats, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, clear_to_color, (struct BITMAP *bitmap, int color)); + AL_METHOD(void, pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); + AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)); + AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); + AL_METHOD(void, draw_sprite_end, (void)); + AL_METHOD(void, blit_end, (void)); + AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); + AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); + AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); + AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); + AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); + AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); + AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); + AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color)); + AL_METHOD(void, __reserved1_, (struct BITMAP *bmp)); + AL_METHOD(void, __reserved2_, (struct BITMAP *bmp)); + AL_METHOD(void, __reserved3_, (struct BITMAP *bmp)); + AL_METHOD(void, __reserved4_, (struct BITMAP *bmp)); + AL_METHOD(void, __reserved5_, (struct BITMAP *bmp)); + AL_METHOD(void, __reserved6_, (struct BITMAP *bmp)); + + AL_METHOD(void, draw_sprite_ex, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int mode, int flip )); +} GFX_VTABLE; + + +AL_VAR(GFX_VTABLE, __linear_vtable8); +AL_VAR(GFX_VTABLE, __linear_vtable15); +AL_VAR(GFX_VTABLE, __linear_vtable16); +AL_VAR(GFX_VTABLE, __linear_vtable24); +AL_VAR(GFX_VTABLE, __linear_vtable32); + + +typedef struct _VTABLE_INFO +{ + int color_depth; + GFX_VTABLE *vtable; +} _VTABLE_INFO; + +AL_ARRAY(_VTABLE_INFO, _vtable_list); + + +/* macros for constructing the vtable list */ +#define BEGIN_COLOR_DEPTH_LIST \ + _VTABLE_INFO _vtable_list[] = \ + { + +#define END_COLOR_DEPTH_LIST \ + { 0, NULL } \ + }; + +#define COLOR_DEPTH_8 \ + { 8, &__linear_vtable8 }, + +#define COLOR_DEPTH_15 \ + { 15, &__linear_vtable15 }, + +#define COLOR_DEPTH_16 \ + { 16, &__linear_vtable16 }, + +#define COLOR_DEPTH_24 \ + { 24, &__linear_vtable24 }, + +#define COLOR_DEPTH_32 \ + { 32, &__linear_vtable32 }, + + +typedef struct BITMAP /* a bitmap structure */ +{ + int w, h; /* width and height in pixels */ + int clip; /* flag if clipping is turned on */ + int cl, cr, ct, cb; /* clip left, right, top and bottom values */ + GFX_VTABLE *vtable; /* drawing functions */ + void *write_bank; /* C func on some machines, asm on i386 */ + void *read_bank; /* C func on some machines, asm on i386 */ + void *dat; /* the memory we allocated for the bitmap */ + unsigned long id; /* for identifying sub-bitmaps */ + void *extra; /* points to a structure with more info */ + int x_ofs; /* horizontal offset (for sub-bitmaps) */ + int y_ofs; /* vertical offset (for sub-bitmaps) */ + int seg; /* bitmap segment */ + ZERO_SIZE_ARRAY(unsigned char *, line); +} BITMAP; + + +#define BMP_ID_SUB 0x20000000 +#define BMP_ID_NOBLIT 0x08000000 +#define BMP_ID_LOCKED 0x04000000 +#define BMP_ID_AUTOLOCK 0x02000000 +#define BMP_ID_MASK 0x01FFFFFF + +#define COLORCONV_NONE 0 + +#define COLORCONV_8_TO_15 1 +#define COLORCONV_8_TO_16 2 +#define COLORCONV_8_TO_24 4 +#define COLORCONV_8_TO_32 8 + +#define COLORCONV_15_TO_8 0x10 +#define COLORCONV_15_TO_16 0x20 +#define COLORCONV_15_TO_24 0x40 +#define COLORCONV_15_TO_32 0x80 + +#define COLORCONV_16_TO_8 0x100 +#define COLORCONV_16_TO_15 0x200 +#define COLORCONV_16_TO_24 0x400 +#define COLORCONV_16_TO_32 0x800 + +#define COLORCONV_24_TO_8 0x1000 +#define COLORCONV_24_TO_15 0x2000 +#define COLORCONV_24_TO_16 0x4000 +#define COLORCONV_24_TO_32 0x8000 + +#define COLORCONV_32_TO_8 0x10000 +#define COLORCONV_32_TO_15 0x20000 +#define COLORCONV_32_TO_16 0x40000 +#define COLORCONV_32_TO_24 0x80000 + +#define COLORCONV_32A_TO_8 0x100000 +#define COLORCONV_32A_TO_15 0x200000 +#define COLORCONV_32A_TO_16 0x400000 +#define COLORCONV_32A_TO_24 0x800000 + +#define COLORCONV_DITHER_PAL 0x1000000 +#define COLORCONV_DITHER_HI 0x2000000 +#define COLORCONV_KEEP_TRANS 0x4000000 + +#define COLORCONV_DITHER (COLORCONV_DITHER_PAL | \ + COLORCONV_DITHER_HI) + +#define COLORCONV_EXPAND_256 (COLORCONV_8_TO_15 | \ + COLORCONV_8_TO_16 | \ + COLORCONV_8_TO_24 | \ + COLORCONV_8_TO_32) + +#define COLORCONV_REDUCE_TO_256 (COLORCONV_15_TO_8 | \ + COLORCONV_16_TO_8 | \ + COLORCONV_24_TO_8 | \ + COLORCONV_32_TO_8 | \ + COLORCONV_32A_TO_8) + +#define COLORCONV_EXPAND_15_TO_16 COLORCONV_15_TO_16 + +#define COLORCONV_REDUCE_16_TO_15 COLORCONV_16_TO_15 + +#define COLORCONV_EXPAND_HI_TO_TRUE (COLORCONV_15_TO_24 | \ + COLORCONV_15_TO_32 | \ + COLORCONV_16_TO_24 | \ + COLORCONV_16_TO_32) + +#define COLORCONV_REDUCE_TRUE_TO_HI (COLORCONV_24_TO_15 | \ + COLORCONV_24_TO_16 | \ + COLORCONV_32_TO_15 | \ + COLORCONV_32_TO_16) + +#define COLORCONV_24_EQUALS_32 (COLORCONV_24_TO_32 | \ + COLORCONV_32_TO_24) + +#define COLORCONV_TOTAL (COLORCONV_EXPAND_256 | \ + COLORCONV_REDUCE_TO_256 | \ + COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_EXPAND_HI_TO_TRUE | \ + COLORCONV_REDUCE_TRUE_TO_HI | \ + COLORCONV_24_EQUALS_32 | \ + COLORCONV_32A_TO_15 | \ + COLORCONV_32A_TO_16 | \ + COLORCONV_32A_TO_24) + +#define COLORCONV_PARTIAL (COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_24_EQUALS_32) + +#define COLORCONV_MOST (COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_EXPAND_HI_TO_TRUE | \ + COLORCONV_REDUCE_TRUE_TO_HI | \ + COLORCONV_24_EQUALS_32) + +#define COLORCONV_KEEP_ALPHA (COLORCONV_TOTAL \ + & ~(COLORCONV_32A_TO_8 | \ + COLORCONV_32A_TO_15 | \ + COLORCONV_32A_TO_16 | \ + COLORCONV_32A_TO_24)) + +AL_FUNC(void, set_color_depth, (int depth)); +AL_FUNC(int, get_color_depth, (void)); +AL_FUNC(void, set_color_conversion, (int mode)); +AL_FUNC(int, get_color_conversion, (void)); +AL_FUNC(BITMAP *, create_bitmap, (int width, int height)); +AL_FUNC(BITMAP *, create_bitmap_ex, (int color_depth, int width, int height)); +AL_FUNC(BITMAP *, create_sub_bitmap, (BITMAP *parent, int x, int y, int width, int height)); +AL_FUNC(void, destroy_bitmap, (BITMAP *bitmap)); +AL_FUNC(void, set_clip_rect, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); +AL_FUNC(void, add_clip_rect, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); +AL_FUNC(void, clear_bitmap, (BITMAP *bitmap)); + +AL_FUNC(void, lock_bitmap, (struct BITMAP *bmp)); + +#ifdef __cplusplus + } +#endif + +#include "inline/gfx.inl" + +#endif /* ifndef ALLEGRO_GFX_H */ + + diff --git a/libsrc/allegro/include/allegro/inline/color.inl b/libsrc/allegro/include/allegro/inline/color.inl new file mode 100644 index 00000000000..341f329d208 --- /dev/null +++ b/libsrc/allegro/include/allegro/inline/color.inl @@ -0,0 +1,179 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Color inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_COLOR_INL +#define ALLEGRO_COLOR_INL + +#ifdef __cplusplus + extern "C" { +#endif + +AL_INLINE(int, makecol15, (int r, int g, int b), +{ + return (((r >> 3) << _rgb_r_shift_15) | + ((g >> 3) << _rgb_g_shift_15) | + ((b >> 3) << _rgb_b_shift_15)); +}) + + +AL_INLINE(int, makecol16, (int r, int g, int b), +{ + return (((r >> 3) << _rgb_r_shift_16) | + ((g >> 2) << _rgb_g_shift_16) | + ((b >> 3) << _rgb_b_shift_16)); +}) + + +AL_INLINE(int, makecol24, (int r, int g, int b), +{ + return ((r << _rgb_r_shift_24) | + (g << _rgb_g_shift_24) | + (b << _rgb_b_shift_24)); +}) + + +AL_INLINE(int, makecol32, (int r, int g, int b), +{ + return ((r << _rgb_r_shift_32) | + (g << _rgb_g_shift_32) | + (b << _rgb_b_shift_32)); +}) + + +AL_INLINE(int, makeacol32, (int r, int g, int b, int a), +{ + return ((r << _rgb_r_shift_32) | + (g << _rgb_g_shift_32) | + (b << _rgb_b_shift_32) | + (a << _rgb_a_shift_32)); +}) + + +AL_INLINE(int, getr8, (int c), +{ + return _rgb_scale_6[(int)_current_palette[c].r]; +}) + + +AL_INLINE(int, getg8, (int c), +{ + return _rgb_scale_6[(int)_current_palette[c].g]; +}) + + +AL_INLINE(int, getb8, (int c), +{ + return _rgb_scale_6[(int)_current_palette[c].b]; +}) + + +AL_INLINE(int, getr15, (int c), +{ + return _rgb_scale_5[(c >> _rgb_r_shift_15) & 0x1F]; +}) + + +AL_INLINE(int, getg15, (int c), +{ + return _rgb_scale_5[(c >> _rgb_g_shift_15) & 0x1F]; +}) + + +AL_INLINE(int, getb15, (int c), +{ + return _rgb_scale_5[(c >> _rgb_b_shift_15) & 0x1F]; +}) + + +AL_INLINE(int, getr16, (int c), +{ + return _rgb_scale_5[(c >> _rgb_r_shift_16) & 0x1F]; +}) + + +AL_INLINE(int, getg16, (int c), +{ + return _rgb_scale_6[(c >> _rgb_g_shift_16) & 0x3F]; +}) + + +AL_INLINE(int, getb16, (int c), +{ + return _rgb_scale_5[(c >> _rgb_b_shift_16) & 0x1F]; +}) + + +AL_INLINE(int, getr24, (int c), +{ + return ((c >> _rgb_r_shift_24) & 0xFF); +}) + + +AL_INLINE(int, getg24, (int c), +{ + return ((c >> _rgb_g_shift_24) & 0xFF); +}) + + +AL_INLINE(int, getb24, (int c), +{ + return ((c >> _rgb_b_shift_24) & 0xFF); +}) + + +AL_INLINE(int, getr32, (int c), +{ + return ((c >> _rgb_r_shift_32) & 0xFF); +}) + + +AL_INLINE(int, getg32, (int c), +{ + return ((c >> _rgb_g_shift_32) & 0xFF); +}) + + +AL_INLINE(int, getb32, (int c), +{ + return ((c >> _rgb_b_shift_32) & 0xFF); +}) + + +AL_INLINE(int, geta32, (int c), +{ + return ((c >> _rgb_a_shift_32) & 0xFF); +}) + + +#ifndef ALLEGRO_DOS + +AL_INLINE(void, _set_color, (int idx, AL_CONST RGB *p), +{ + set_color(idx, p); +}) + +#endif + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_COLOR_INL */ + + diff --git a/libsrc/allegro/include/allegro/inline/draw.inl b/libsrc/allegro/include/allegro/inline/draw.inl new file mode 100644 index 00000000000..319d1f5cf42 --- /dev/null +++ b/libsrc/allegro/include/allegro/inline/draw.inl @@ -0,0 +1,408 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Draw inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DRAW_INL +#define ALLEGRO_DRAW_INL + +#include "allegro/debug.h" +#include "gfx.inl" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_INLINE(int, getpixel, (BITMAP *bmp, int x, int y), +{ + ASSERT(bmp); + + return bmp->vtable->getpixel(bmp, x, y); +}) + + +AL_INLINE(void, putpixel, (BITMAP *bmp, int x, int y, int color), +{ + ASSERT(bmp); + + bmp->vtable->putpixel(bmp, x, y, color); +}) + + +AL_INLINE(void, _allegro_vline, (BITMAP *bmp, int x, int y_1, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->vline(bmp, x, y_1, y2, color); +}) + + +AL_INLINE(void, _allegro_hline, (BITMAP *bmp, int x1, int y, int x2, int color), +{ + ASSERT(bmp); + + bmp->vtable->hline(bmp, x1, y, x2, color); +}) + + +/* The curses API also contains functions called vline and hline so we have + * called our functions _allegro_vline and _allegro_hline. User programs + * should use the vline/hline aliases as they are the official names. + */ +#ifndef ALLEGRO_NO_VHLINE_ALIAS + AL_ALIAS_VOID_RET(vline(BITMAP *bmp, int x, int y_1, int y2, int color), _allegro_vline(bmp, x, y_1, y2, color)) + AL_ALIAS_VOID_RET(hline(BITMAP *bmp, int x1, int y, int x2, int color), _allegro_hline(bmp, x1, y, x2, color)) +#endif + + +AL_INLINE(void, line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->line(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->rectfill(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, triangle, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color), +{ + ASSERT(bmp); + + bmp->vtable->triangle(bmp, x1, y_1, x2, y2, x3, y3, color); +}) + + +AL_INLINE(void, polygon, (BITMAP *bmp, int vertices, AL_CONST int *points, int color), +{ + ASSERT(bmp); + + bmp->vtable->polygon(bmp, vertices, points, color); +}) + + +AL_INLINE(void, rect, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->rect(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, circlefill, (BITMAP *bmp, int x, int y, int radius, int color), +{ + ASSERT(bmp); + + bmp->vtable->circlefill(bmp, x, y, radius, color); +}) + + +AL_INLINE(void, floodfill, (BITMAP *bmp, int x, int y, int color), +{ + ASSERT(bmp); + + bmp->vtable->floodfill(bmp, x, y, color); +}) + + +AL_INLINE(void, draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + + if (sprite->vtable->color_depth == 8) { + bmp->vtable->draw_256_sprite(bmp, sprite, x, y); + } + else { + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + bmp->vtable->draw_sprite(bmp, sprite, x, y); + } +}) + +AL_INLINE(void, draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y),{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_sprite_v_flip(bmp, sprite, x, y); +}) + +AL_INLINE(void, draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y),{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_sprite_h_flip(bmp, sprite, x, y); +}) + +AL_INLINE(void, draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_sprite_vh_flip(bmp, sprite, x, y); +}) + +AL_INLINE(void, draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + + if (sprite->vtable->color_depth == 32) { + ASSERT(bmp->vtable->draw_trans_rgba_sprite); + bmp->vtable->draw_trans_rgba_sprite(bmp, sprite, x, y); + } + else { + ASSERT((bmp->vtable->color_depth == sprite->vtable->color_depth) || + ((bmp->vtable->color_depth == 32) && + (sprite->vtable->color_depth == 8))); + bmp->vtable->draw_trans_sprite(bmp, sprite, x, y); + } +}) + + +AL_INLINE(void, draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_lit_sprite(bmp, sprite, x, y, color); +}) + + +AL_INLINE(void, rotate_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, + (y<<16) + (sprite->h * 0x10000) / 2, + sprite->w << 15, sprite->h << 15, + angle, 0x10000, FALSE); +}) + + +AL_INLINE(void, rotate_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, + (y<<16) + (sprite->h * 0x10000) / 2, + sprite->w << 15, sprite->h << 15, + angle, 0x10000, TRUE); +}) + + +AL_INLINE(void, rotate_scaled_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, + (y<<16) + (sprite->h * scale) / 2, + sprite->w << 15, sprite->h << 15, + angle, scale, FALSE); +}) + + +AL_INLINE(void, rotate_scaled_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, + (y<<16) + (sprite->h * scale) / 2, + sprite->w << 15, sprite->h << 15, + angle, scale, TRUE); +}) + + +AL_INLINE(void, pivot_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, FALSE); +}) + + +AL_INLINE(void, pivot_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, TRUE); +}) + + +AL_INLINE(void, pivot_scaled_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, FALSE); +}) + + +AL_INLINE(void, pivot_scaled_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, TRUE); +}) + + +AL_INLINE(void, _putpixel, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write8(addr+x, color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read8(addr+x); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel15, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write15(addr+x*sizeof(short), color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel15, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read15(addr+x*sizeof(short)); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel16, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write16(addr+x*sizeof(short), color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel16, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read16(addr+x*sizeof(short)); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel24, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write24(addr+x*3, color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel24, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read24(addr+x*3); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel32, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write32(addr+x*sizeof(int32_t), color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel32, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read32(addr+x*sizeof(int32_t)); + bmp_unwrite_line(bmp); + + return c; +}) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DRAW_INL */ + + diff --git a/libsrc/allegro/include/allegro/inline/fix.inl b/libsrc/allegro/include/allegro/inline/fix.inl new file mode 100644 index 00000000000..68620801655 --- /dev/null +++ b/libsrc/allegro/include/allegro/inline/fix.inl @@ -0,0 +1,254 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fix class inline functions. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FIX_INL +#define ALLEGRO_FIX_INL + +#ifdef __cplusplus + + +inline fix operator + (const fix x, const fix y) { fix t; t.v = x.v + y.v; return t; } +inline fix operator + (const fix x, const int y) { fix t; t.v = x.v + itofix(y); return t; } +inline fix operator + (const int x, const fix y) { fix t; t.v = itofix(x) + y.v; return t; } +inline fix operator + (const fix x, const long y) { fix t; t.v = x.v + itofix(y); return t; } +inline fix operator + (const long x, const fix y) { fix t; t.v = itofix(x) + y.v; return t; } +inline fix operator + (const fix x, const float y) { fix t; t.v = x.v + ftofix(y); return t; } +inline fix operator + (const float x, const fix y) { fix t; t.v = ftofix(x) + y.v; return t; } +inline fix operator + (const fix x, const double y) { fix t; t.v = x.v + ftofix(y); return t; } +inline fix operator + (const double x, const fix y) { fix t; t.v = ftofix(x) + y.v; return t; } + +inline fix operator - (const fix x, const fix y) { fix t; t.v = x.v - y.v; return t; } +inline fix operator - (const fix x, const int y) { fix t; t.v = x.v - itofix(y); return t; } +inline fix operator - (const int x, const fix y) { fix t; t.v = itofix(x) - y.v; return t; } +inline fix operator - (const fix x, const long y) { fix t; t.v = x.v - itofix(y); return t; } +inline fix operator - (const long x, const fix y) { fix t; t.v = itofix(x) - y.v; return t; } +inline fix operator - (const fix x, const float y) { fix t; t.v = x.v - ftofix(y); return t; } +inline fix operator - (const float x, const fix y) { fix t; t.v = ftofix(x) - y.v; return t; } +inline fix operator - (const fix x, const double y) { fix t; t.v = x.v - ftofix(y); return t; } +inline fix operator - (const double x, const fix y) { fix t; t.v = ftofix(x) - y.v; return t; } + +inline fix operator * (const fix x, const fix y) { fix t; t.v = fixmul(x.v, y.v); return t; } +inline fix operator * (const fix x, const int y) { fix t; t.v = x.v * y; return t; } +inline fix operator * (const int x, const fix y) { fix t; t.v = x * y.v; return t; } +inline fix operator * (const fix x, const long y) { fix t; t.v = x.v * y; return t; } +inline fix operator * (const long x, const fix y) { fix t; t.v = x * y.v; return t; } +inline fix operator * (const fix x, const float y) { fix t; t.v = ftofix(fixtof(x.v) * y); return t; } +inline fix operator * (const float x, const fix y) { fix t; t.v = ftofix(x * fixtof(y.v)); return t; } +inline fix operator * (const fix x, const double y) { fix t; t.v = ftofix(fixtof(x.v) * y); return t; } +inline fix operator * (const double x, const fix y) { fix t; t.v = ftofix(x * fixtof(y.v)); return t; } + +inline fix operator / (const fix x, const fix y) { fix t; t.v = fixdiv(x.v, y.v); return t; } +inline fix operator / (const fix x, const int y) { fix t; t.v = x.v / y; return t; } +inline fix operator / (const int x, const fix y) { fix t; t.v = fixdiv(itofix(x), y.v); return t; } +inline fix operator / (const fix x, const long y) { fix t; t.v = x.v / y; return t; } +inline fix operator / (const long x, const fix y) { fix t; t.v = fixdiv(itofix(x), y.v); return t; } +inline fix operator / (const fix x, const float y) { fix t; t.v = ftofix(fixtof(x.v) / y); return t; } +inline fix operator / (const float x, const fix y) { fix t; t.v = ftofix(x / fixtof(y.v)); return t; } +inline fix operator / (const fix x, const double y) { fix t; t.v = ftofix(fixtof(x.v) / y); return t; } +inline fix operator / (const double x, const fix y) { fix t; t.v = ftofix(x / fixtof(y.v)); return t; } + +inline fix operator << (const fix x, const int y) { fix t; t.v = x.v << y; return t; } +inline fix operator >> (const fix x, const int y) { fix t; t.v = x.v >> y; return t; } + +inline int operator == (const fix x, const fix y) { return (x.v == y.v); } +inline int operator == (const fix x, const int y) { return (x.v == itofix(y)); } +inline int operator == (const int x, const fix y) { return (itofix(x) == y.v); } +inline int operator == (const fix x, const long y) { return (x.v == itofix(y)); } +inline int operator == (const long x, const fix y) { return (itofix(x) == y.v); } +inline int operator == (const fix x, const float y) { return (x.v == ftofix(y)); } +inline int operator == (const float x, const fix y) { return (ftofix(x) == y.v); } +inline int operator == (const fix x, const double y) { return (x.v == ftofix(y)); } +inline int operator == (const double x, const fix y) { return (ftofix(x) == y.v); } + +inline int operator != (const fix x, const fix y) { return (x.v != y.v); } +inline int operator != (const fix x, const int y) { return (x.v != itofix(y)); } +inline int operator != (const int x, const fix y) { return (itofix(x) != y.v); } +inline int operator != (const fix x, const long y) { return (x.v != itofix(y)); } +inline int operator != (const long x, const fix y) { return (itofix(x) != y.v); } +inline int operator != (const fix x, const float y) { return (x.v != ftofix(y)); } +inline int operator != (const float x, const fix y) { return (ftofix(x) != y.v); } +inline int operator != (const fix x, const double y) { return (x.v != ftofix(y)); } +inline int operator != (const double x, const fix y) { return (ftofix(x) != y.v); } + +inline int operator < (const fix x, const fix y) { return (x.v < y.v); } +inline int operator < (const fix x, const int y) { return (x.v < itofix(y)); } +inline int operator < (const int x, const fix y) { return (itofix(x) < y.v); } +inline int operator < (const fix x, const long y) { return (x.v < itofix(y)); } +inline int operator < (const long x, const fix y) { return (itofix(x) < y.v); } +inline int operator < (const fix x, const float y) { return (x.v < ftofix(y)); } +inline int operator < (const float x, const fix y) { return (ftofix(x) < y.v); } +inline int operator < (const fix x, const double y) { return (x.v < ftofix(y)); } +inline int operator < (const double x, const fix y) { return (ftofix(x) < y.v); } + +inline int operator > (const fix x, const fix y) { return (x.v > y.v); } +inline int operator > (const fix x, const int y) { return (x.v > itofix(y)); } +inline int operator > (const int x, const fix y) { return (itofix(x) > y.v); } +inline int operator > (const fix x, const long y) { return (x.v > itofix(y)); } +inline int operator > (const long x, const fix y) { return (itofix(x) > y.v); } +inline int operator > (const fix x, const float y) { return (x.v > ftofix(y)); } +inline int operator > (const float x, const fix y) { return (ftofix(x) > y.v); } +inline int operator > (const fix x, const double y) { return (x.v > ftofix(y)); } +inline int operator > (const double x, const fix y) { return (ftofix(x) > y.v); } + +inline int operator <= (const fix x, const fix y) { return (x.v <= y.v); } +inline int operator <= (const fix x, const int y) { return (x.v <= itofix(y)); } +inline int operator <= (const int x, const fix y) { return (itofix(x) <= y.v); } +inline int operator <= (const fix x, const long y) { return (x.v <= itofix(y)); } +inline int operator <= (const long x, const fix y) { return (itofix(x) <= y.v); } +inline int operator <= (const fix x, const float y) { return (x.v <= ftofix(y)); } +inline int operator <= (const float x, const fix y) { return (ftofix(x) <= y.v); } +inline int operator <= (const fix x, const double y) { return (x.v <= ftofix(y)); } +inline int operator <= (const double x, const fix y) { return (ftofix(x) <= y.v); } + +inline int operator >= (const fix x, const fix y) { return (x.v >= y.v); } +inline int operator >= (const fix x, const int y) { return (x.v >= itofix(y)); } +inline int operator >= (const int x, const fix y) { return (itofix(x) >= y.v); } +inline int operator >= (const fix x, const long y) { return (x.v >= itofix(y)); } +inline int operator >= (const long x, const fix y) { return (itofix(x) >= y.v); } +inline int operator >= (const fix x, const float y) { return (x.v >= ftofix(y)); } +inline int operator >= (const float x, const fix y) { return (ftofix(x) >= y.v); } +inline int operator >= (const fix x, const double y) { return (x.v >= ftofix(y)); } +inline int operator >= (const double x, const fix y) { return (ftofix(x) >= y.v); } + +inline fix sqrt(fix x) { fix t; t.v = fixsqrt(x.v); return t; } +inline fix cos(fix x) { fix t; t.v = fixcos(x.v); return t; } +inline fix sin(fix x) { fix t; t.v = fixsin(x.v); return t; } +inline fix tan(fix x) { fix t; t.v = fixtan(x.v); return t; } +inline fix acos(fix x) { fix t; t.v = fixacos(x.v); return t; } +inline fix asin(fix x) { fix t; t.v = fixasin(x.v); return t; } +inline fix atan(fix x) { fix t; t.v = fixatan(x.v); return t; } +inline fix atan2(fix x, fix y) { fix t; t.v = fixatan2(x.v, y.v); return t; } + + +inline void get_translation_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_translation_matrix(m, x.v, y.v, z.v); +} + + +inline void get_scaling_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_scaling_matrix(m, x.v, y.v, z.v); +} + + +inline void get_x_rotate_matrix(MATRIX *m, fix r) +{ + get_x_rotate_matrix(m, r.v); +} + + +inline void get_y_rotate_matrix(MATRIX *m, fix r) +{ + get_y_rotate_matrix(m, r.v); +} + + +inline void get_z_rotate_matrix(MATRIX *m, fix r) +{ + get_z_rotate_matrix(m, r.v); +} + + +inline void get_rotation_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_rotation_matrix(m, x.v, y.v, z.v); +} + + +inline void get_align_matrix(MATRIX *m, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup) +{ + get_align_matrix(m, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v); +} + + +inline void get_vector_rotation_matrix(MATRIX *m, fix x, fix y, fix z, fix a) +{ + get_vector_rotation_matrix(m, x.v, y.v, z.v, a.v); +} + + +inline void get_transformation_matrix(MATRIX *m, fix scale, fix xrot, fix yrot, fix zrot, fix x, fix y, fix z) +{ + get_transformation_matrix(m, scale.v, xrot.v, yrot.v, zrot.v, x.v, y.v, z.v); +} + + +inline void get_camera_matrix(MATRIX *m, fix x, fix y, fix z, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup, fix fov, fix aspect) +{ + get_camera_matrix(m, x.v, y.v, z.v, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v, fov.v, aspect.v); +} + + +inline void qtranslate_matrix(MATRIX *m, fix x, fix y, fix z) +{ + qtranslate_matrix(m, x.v, y.v, z.v); +} + + +inline void qscale_matrix(MATRIX *m, fix scale) +{ + qscale_matrix(m, scale.v); +} + + +inline fix vector_length(fix x, fix y, fix z) +{ + fix t; + t.v = vector_length(x.v, y.v, z.v); + return t; +} + + +inline void normalize_vector(fix *x, fix *y, fix *z) +{ + normalize_vector(&x->v, &y->v, &z->v); +} + + +inline void cross_product(fix x1, fix y_1, fix z1, fix x2, fix y2, fix z2, fix *xout, fix *yout, fix *zout) +{ + cross_product(x1.v, y_1.v, z1.v, x2.v, y2.v, z2.v, &xout->v, &yout->v, &zout->v); +} + + +inline fix dot_product(fix x1, fix y_1, fix z1, fix x2, fix y2, fix z2) +{ + fix t; + t.v = dot_product(x1.v, y_1.v, z1.v, x2.v, y2.v, z2.v); + return t; +} + + +inline void apply_matrix(MATRIX *m, fix x, fix y, fix z, fix *xout, fix *yout, fix *zout) +{ + apply_matrix(m, x.v, y.v, z.v, &xout->v, &yout->v, &zout->v); +} + + +inline void persp_project(fix x, fix y, fix z, fix *xout, fix *yout) +{ + persp_project(x.v, y.v, z.v, &xout->v, &yout->v); +} + + +#endif /* ifdef __cplusplus */ + +#endif /* ifndef ALLEGRO_FIX_INL */ + + diff --git a/libsrc/allegro/include/allegro/inline/fmaths.inl b/libsrc/allegro/include/allegro/inline/fmaths.inl new file mode 100644 index 00000000000..e391335aa3a --- /dev/null +++ b/libsrc/allegro/include/allegro/inline/fmaths.inl @@ -0,0 +1,234 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point math inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FMATHS_INL +#define ALLEGRO_FMATHS_INL + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ftofix and fixtof are used in generic C versions of fixmul and fixdiv */ +AL_INLINE(fixed, ftofix, (double x), +{ + if (x > 32767.0) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + + if (x < -32767.0) { + *allegro_errno = ERANGE; + return -0x7FFFFFFF; + } + + return (fixed)(x * 65536.0 + (x < 0 ? -0.5 : 0.5)); +}) + + +AL_INLINE(double, fixtof, (fixed x), +{ + return (double)x / 65536.0; +}) + + +#ifdef ALLEGRO_NO_ASM + +/* use generic C versions */ + +AL_INLINE(fixed, fixadd, (fixed x, fixed y), +{ + fixed result = x + y; + + if (result >= 0) { + if ((x < 0) && (y < 0)) { + *allegro_errno = ERANGE; + return -0x7FFFFFFF; + } + else + return result; + } + else { + if ((x > 0) && (y > 0)) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + else + return result; + } +}) + + +AL_INLINE(fixed, fixsub, (fixed x, fixed y), +{ + fixed result = x - y; + + if (result >= 0) { + if ((x < 0) && (y > 0)) { + *allegro_errno = ERANGE; + return -0x7FFFFFFF; + } + else + return result; + } + else { + if ((x > 0) && (y < 0)) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + else + return result; + } +}) + + +/* In benchmarks conducted circa May 2005 we found that, in the main: + * - IA32 machines performed faster with one implementation; + * - AMD64 and G4 machines performed faster with another implementation. + * + * Benchmarks were mainly done with differing versions of gcc. + * Results varied with other compilers, optimisation levels, etc. + * so this is not optimal, though a tenable compromise. + * + * Note that the following implementation are NOT what were benchmarked. + * We had forgotten to put in overflow detection in those versions. + * If you don't need overflow detection then previous versions in the + * CVS tree might be worth looking at. + * + * PS. Don't move the #ifs inside the AL_INLINE; BCC doesn't like it. + */ +#if (defined ALLEGRO_I386) || (!defined LONG_LONG) + AL_INLINE(fixed, fixmul, (fixed x, fixed y), + { + return ftofix(fixtof(x) * fixtof(y)); + }) +#else + AL_INLINE(fixed, fixmul, (fixed x, fixed y), + { + LONG_LONG lx = x; + LONG_LONG ly = y; + LONG_LONG lres = (lx*ly); + + if (lres > 0x7FFFFFFF0000LL) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + else if (lres < -0x7FFFFFFF0000LL) { + *allegro_errno = ERANGE; + return 0x80000000; + } + else { + int res = lres >> 16; + return res; + } + }) +#endif /* fixmul() C implementations */ + + +AL_INLINE(fixed, fixdiv, (fixed x, fixed y), +{ + if (y == 0) { + *allegro_errno = ERANGE; + return (x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF; + } + else + return ftofix(fixtof(x) / fixtof(y)); +}) + + +AL_INLINE(int, fixfloor, (fixed x), +{ + /* (x >> 16) is not portable */ + if (x >= 0) + return (x >> 16); + else + return ~((~x) >> 16); +}) + + +AL_INLINE(int, fixceil, (fixed x), +{ + if (x > 0x7FFF0000) { + *allegro_errno = ERANGE; + return 0x7FFF; + } + + return fixfloor(x + 0xFFFF); +}) + +#endif /* C vs. inline asm */ + + +AL_INLINE(fixed, itofix, (int x), +{ + return x << 16; +}) + + +AL_INLINE(int, fixtoi, (fixed x), +{ + return fixfloor(x) + ((x & 0x8000) >> 15); +}) + + +AL_INLINE(fixed, fixcos, (fixed x), +{ + return _cos_tbl[((x + 0x4000) >> 15) & 0x1FF]; +}) + + +AL_INLINE(fixed, fixsin, (fixed x), +{ + return _cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF]; +}) + + +AL_INLINE(fixed, fixtan, (fixed x), +{ + return _tan_tbl[((x + 0x4000) >> 15) & 0xFF]; +}) + + +AL_INLINE(fixed, fixacos, (fixed x), +{ + if ((x < -65536) || (x > 65536)) { + *allegro_errno = EDOM; + return 0; + } + + return _acos_tbl[(x+65536+127)>>8]; +}) + + +AL_INLINE(fixed, fixasin, (fixed x), +{ + if ((x < -65536) || (x > 65536)) { + *allegro_errno = EDOM; + return 0; + } + + return 0x00400000 - _acos_tbl[(x+65536+127)>>8]; +}) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FMATHS_INL */ + + diff --git a/libsrc/allegro/include/allegro/inline/gfx.inl b/libsrc/allegro/include/allegro/inline/gfx.inl new file mode 100644 index 00000000000..db3113be773 --- /dev/null +++ b/libsrc/allegro/include/allegro/inline/gfx.inl @@ -0,0 +1,260 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Graphics inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GFX_INL +#define ALLEGRO_GFX_INL + +#include "allegro/debug.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef ALLEGRO_NO_ASM + + /* use generic C versions */ + +AL_INLINE(int, _default_ds, (void), +{ + return 0; +}) + +#ifdef ALLEGRO_BCC32 + + /* BCC32 is a somewhat unusual platform because it mixes a MSVC/MinGW generated DLL + * (for which ALLEGRO_NO_ASM is not defined) with Borland C++ compiled programs for + * which ALLEGRO_NO_ASM is defined. As a result, Borland C++ compiled programs can't + * use the inlined version of bmp_write_line(), bmp_read_line() and bmp_unwrite_line() + * because the write_bank() and read_bank() methods of the BITMAP class don't expect + * the same calling convention on both sides. + */ + +AL_FUNC(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne)); +AL_FUNC(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne)); +AL_FUNC(void, bmp_unwrite_line, (BITMAP *bmp)); + +#else + +typedef AL_METHOD(uintptr_t, _BMP_BANK_SWITCHER, (BITMAP *bmp, int lyne)); +typedef AL_METHOD(void, _BMP_UNBANK_SWITCHER, (BITMAP *bmp)); + + +AL_INLINE(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne), +{ + _BMP_BANK_SWITCHER switcher = (_BMP_BANK_SWITCHER)bmp->write_bank; + return switcher(bmp, lyne); +}) + + +AL_INLINE(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne), +{ + _BMP_BANK_SWITCHER switcher = (_BMP_BANK_SWITCHER)bmp->read_bank; + return switcher(bmp, lyne); +}) + + +AL_INLINE(void, bmp_unwrite_line, (BITMAP *bmp), +{ + _BMP_UNBANK_SWITCHER switcher = (_BMP_UNBANK_SWITCHER)bmp->vtable->unwrite_bank; + switcher(bmp); +}) + +#endif /* defined ALLEGRO_BCC32 */ + +#endif /* C vs. inline asm */ + + + +AL_INLINE(void, clear_to_color, (BITMAP *bitmap, int color), +{ + ASSERT(bitmap); + + bitmap->vtable->clear_to_color(bitmap, color); +}) + + +AL_INLINE(int, bitmap_color_depth, (BITMAP *bmp), +{ + ASSERT(bmp); + + return bmp->vtable->color_depth; +}) + + +AL_INLINE(int, bitmap_mask_color, (BITMAP *bmp), +{ + ASSERT(bmp); + + return bmp->vtable->mask_color; +}) + + +AL_INLINE(int, is_same_bitmap, (BITMAP *bmp1, BITMAP *bmp2), +{ + unsigned long m1; + unsigned long m2; + + if ((!bmp1) || (!bmp2)) + return FALSE; + + if (bmp1 == bmp2) + return TRUE; + + m1 = bmp1->id & BMP_ID_MASK; + m2 = bmp2->id & BMP_ID_MASK; + + return ((m1) && (m1 == m2)); +}) + + +AL_INLINE(int, is_linear_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return TRUE; // only support linear memory bitmaps +}) + + +AL_INLINE(int, is_planar_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return FALSE; // only support linear memory bitmaps +}) + + +AL_INLINE(int, is_memory_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return TRUE; // only support linear memory bitmaps +}) + + +AL_INLINE(int, is_screen_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return FALSE; // only support linear memory bitmaps +}) + + +AL_INLINE(int, is_video_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return FALSE; // only support linear memory bitmaps +}) + + +AL_INLINE(int, is_system_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return FALSE; // only support linear memory bitmaps +}) + + +AL_INLINE(int, is_sub_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & BMP_ID_SUB) != 0; +}) + + +#ifdef ALLEGRO_MPW + + #define acquire_bitmap(bmp) + #define release_bitmap(bmp) + #define acquire_screen() + #define release_screen() + +#else + +AL_INLINE(void, acquire_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + if (bmp->vtable->acquire) + bmp->vtable->acquire(bmp); +}) + + +AL_INLINE(void, release_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + if (bmp->vtable->release) + bmp->vtable->release(bmp); +}) + +#endif + + +AL_INLINE(int, is_inside_bitmap, (BITMAP *bmp, int x, int y, int clip), +{ + ASSERT(bmp); + + if (clip) { + if (bmp->clip) + /* internal clipping is inclusive-exclusive */ + return (x >= bmp->cl) && (y >= bmp->ct) && (x < bmp->cr) && (y < bmp->cb); + else + return TRUE; + } + else + /* bitmap dimensions are always non-negative */ + return (unsigned int)x < (unsigned int)bmp->w && (unsigned int)y < (unsigned int)bmp->h; +}) + + +AL_INLINE(void, get_clip_rect, (BITMAP *bitmap, int *x1, int *y_1, int *x2, int *y2), +{ + ASSERT(bitmap); + + /* internal clipping is inclusive-exclusive */ + *x1 = bitmap->cl; + *y_1 = bitmap->ct; + *x2 = bitmap->cr-1; + *y2 = bitmap->cb-1; +}) + +AL_INLINE(void, set_clip_state, (BITMAP *bitmap, int state), +{ + ASSERT(bitmap); + + bitmap->clip = state; +}) + +AL_INLINE(int, get_clip_state, (BITMAP *bitmap), +{ + ASSERT(bitmap); + + return bitmap->clip; +}) + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_GFX_INL */ + + diff --git a/libsrc/allegro/include/allegro/internal/aintern.h b/libsrc/allegro/include/allegro/internal/aintern.h new file mode 100644 index 00000000000..b20455a84fe --- /dev/null +++ b/libsrc/allegro/include/allegro/internal/aintern.h @@ -0,0 +1,596 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the library code. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTERN_H +#define AINTERN_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* length in bytes of the cpu_vendor string */ +#define _AL_CPU_VENDOR_SIZE 32 + + +/* flag for how many times we have been initialised */ +AL_VAR(int, _allegro_count); + + +/* flag to know whether we are being called by the exit mechanism */ +AL_VAR(int, _allegro_in_exit); + + +AL_FUNCPTR(int, _al_trace_handler, (AL_CONST char *msg)); + + +/* malloc wrappers */ +/* The 4.3 branch uses the following macro names to allow the user to customise + * the memory management routines. We don't have that feature in 4.2, but we + * use the same macros names in order to reduce divergence of the codebases. + */ +#define _AL_MALLOC(SIZE) (_al_malloc(SIZE)) +#define _AL_MALLOC_ATOMIC(SIZE) (_al_malloc(SIZE)) +#define _AL_FREE(PTR) (_al_free(PTR)) +#define _AL_REALLOC(PTR, SIZE) (_al_realloc(PTR, SIZE)) + +AL_FUNC(void *, _al_malloc, (size_t size)); +AL_FUNC(void, _al_free, (void *mem)); +AL_FUNC(void *, _al_realloc, (void *mem, size_t size)); +AL_FUNC(char *, _al_strdup, (AL_CONST char *string)); +AL_FUNC(char *, _al_ustrdup, (AL_CONST char *string)); + + + +/* some Allegro functions need a block of scratch memory */ +AL_VAR(void *, _scratch_mem); +AL_VAR(int, _scratch_mem_size); + + +AL_INLINE(void, _grow_scratch_mem, (int size), +{ + if (size > _scratch_mem_size) { + size = (size+1023) & 0xFFFFFC00; + _scratch_mem = _AL_REALLOC(_scratch_mem, size); + _scratch_mem_size = size; + } +}) + + +/* list of functions to call at program cleanup */ +AL_FUNC(void, _add_exit_func, (AL_METHOD(void, func, (void)), AL_CONST char *desc)); +AL_FUNC(void, _remove_exit_func, (AL_METHOD(void, func, (void)))); + + +/* helper structure for talking to Unicode strings */ +typedef struct UTYPE_INFO +{ + int id; + AL_METHOD(int, u_getc, (AL_CONST char *s)); + AL_METHOD(int, u_getx, (char **s)); + AL_METHOD(int, u_setc, (char *s, int c)); + AL_METHOD(int, u_width, (AL_CONST char *s)); + AL_METHOD(int, u_cwidth, (int c)); + AL_METHOD(int, u_isok, (int c)); + int u_width_max; +} UTYPE_INFO; + +AL_FUNC(UTYPE_INFO *, _find_utype, (int type)); + + +/* message stuff */ +#define ALLEGRO_MESSAGE_SIZE 4096 + + +/* wrappers for implementing disk I/O on different platforms */ +AL_FUNC(int, _al_file_isok, (AL_CONST char *filename)); +AL_FUNC(uint64_t, _al_file_size_ex, (AL_CONST char *filename)); +AL_FUNC(time_t, _al_file_time, (AL_CONST char *filename)); +AL_FUNC(int, _al_drive_exists, (int drive)); +AL_FUNC(int, _al_getdrive, (void)); +AL_FUNC(void, _al_getdcwd, (int drive, char *buf, int size)); + +/* obsolete; only exists for binary compatibility with 4.2.0 */ +AL_FUNC(long, _al_file_size, (AL_CONST char *filename)); + + +/* packfile stuff */ +AL_VAR(int, _packfile_filesize); +AL_VAR(int, _packfile_datasize); +AL_VAR(int, _packfile_type); +AL_FUNC(PACKFILE *, _pack_fdopen, (int fd, AL_CONST char *mode)); + + + +#if (defined ALLEGRO_WINDOWS) + + AL_FUNC(int, _al_win_open, (const char *filename, int mode, int perm)); + AL_FUNC(int, _al_win_unlink, (const char *filename)); + + + #define _al_open(filename, mode, perm) _al_win_open(filename, mode, perm) + #define _al_unlink(filename) _al_win_unlink(filename) + +#else + + #define _al_open(filename, mode, perm) open(filename, mode, perm) + #define _al_unlink(filename) unlink(filename) + +#endif + + + +/* caches and tables for svga bank switching */ +AL_VAR(int, _last_bank_1); +AL_VAR(int, _last_bank_2); + +AL_VAR(int *, _gfx_bank); + +/* bank switching routines (these use a non-C calling convention on i386!) */ +AL_FUNC(uintptr_t, _stub_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _stub_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _stub_bank_switch_end, (void)); + + + +/* stuff for setting up bitmaps */ +AL_FUNC(GFX_VTABLE *, _get_vtable, (int color_depth)); + +AL_VAR(int, _sub_bitmap_id_count); + + +#ifdef ALLEGRO_I386 + #define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) +#else + #ifdef ALLEGRO_MPW + /* in Mac 24 bit is a unsigned long */ + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : 4)) + #else + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : (((bpp) <= 24) ? 3 : 4))) + #endif +#endif + +AL_FUNC(int, _color_load_depth, (int depth, int hasalpha)); + +AL_VAR(int, _color_conv); + +AL_FUNC(BITMAP *, _fixup_loaded_bitmap, (BITMAP *bmp, PALETTE pal, int bpp)); + +AL_FUNC(int, _bitmap_has_alpha, (BITMAP *bmp)); + +/* default truecolor pixel format */ +#define DEFAULT_RGB_R_SHIFT_15 0 +#define DEFAULT_RGB_G_SHIFT_15 5 +#define DEFAULT_RGB_B_SHIFT_15 10 +#define DEFAULT_RGB_R_SHIFT_16 0 +#define DEFAULT_RGB_G_SHIFT_16 5 +#define DEFAULT_RGB_B_SHIFT_16 11 +#define DEFAULT_RGB_R_SHIFT_24 0 +#define DEFAULT_RGB_G_SHIFT_24 8 +#define DEFAULT_RGB_B_SHIFT_24 16 +#define DEFAULT_RGB_R_SHIFT_32 0 +#define DEFAULT_RGB_G_SHIFT_32 8 +#define DEFAULT_RGB_B_SHIFT_32 16 +#define DEFAULT_RGB_A_SHIFT_32 24 + + + +/* current drawing mode */ +AL_VAR(int, _drawing_mode); +AL_VAR(BITMAP *, _drawing_pattern); +AL_VAR(int, _drawing_x_anchor); +AL_VAR(int, _drawing_y_anchor); +AL_VAR(unsigned int, _drawing_x_mask); +AL_VAR(unsigned int, _drawing_y_mask); + +AL_FUNCPTR(int *, _palette_expansion_table, (int bpp)); + +AL_VAR(int, _color_depth); + +AL_VAR(int, _current_palette_changed); +AL_VAR(PALETTE, _prev_current_palette); +AL_VAR(int, _got_prev_current_palette); + +AL_ARRAY(int, _palette_color8); +AL_ARRAY(int, _palette_color15); +AL_ARRAY(int, _palette_color16); +AL_ARRAY(int, _palette_color24); +AL_ARRAY(int, _palette_color32); + +/* truecolor blending functions */ +AL_VAR(BLENDER_FUNC, _blender_func15); +AL_VAR(BLENDER_FUNC, _blender_func16); +AL_VAR(BLENDER_FUNC, _blender_func24); +AL_VAR(BLENDER_FUNC, _blender_func32); + +AL_VAR(BLENDER_FUNC, _blender_func15x); +AL_VAR(BLENDER_FUNC, _blender_func16x); +AL_VAR(BLENDER_FUNC, _blender_func24x); + +AL_VAR(int, _blender_col_15); +AL_VAR(int, _blender_col_16); +AL_VAR(int, _blender_col_24); +AL_VAR(int, _blender_col_32); + +AL_VAR(int, _blender_alpha); + +AL_FUNC(unsigned long, _blender_black, (unsigned long x, unsigned long y, unsigned long n)); + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(unsigned long, _blender_trans15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen15, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_trans16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen16, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) + +AL_FUNC(unsigned long, _blender_trans24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen24, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +AL_FUNC(unsigned long, _blender_alpha15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha32, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_write_alpha, (unsigned long x, unsigned long y, unsigned long n)); + + +/* graphics drawing routines */ +AL_FUNC(void, _normal_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _fast_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _normal_rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(int, _linear_getpixel8, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel8, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline8, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline8, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_ex8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); +AL_FUNC(void, _linear_draw_sprite_v_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit8, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color8, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _linear_putpixel15, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline15, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline15, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_trans_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); + +AL_FUNC(int, _linear_getpixel16, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel16, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline16, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline16, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_ex16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); +AL_FUNC(void, _linear_draw_256_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color16, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(int, _linear_getpixel24, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel24, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline24, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline24, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_ex24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); +AL_FUNC(void, _linear_draw_256_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color24, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(int, _linear_getpixel32, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel32, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline32, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline32, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_ex32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); +AL_FUNC(void, _linear_draw_256_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color32, (BITMAP *bitmap, int color)); + +#endif + + + +/* color conversion routines */ +typedef struct GRAPHICS_RECT { + int width; + int height; + int pitch; + void *data; +} GRAPHICS_RECT; + +typedef void (COLORCONV_BLITTER_FUNC)(GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect); + +AL_FUNC(COLORCONV_BLITTER_FUNC *, _get_colorconv_blitter, (int from_depth, int to_depth)); +AL_FUNC(void, _release_colorconv_blitter, (COLORCONV_BLITTER_FUNC *blitter)); +AL_FUNC(void, _set_colorconv_palette, (AL_CONST struct RGB *p, int from, int to)); +AL_FUNC(unsigned char *, _get_colorconv_map, (void)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _colorconv_blit_8_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _colorconv_blit_15_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +AL_FUNC(void, _colorconv_blit_16_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _colorconv_blit_24_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _colorconv_blit_32_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + + + +/* generic color conversion blitter */ +AL_FUNC(void, _blit_between_formats, (BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)); + + +/* asm helper for stretch_blit() */ +#ifndef SCAN_EXPORT +AL_FUNC(void, _do_stretch, (BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth)); +#endif + + +/* lower level functions for rotation */ +AL_FUNC(void, _parallelogram_map, (BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy), int sub_pixel_accuracy)); +AL_FUNC(void, _parallelogram_map_standard, (BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _rotate_scale_flip_coordinates, (fixed w, fixed h, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale_x, fixed scale_y, int h_flip, int v_flip, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); + + +/* number of fractional bits used by the polygon rasteriser */ +#define POLYGON_FIX_SHIFT 18 + + + + +/* information for polygon scanline fillers */ +typedef struct POLYGON_SEGMENT +{ + fixed u, v, du, dv; /* fixed point u/v coordinates */ + fixed c, dc; /* single color gouraud shade values */ + fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ + float z, dz; /* polygon depth (1/z) */ + float fu, fv, dfu, dfv; /* floating point u/v coordinates */ + unsigned char *texture; /* the texture map */ + int umask, vmask, vshift; /* texture map size information */ + int seg; /* destination bitmap selector */ + uintptr_t zbuf_addr; /* Z-buffer address */ + uintptr_t read_addr; /* reading address for transparency modes */ +} POLYGON_SEGMENT; + + +/* an active polygon edge */ +typedef struct POLYGON_EDGE +{ + int top; /* top y position */ + int bottom; /* bottom y position */ + fixed x, dx; /* fixed point x position and gradient */ + fixed w; /* width of line segment */ + POLYGON_SEGMENT dat; /* texture/gouraud information */ + struct POLYGON_EDGE *prev; /* doubly linked list */ + struct POLYGON_EDGE *next; + struct POLYGON_INFO *poly; /* father polygon */ +} POLYGON_EDGE; + + + +/* datafile ID's for compatibility with the old datafile format */ +#define V1_DAT_MAGIC 0x616C6C2EL + +#define V1_DAT_DATA 0 +#define V1_DAT_FONT 1 +#define V1_DAT_BITMAP_16 2 +#define V1_DAT_BITMAP_256 3 +#define V1_DAT_SPRITE_16 4 +#define V1_DAT_SPRITE_256 5 +#define V1_DAT_PALETTE_16 6 +#define V1_DAT_PALETTE_256 7 +#define V1_DAT_FONT_8x8 8 +#define V1_DAT_FONT_PROP 9 +#define V1_DAT_BITMAP 10 +#define V1_DAT_PALETTE 11 +#define V1_DAT_SAMPLE 12 +#define V1_DAT_MIDI 13 +#define V1_DAT_RLE_SPRITE 14 +#define V1_DAT_FLI 15 +#define V1_DAT_C_SPRITE 16 +#define V1_DAT_XC_SPRITE 17 + +#define OLD_FONT_SIZE 95 +#define LESS_OLD_FONT_SIZE 224 + + +/* datafile object loading functions */ +AL_FUNC(void, _unload_datafile_object, (DATAFILE *dat)); + + +/* information about a datafile object */ +typedef struct DATAFILE_TYPE +{ + int type; + AL_METHOD(void *, load, (PACKFILE *f, long size)); + AL_METHOD(void, destroy, (void *)); +} DATAFILE_TYPE; + + +#define MAX_DATAFILE_TYPES 32 + +AL_ARRAY(DATAFILE_TYPE, _datafile_type); + +/* for readbmp.c */ +AL_FUNC(void, _register_bitmap_file_type_init, (void)); + + + +/* various libc stuff */ +AL_FUNC(void *, _al_sane_realloc, (void *ptr, size_t size)); +AL_FUNC(char *, _al_sane_strncpy, (char *dest, const char *src, size_t n)); + + +#define _AL_RAND_MAX 0xFFFF +AL_FUNC(void, _al_srand, (int seed)); +AL_FUNC(int, _al_rand, (void)); + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef AINTERN_H */ diff --git a/libsrc/allegro/include/allegro/internal/alconfig.h b/libsrc/allegro/include/allegro/internal/alconfig.h new file mode 100644 index 00000000000..0b27004486a --- /dev/null +++ b/libsrc/allegro/include/allegro/internal/alconfig.h @@ -0,0 +1,414 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +/* which color depths to include? */ +#define ALLEGRO_COLOR8 +#define ALLEGRO_COLOR16 +#define ALLEGRO_COLOR24 +#define ALLEGRO_COLOR32 + + +/* for backward compatibility */ +#ifdef USE_CONSOLE + #define ALLEGRO_NO_MAGIC_MAIN + #define ALLEGRO_USE_CONSOLE +#endif + + +/* include platform-specific stuff */ +#ifndef SCAN_EXPORT + #if defined ALLEGRO_MSVC + #include "allegro/platform/almsvc.h" + #elif defined ALLEGRO_MACOSX + #include "allegro/platform/alosxcfg.h" + #elif defined ALLEGRO_UNIX + #include "allegro/platform/alucfg.h" + #elif defined ALLEGRO_IOS + #include "allegro/platform/alioscfg.h" + #elif defined ALLEGRO_ANDROID + #include "allegro/platform/alandcfg.h" + #else + #error platform not supported + #endif + + #include "allegro/platform/astdint.h" +#endif + + +/* special definitions for the GCC compiler */ +#ifdef __GNUC__ + #define ALLEGRO_GCC + + #ifndef AL_INLINE + #ifdef __cplusplus + #define AL_INLINE(type, name, args, code) \ + static inline type name args; \ + static inline type name args code + /* Needed if this header is included by C99 user code, as + * "extern __inline__" is defined differently in C99 (it exports + * a new global function symbol). + */ + #elif __GNUC_STDC_INLINE__ + #define AL_INLINE(type, name, args, code) \ + extern __inline__ __attribute__((__gnu_inline__)) type name args; \ + extern __inline__ __attribute__((__gnu_inline__)) type name args code + #else + #define AL_INLINE(type, name, args, code) \ + extern __inline__ type name args; \ + extern __inline__ type name args code + #endif + #endif + + #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) __attribute__ ((format (printf, a, b))) + + #ifndef INLINE + #define INLINE __inline__ + #endif + + #if __GNUC__ >= 3 + /* SET: According to gcc volatile is ignored for a return type. + * I think the code should just ensure that inportb is declared as an + * __asm__ __volatile__ macro. If that's the case the extra volatile + * doesn't have any sense. + */ + #define RET_VOLATILE + #else + #define RET_VOLATILE volatile + #endif + + #ifndef ZERO_SIZE_ARRAY + #if __GNUC__ < 3 + #define ZERO_SIZE_ARRAY(type, name) __extension__ type name[0] + #else + #define ZERO_SIZE_ARRAY(type, name) type name[] /* ISO C99 flexible array members */ + #endif + #endif + + #ifndef LONG_LONG + #define LONG_LONG long long + #ifdef ALLEGRO_GUESS_INTTYPES_OK + #define int64_t signed long long + #define uint64_t unsigned long long + #endif + #endif + + #ifdef __i386__ + #define ALLEGRO_I386 + #ifndef ALLEGRO_NO_ASM + #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) + #endif + #endif + + #ifdef __amd64__ + #define ALLEGRO_AMD64 + #ifndef ALLEGRO_NO_ASM + #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) + #endif + #endif + + #ifdef __arm__ + #define ALLEGRO_ARM + #endif + + #ifndef AL_CONST + #define AL_CONST const + #endif + + #ifndef AL_FUNC_DEPRECATED + #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) + #define AL_FUNC_DEPRECATED(type, name, args) AL_FUNC(__attribute__ ((deprecated)) type, name, args) + #define AL_PRINTFUNC_DEPRECATED(type, name, args, a, b) AL_PRINTFUNC(__attribute__ ((deprecated)) type, name, args, a, b) + #define AL_INLINE_DEPRECATED(type, name, args, code) AL_INLINE(__attribute__ ((deprecated)) type, name, args, code) + #endif + #endif + + #ifndef AL_ALIAS + #define AL_ALIAS(DECL, CALL) \ + static __attribute__((unused)) __inline__ DECL \ + { \ + return CALL; \ + } + #endif + + #ifndef AL_ALIAS_VOID_RET + #define AL_ALIAS_VOID_RET(DECL, CALL) \ + static __attribute__((unused)) __inline__ void DECL \ + { \ + CALL; \ + } + #endif +#endif + + +/* use constructor functions, if supported */ +#ifdef ALLEGRO_USE_CONSTRUCTOR + #define CONSTRUCTOR_FUNCTION(func) func __attribute__ ((constructor)) + #define DESTRUCTOR_FUNCTION(func) func __attribute__ ((destructor)) +#endif + + +/* the rest of this file fills in some default definitions of language + * features and helper functions, which are conditionalised so they will + * only be included if none of the above headers defined custom versions. + */ + +#ifndef _AL_SINCOS + #define _AL_SINCOS(x, s, c) do { (c) = cos(x); (s) = sin(x); } while (0) +#endif + +#ifndef INLINE + #define INLINE +#endif + +#ifndef RET_VOLATILE + #define RET_VOLATILE volatile +#endif + +#ifndef ZERO_SIZE_ARRAY + #define ZERO_SIZE_ARRAY(type, name) type name[] +#endif + +#ifndef AL_CONST + #define AL_CONST +#endif + +#ifndef AL_VAR + #define AL_VAR(type, name) extern type name +#endif + +#ifndef AL_ARRAY + #define AL_ARRAY(type, name) extern type name[] +#endif + +#ifndef AL_FUNC + #define AL_FUNC(type, name, args) type name args +#endif + +#ifndef AL_PRINTFUNC + #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) +#endif + +#ifndef AL_METHOD + #define AL_METHOD(type, name, args) type (*name) args +#endif + +#ifndef AL_FUNCPTR + #define AL_FUNCPTR(type, name, args) extern type (*name) args +#endif + +#ifndef AL_FUNCPTRARRAY + #define AL_FUNCPTRARRAY(type, name, args) extern type (*name[]) args +#endif + +#ifndef AL_INLINE + #define AL_INLINE(type, name, args, code) type name args; +#endif + +#ifndef AL_FUNC_DEPRECATED + #define AL_FUNC_DEPRECATED(type, name, args) AL_FUNC(type, name, args) + #define AL_PRINTFUNC_DEPRECATED(type, name, args, a, b) AL_PRINTFUNC(type, name, args, a, b) + #define AL_INLINE_DEPRECATED(type, name, args, code) AL_INLINE(type, name, args, code) +#endif + +#ifndef AL_ALIAS + #define AL_ALIAS(DECL, CALL) \ + static INLINE DECL \ + { \ + return CALL; \ + } +#endif + +#ifndef AL_ALIAS_VOID_RET + #define AL_ALIAS_VOID_RET(DECL, CALL) \ + static INLINE void DECL \ + { \ + CALL; \ + } +#endif + +#ifndef END_OF_MAIN + #define END_OF_MAIN() +#endif + + +/* fill in default memory locking macros */ +#ifndef END_OF_FUNCTION + #define END_OF_FUNCTION(x) + #define END_OF_STATIC_FUNCTION(x) + #define LOCK_DATA(d, s) + #define LOCK_CODE(c, s) + #define UNLOCK_DATA(d, s) + #define LOCK_VARIABLE(x) + #define LOCK_FUNCTION(x) +#endif + + +/* fill in default filename behaviour */ +#ifndef ALLEGRO_LFN + #define ALLEGRO_LFN 1 +#endif + +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) + #define OTHER_PATH_SEPARATOR '\\' + #define DEVICE_SEPARATOR ':' +#else + #define OTHER_PATH_SEPARATOR '/' + #define DEVICE_SEPARATOR '\0' +#endif + + +/* emulate the FA_* flags for platforms that don't already have them */ +#ifndef FA_RDONLY + #define FA_RDONLY 1 + #define FA_HIDDEN 2 + #define FA_SYSTEM 4 + #define FA_LABEL 8 + #define FA_DIREC 16 + #define FA_ARCH 32 +#endif + #define FA_NONE 0 + #define FA_ALL (~FA_NONE) + + +#ifdef __cplusplus + extern "C" { +#endif + +/* emulate missing library functions */ +#ifdef ALLEGRO_NO_STRICMP + AL_FUNC(int, _alemu_stricmp, (AL_CONST char *s1, AL_CONST char *s2)); + #define stricmp _alemu_stricmp +#endif + +#ifdef ALLEGRO_NO_STRLWR + AL_FUNC(char *, _alemu_strlwr, (char *string)); + #define strlwr _alemu_strlwr +#endif + +#ifdef ALLEGRO_NO_STRUPR + AL_FUNC(char *, _alemu_strupr, (char *string)); + #define strupr _alemu_strupr +#endif + +#ifdef ALLEGRO_NO_MEMCMP + AL_FUNC(int, _alemu_memcmp, (AL_CONST void *s1, AL_CONST void *s2, size_t num)); + #define memcmp _alemu_memcmp +#endif + + +/* if nobody put them elsewhere, video bitmaps go in regular memory */ +#ifndef _video_ds + #define _video_ds() _default_ds() +#endif + + +/* not many places actually use these, but still worth emulating */ +#ifndef ALLEGRO_DJGPP + #define _farsetsel(seg) + #define _farnspokeb(addr, val) (*((uint8_t *)(addr)) = (val)) + #define _farnspokew(addr, val) (*((uint16_t *)(addr)) = (val)) + #define _farnspokel(addr, val) (*((uint32_t *)(addr)) = (val)) + #define _farnspeekb(addr) (*((uint8_t *)(addr))) + #define _farnspeekw(addr) (*((uint16_t *)(addr))) + #define _farnspeekl(addr) (*((uint32_t *)(addr))) +#endif + + +/* endian-independent 3-byte accessor macros */ +#ifdef ALLEGRO_LITTLE_ENDIAN + + #define READ3BYTES(p) ((*(unsigned char *)(p)) \ + | (*((unsigned char *)(p) + 1) << 8) \ + | (*((unsigned char *)(p) + 2) << 16)) + + #define WRITE3BYTES(p,c) ((*(unsigned char *)(p) = (c)), \ + (*((unsigned char *)(p) + 1) = (c) >> 8), \ + (*((unsigned char *)(p) + 2) = (c) >> 16)) + +#elif defined ALLEGRO_BIG_ENDIAN + + #define READ3BYTES(p) ((*(unsigned char *)(p) << 16) \ + | (*((unsigned char *)(p) + 1) << 8) \ + | (*((unsigned char *)(p) + 2))) + + #define WRITE3BYTES(p,c) ((*(unsigned char *)(p) = (c) >> 16), \ + (*((unsigned char *)(p) + 1) = (c) >> 8), \ + (*((unsigned char *)(p) + 2) = (c))) + +#elif defined SCAN_DEPEND + + #define READ3BYTES(p) + #define WRITE3BYTES(p,c) + +#else + #error endianess not defined +#endif + + +/* generic versions of the video memory access helpers */ +#ifndef bmp_select + #define bmp_select(bmp) +#endif + +#ifndef bmp_write8 + #define bmp_write8(addr, c) (*((uint8_t *)(addr)) = (c)) + #define bmp_write15(addr, c) (*((uint16_t *)(addr)) = (c)) + #define bmp_write16(addr, c) (*((uint16_t *)(addr)) = (c)) + #define bmp_write32(addr, c) (*((uint32_t *)(addr)) = (c)) + + #define bmp_read8(addr) (*((uint8_t *)(addr))) + #define bmp_read15(addr) (*((uint16_t *)(addr))) + #define bmp_read16(addr) (*((uint16_t *)(addr))) + #define bmp_read32(addr) (*((uint32_t *)(addr))) + + AL_INLINE(int, bmp_read24, (uintptr_t addr), + { + unsigned char *p = (unsigned char *)addr; + int c; + + c = READ3BYTES(p); + + return c; + }) + + AL_INLINE(void, bmp_write24, (uintptr_t addr, int c), + { + unsigned char *p = (unsigned char *)addr; + + WRITE3BYTES(p, c); + }) + +#endif + + +/* default random function definition */ +#ifndef AL_RAND + #define AL_RAND() (rand()) +#endif + +#ifdef __cplusplus + } +#endif + + +/* parameters for the color conversion code */ +#if (defined ALLEGRO_WINDOWS) || (defined ALLEGRO_QNX) + #define ALLEGRO_COLORCONV_ALIGNED_WIDTH + #define ALLEGRO_NO_COLORCOPY +#endif + diff --git a/libsrc/allegro/include/allegro/palette.h b/libsrc/allegro/include/allegro/palette.h new file mode 100644 index 00000000000..d1964a04ac1 --- /dev/null +++ b/libsrc/allegro/include/allegro/palette.h @@ -0,0 +1,42 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Palette type. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_PALETTE_H +#define ALLEGRO_PALETTE_H + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct RGB +{ + unsigned char r, g, b; + unsigned char filler; +} RGB; + +#define PAL_SIZE 256 + +typedef RGB PALETTE[PAL_SIZE]; + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_PALETTE_H */ + + diff --git a/libsrc/allegro/include/allegro/platform/alandcfg.h b/libsrc/allegro/include/allegro/platform/alandcfg.h new file mode 100644 index 00000000000..83875bb3708 --- /dev/null +++ b/libsrc/allegro/include/allegro/platform/alandcfg.h @@ -0,0 +1,55 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Android specific header defines. + * + * By JJS for the Adventure Game Studio runtime port. + * Based on the Allegro PSP port. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALANDCFG_H +#define ALANDCFG_H + +#ifndef SCAN_DEPEND + #include + #include +#endif + +#include + +#define ALLEGRO_HAVE_DIRENT_H 1 +#define ALLEGRO_HAVE_INTTYPES_H 1 +#define ALLEGRO_HAVE_STDINT_H 1 +#define ALLEGRO_HAVE_SYS_TIME_H 1 +#define ALLEGRO_HAVE_SYS_STAT_H 1 + +/* Describe this platform */ +#define ALLEGRO_PLATFORM_STR "Android" +#define ALLEGRO_USE_CONSTRUCTOR + +#define ALLEGRO_LITTLE_ENDIAN + +/* Provide implementations of missing definitions */ +#ifndef O_BINARY + #define O_BINARY 0 +#endif +#define dup(X) (fcntl(X, F_DUPFD, 0)) + +/* Exclude ASM */ +#ifndef ALLEGRO_NO_ASM + #define ALLEGRO_NO_ASM +#endif + + + +#endif diff --git a/libsrc/allegro/include/allegro/platform/alioscfg.h b/libsrc/allegro/include/allegro/platform/alioscfg.h new file mode 100644 index 00000000000..406babcec23 --- /dev/null +++ b/libsrc/allegro/include/allegro/platform/alioscfg.h @@ -0,0 +1,58 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Android specific header defines. + * + * By JJS for the Adventure Game Studio runtime port. + * Based on the Allegro PSP port. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALIOSCFG_H +#define ALIOSCFG_H + +#ifndef SCAN_DEPEND + #include + #include +#endif + + +#include + +#define ALLEGRO_HAVE_DIRENT_H 1 +#define ALLEGRO_HAVE_INTTYPES_H 1 +#define ALLEGRO_HAVE_STDINT_H 1 +#define ALLEGRO_HAVE_SYS_TIME_H 1 +#define ALLEGRO_HAVE_SYS_STAT_H 1 + +#define ALLEGRO_HAVE_LIBPTHREAD 1 + +/* Describe this platform */ +#define ALLEGRO_PLATFORM_STR "iOS" +#define ALLEGRO_USE_CONSTRUCTOR +#define ALLEGRO_MULTITHREADED +#define ALLEGRO_LITTLE_ENDIAN + +/* Provide implementations of missing definitions */ +#ifndef O_BINARY + #define O_BINARY 0 +#endif +#define dup(X) (fcntl(X, F_DUPFD, 0)) + +/* Exclude ASM */ +#ifndef ALLEGRO_NO_ASM + #define ALLEGRO_NO_ASM +#endif + + + +#endif diff --git a/libsrc/allegro/include/allegro/platform/almsvc.h b/libsrc/allegro/include/allegro/platform/almsvc.h new file mode 100644 index 00000000000..8e8e52593dc --- /dev/null +++ b/libsrc/allegro/include/allegro/platform/almsvc.h @@ -0,0 +1,91 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with MSVC. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include + #include + #include +#endif + + +#pragma warning (disable: 4200 4244 4305) + + +/* describe this platform */ +#ifdef ALLEGRO_STATICLINK + #define ALLEGRO_PLATFORM_STR "MSVC.s" +#else + #define ALLEGRO_PLATFORM_STR "MSVC" +#endif + +#define ALLEGRO_WINDOWS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_GUESS_INTTYPES_OK +#define ALLEGRO_MULTITHREADED + + +/* describe how function prototypes look to MSVC */ +#if defined ALLEGRO_STATICLINK + #define _AL_DLL +#elif defined ALLEGRO_SRC + #define _AL_DLL __declspec(dllexport) +#else + #define _AL_DLL __declspec(dllimport) +#endif + +#define AL_VAR(type, name) extern _AL_DLL type name +#define AL_ARRAY(type, name) extern _AL_DLL type name[] +#define AL_FUNC(type, name, args) _AL_DLL type __cdecl name args +#define AL_METHOD(type, name, args) type (__cdecl *name) args +#define AL_FUNCPTR(type, name, args) extern _AL_DLL type (__cdecl *name) args + +#ifdef AL_INLINE + #define END_OF_INLINE(name) void *_force_instantiate_##name = name; +#else + #define END_OF_INLINE(name) +#endif + +#undef AL_INLINE + +#define AL_INLINE(type, name, args, code) __inline _AL_DLL type __cdecl name args code END_OF_INLINE(name) + +#define INLINE __inline + +#define LONG_LONG __int64 +#if (_MSC_VER >= 1600) + #define ALLEGRO_HAVE_STDINT_H +#else + #define int64_t signed __int64 + #define uint64_t unsigned __int64 +#endif + +#define AL_CONST const + + +/* describe the asm syntax for this platform */ +#define ALLEGRO_ASM_PREFIX "_" + + +/* life would be so easy if compilers would all use the same names! */ +#if (!defined S_IRUSR) && (!defined SCAN_DEPEND) + #define S_IRUSR S_IREAD + #define S_IWUSR S_IWRITE +#endif + diff --git a/libsrc/allegro/include/allegro/platform/alosxcfg.h b/libsrc/allegro/include/allegro/platform/alosxcfg.h new file mode 100644 index 00000000000..ad9f6c72964 --- /dev/null +++ b/libsrc/allegro/include/allegro/platform/alosxcfg.h @@ -0,0 +1,60 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with MacOS X. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALOSXCFG_H +#define ALOSXCFG_H + +/* Provide implementations of missing functions */ +#define ALLEGRO_NO_STRICMP +#define ALLEGRO_NO_STRLWR +#define ALLEGRO_NO_STRUPR + +/* Override default definitions for this platform */ +#define AL_RAND() ((rand() >> 16) & 0x7fff) + +/* A static auto config */ +#define ALLEGRO_HAVE_LIBPTHREAD 1 +#define ALLEGRO_HAVE_DIRENT_H 1 +#define ALLEGRO_HAVE_INTTYPES_H 1 +#define ALLEGRO_HAVE_STDINT_H 1 +#define ALLEGRO_HAVE_SYS_TIME_H 1 +#define ALLEGRO_HAVE_SYS_STAT_H 1 +#define ALLEGRO_HAVE_MKSTEMP 1 + +/* Describe this platform */ +#define ALLEGRO_PLATFORM_STR "MacOS X" +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_USE_CONSTRUCTOR +#define ALLEGRO_MULTITHREADED + +/* Endianesse - different between Intel and PPC based Mac's */ +#ifdef __LITTLE_ENDIAN__ + #define ALLEGRO_LITTLE_ENDIAN +#endif +#ifdef __BIG_ENDIAN__ + #define ALLEGRO_BIG_ENDIAN +#endif + +/* Exclude ASM */ + +#ifndef ALLEGRO_NO_ASM + #define ALLEGRO_NO_ASM +#endif + + +#endif diff --git a/libsrc/allegro/include/allegro/platform/alucfg.h b/libsrc/allegro/include/allegro/platform/alucfg.h new file mode 100644 index 00000000000..32870d8bcc3 --- /dev/null +++ b/libsrc/allegro/include/allegro/platform/alucfg.h @@ -0,0 +1,56 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use on Unix platforms. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include +#include + +/* Describe this platform. */ +#define ALLEGRO_PLATFORM_STR "Unix" +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_VRAM_SINGLE_SURFACE + +/* These defines will be provided by configure script. */ +#undef ALLEGRO_COLOR8 +#undef ALLEGRO_COLOR16 +#undef ALLEGRO_COLOR24 +#undef ALLEGRO_COLOR32 + +/* Include configuration generated by configure script. */ +#include "allegro/platform/alunixac.h" + +/* Enable multithreaded library */ +#ifdef ALLEGRO_HAVE_LIBPTHREAD +#define ALLEGRO_MULTITHREADED +#endif + +/* Provide implementations of missing functions. */ +#ifndef ALLEGRO_HAVE_STRICMP +#define ALLEGRO_NO_STRICMP +#endif + +#ifndef ALLEGRO_HAVE_STRLWR +#define ALLEGRO_NO_STRLWR +#endif + +#ifndef ALLEGRO_HAVE_STRUPR +#define ALLEGRO_NO_STRUPR +#endif + +#ifndef ALLEGRO_HAVE_MEMCMP +#define ALLEGRO_NO_MEMCMP +#endif diff --git a/libsrc/allegro/include/allegro/platform/astdint.h b/libsrc/allegro/include/allegro/platform/astdint.h new file mode 100644 index 00000000000..a0962423df2 --- /dev/null +++ b/libsrc/allegro/include/allegro/platform/astdint.h @@ -0,0 +1,37 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * A header file to get definitions of uint*_t and int*_t. + * + * By Peter Wang. + * + * See readme.txt for copyright information. + */ + +#ifndef ASTDINT_H +#define ASTDINT_H + +/* Please only include this file from include/allegro/internal/alconfig.h + * and don't add more than inttypes.h/stdint.h emulation here. Thanks. + */ + + + +#if defined ALLEGRO_HAVE_INTTYPES_H + #include +#elif defined ALLEGRO_HAVE_STDINT_H + #include +#else + #error I dunno how to get the definitions of fixed-width integer types on your platform. Please report this to your friendly Allegro developer. +#endif + + + +#endif /* ifndef ASTDINT_H */ diff --git a/libsrc/allegro/include/allegro/system.h b/libsrc/allegro/include/allegro/system.h new file mode 100644 index 00000000000..ad89df129be --- /dev/null +++ b/libsrc/allegro/include/allegro/system.h @@ -0,0 +1,68 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * System level: initialization, cleanup, etc. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_SYSTEM_H +#define ALLEGRO_SYSTEM_H + +#include "base.h" +#include "unicode.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct RGB; +struct BITMAP; +struct GFX_VTABLE; + +#define ALLEGRO_ERROR_SIZE 256 + +AL_ARRAY(char, allegro_id); +AL_ARRAY(char, allegro_error); + + +#define SYSTEM_AUTODETECT 0 +#define SYSTEM_NONE AL_ID('N','O','N','E') + +#define MAKE_VERSION(a, b, c) (((a)<<16)|((b)<<8)|(c)) + +AL_FUNC(int, _install_allegro_version_check, (int system_id, int *errno_ptr, + AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void)))), int version)); + +AL_INLINE(int, install_allegro, (int system_id, int *errno_ptr, + AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void))))), +{ + return _install_allegro_version_check(system_id, errno_ptr, atexit_ptr, \ + MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)); +}) + +#define allegro_init() _install_allegro_version_check(SYSTEM_AUTODETECT, &errno, \ + (int (*)(void (*)(void)))atexit, \ + MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)) + +AL_FUNC(void, allegro_exit, (void)); + +AL_PRINTFUNC(void, allegro_message, (AL_CONST char *msg, ...), 1, 2); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_SYSTEM_H */ + + diff --git a/libsrc/allegro/include/allegro/unicode.h b/libsrc/allegro/include/allegro/unicode.h new file mode 100644 index 00000000000..20e9fc4ac6a --- /dev/null +++ b/libsrc/allegro/include/allegro/unicode.h @@ -0,0 +1,116 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Unicode support routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_UNICODE__H +#define ALLEGRO_UNICODE__H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define U_ASCII AL_ID('A','S','C','8') +#define U_ASCII_CP AL_ID('A','S','C','P') +#define U_UNICODE AL_ID('U','N','I','C') +#define U_UTF8 AL_ID('U','T','F','8') +#define U_CURRENT AL_ID('c','u','r','.') + +AL_FUNC(void, set_uformat, (int type)); +AL_FUNC(int, get_uformat, (void)); +AL_FUNC(void, register_uformat, (int type, AL_METHOD(int, u_getc, (AL_CONST char *s)), AL_METHOD(int, u_getx, (char **s)), AL_METHOD(int, u_setc, (char *s, int c)), AL_METHOD(int, u_width, (AL_CONST char *s)), AL_METHOD(int, u_cwidth, (int c)), AL_METHOD(int, u_isok, (int c)), int u_width_max)); +AL_FUNC(void, set_ucodepage, (AL_CONST unsigned short *table, AL_CONST unsigned short *extras)); + +AL_FUNC(int, need_uconvert, (AL_CONST char *s, int type, int newtype)); +AL_FUNC(int, uconvert_size, (AL_CONST char *s, int type, int newtype)); +AL_FUNC(void, do_uconvert, (AL_CONST char *s, int type, char *buf, int newtype, int size)); +AL_FUNC(char *, uconvert, (AL_CONST char *s, int type, char *buf, int newtype, int size)); +AL_FUNC(int, uwidth_max, (int type)); + +#define uconvert_ascii(s, buf) uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)) +#define uconvert_toascii(s, buf) uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)) + +#define EMPTY_STRING "\0\0\0" + +AL_ARRAY(char, empty_string); + +AL_FUNCPTR(int, ugetc, (AL_CONST char *s)); +AL_FUNCPTR(int, ugetx, (char **s)); +AL_FUNCPTR(int, ugetxc, (AL_CONST char **s)); +AL_FUNCPTR(int, usetc, (char *s, int c)); +AL_FUNCPTR(int, uwidth, (AL_CONST char *s)); +AL_FUNCPTR(int, ucwidth, (int c)); +AL_FUNCPTR(int, uisok, (int c)); +AL_FUNC(int, uoffset, (AL_CONST char *s, int idx)); +AL_FUNC(int, ugetat, (AL_CONST char *s, int idx)); +AL_FUNC(int, usetat, (char *s, int idx, int c)); +AL_FUNC(int, uinsert, (char *s, int idx, int c)); +AL_FUNC(int, uremove, (char *s, int idx)); +AL_FUNC(int, utolower, (int c)); +AL_FUNC(int, utoupper, (int c)); +AL_FUNC(int, uisspace, (int c)); +AL_FUNC(int, uisdigit, (int c)); +AL_FUNC(int, ustrsize, (AL_CONST char *s)); +AL_FUNC(int, ustrsizez, (AL_CONST char *s)); +AL_FUNC(char *, _ustrdup, (AL_CONST char *src, AL_METHOD(void *, malloc_func, (size_t)))); +AL_FUNC(char *, ustrzcpy, (char *dest, int size, AL_CONST char *src)); +AL_FUNC(char *, ustrzcat, (char *dest, int size, AL_CONST char *src)); +AL_FUNC(int, ustrlen, (AL_CONST char *s)); +AL_FUNC(int, ustrcmp, (AL_CONST char *s1, AL_CONST char *s2)); +AL_FUNC(char *, ustrzncpy, (char *dest, int size, AL_CONST char *src, int n)); +AL_FUNC(char *, ustrzncat, (char *dest, int size, AL_CONST char *src, int n)); +AL_FUNC(int, ustrncmp, (AL_CONST char *s1, AL_CONST char *s2, int n)); +AL_FUNC(int, ustricmp, (AL_CONST char *s1, AL_CONST char *s2)); +AL_FUNC(int, ustrnicmp, (AL_CONST char *s1, AL_CONST char *s2, int n)); +AL_FUNC(char *, ustrlwr, (char *s)); +AL_FUNC(char *, ustrupr, (char *s)); +AL_FUNC(char *, ustrchr, (AL_CONST char *s, int c)); +AL_FUNC(char *, ustrrchr, (AL_CONST char *s, int c)); +AL_FUNC(char *, ustrstr, (AL_CONST char *s1, AL_CONST char *s2)); +AL_FUNC(char *, ustrpbrk, (AL_CONST char *s, AL_CONST char *set)); +AL_FUNC(char *, ustrtok, (char *s, AL_CONST char *set)); +AL_FUNC(char *, ustrtok_r, (char *s, AL_CONST char *set, char **last)); +AL_FUNC(double, uatof, (AL_CONST char *s)); +AL_FUNC(long, ustrtol, (AL_CONST char *s, char **endp, int base)); +AL_FUNC(double, ustrtod, (AL_CONST char *s, char **endp)); +AL_FUNC(AL_CONST char *, ustrerror, (int err)); +AL_PRINTFUNC(int, uszprintf, (char *buf, int size, AL_CONST char *format, ...), 3, 4); +AL_FUNC(int, uvszprintf, (char *buf, int size, AL_CONST char *format, va_list args)); +AL_PRINTFUNC(int, usprintf, (char *buf, AL_CONST char *format, ...), 2, 3); + +#ifndef ustrdup + #ifdef FORTIFY + #define ustrdup(src) _ustrdup(src, Fortify_malloc) + #else + #define ustrdup(src) _ustrdup(src, malloc) + #endif +#endif + +#define ustrcpy(dest, src) ustrzcpy(dest, INT_MAX, src) +#define ustrcat(dest, src) ustrzcat(dest, INT_MAX, src) +#define ustrncpy(dest, src, n) ustrzncpy(dest, INT_MAX, src, n) +#define ustrncat(dest, src, n) ustrzncat(dest, INT_MAX, src, n) +#define uvsprintf(buf, format, args) uvszprintf(buf, INT_MAX, format, args) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_UNICODE__H */ + + diff --git a/libsrc/allegro/include/winalleg.h b/libsrc/allegro/include/winalleg.h new file mode 100644 index 00000000000..a9d2760ea1f --- /dev/null +++ b/libsrc/allegro/include/winalleg.h @@ -0,0 +1,93 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Windows header file for the Allegro library. + * + * It must be included by Allegro programs that need to use + * direct Win32 API calls and by Win32 programs that need to + * interface with Allegro. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef WIN_ALLEGRO_H +#define WIN_ALLEGRO_H + +#ifndef ALLEGRO_H + #error Please include allegro.h before winalleg.h! +#endif + +#ifdef ALLEGRO_SRC + #define WIN32_LEAN_AND_MEAN /* to save compilation time */ +#endif + + + +/* bodges to avoid conflicts between Allegro and Windows */ +#define BITMAP WINDOWS_BITMAP + +#if (!defined SCAN_EXPORT) && (!defined SCAN_DEPEND) + #ifdef ALLEGRO_AND_MFC + #ifdef DEBUGMODE + #define AL_ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } + #define AL_TRACE al_trace + #else + #define AL_ASSERT(condition) + #define AL_TRACE 1 ? (void) 0 : al_trace + #endif + + #undef TRACE + #undef ASSERT + + #include + #else + #include + #endif +#endif + +#define WINDOWS_RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + +#undef BITMAP +#undef RGB + + + +/* Allegro's Win32 specific interface */ +#ifdef __cplusplus + extern "C" { +#endif + + +/* GDI to DirectDraw routines */ +AL_FUNC(HDC, win_get_dc, (BITMAP *bmp)); +AL_FUNC(void, win_release_dc, (BITMAP *bmp, HDC dc)); + + +/* GDI routines */ +AL_FUNC(void, set_gdi_color_format, (void)); +AL_FUNC(void, set_palette_to_hdc, (HDC dc, PALETTE pal)); +AL_FUNC(HPALETTE, convert_palette_to_hpalette, (PALETTE pal)); +AL_FUNC(void, convert_hpalette_to_palette, (HPALETTE hpal, PALETTE pal)); +AL_FUNC(HBITMAP, convert_bitmap_to_hbitmap, (BITMAP *bitmap)); +AL_FUNC(BITMAP *, convert_hbitmap_to_bitmap, (HBITMAP bitmap)); +AL_FUNC(void, draw_to_hdc, (HDC dc, BITMAP *bitmap, int x, int y)); +AL_FUNC(void, blit_to_hdc, (BITMAP *bitmap, HDC dc, int src_x, int src_y, int dest_x, int dest_y, int w, int h)); +AL_FUNC(void, stretch_blit_to_hdc, (BITMAP *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)); +AL_FUNC(void, blit_from_hdc, (HDC dc, BITMAP *bitmap, int src_x, int src_y, int dest_x, int dest_y, int w, int h)); +AL_FUNC(void, stretch_blit_from_hdc, (HDC hdc, BITMAP *bitmap, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef WIN_ALLEGRO_H */ diff --git a/libsrc/allegro/src/allegro.c b/libsrc/allegro/src/allegro.c new file mode 100644 index 00000000000..453c8a42381 --- /dev/null +++ b/libsrc/allegro/src/allegro.c @@ -0,0 +1,593 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Assorted globals and setup/cleanup routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#define PREFIX_I "al-main INFO: " +#define PREFIX_W "al-main WARNING: " +#define PREFIX_E "al-main ERROR: " + +#ifdef ALLEGRO_AMIGA + #define LOGFILE "RAM:allegro.log" +#else + #define LOGFILE "allegro.log" +#endif + + +/* in case you want to report version numbers */ +char allegro_id[] = "Allegro " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR; + + +/* error message for sound and gfx init routines */ +char allegro_error[ALLEGRO_ERROR_SIZE] = EMPTY_STRING; + + +/* error value, which will work even with DLL linkage */ +int *allegro_errno = NULL; + + +/* flag for how many times we have been initialised */ +int _allegro_count = 0; + + +/* flag to know whether we are being called by the exit mechanism */ +int _allegro_in_exit = FALSE; + + +/* info about the current graphics drawing mode */ +int _drawing_mode = DRAW_MODE_SOLID; + +BITMAP *_drawing_pattern = NULL; + +int _drawing_x_anchor = 0; +int _drawing_y_anchor = 0; + +unsigned int _drawing_x_mask = 0; +unsigned int _drawing_y_mask = 0; + + +/* default palette structures */ +PALETTE black_palette; +PALETTE _current_palette; + +int _current_palette_changed = 0xFFFFFFFF; + + +PALETTE desktop_palette = +{ + { 63, 63, 63, 0 }, { 63, 0, 0, 0 }, { 0, 63, 0, 0 }, { 63, 63, 0, 0 }, + { 0, 0, 63, 0 }, { 63, 0, 63, 0 }, { 0, 63, 63, 0 }, { 16, 16, 16, 0 }, + { 31, 31, 31, 0 }, { 63, 31, 31, 0 }, { 31, 63, 31, 0 }, { 63, 63, 31, 0 }, + { 31, 31, 63, 0 }, { 63, 31, 63, 0 }, { 31, 63, 63, 0 }, { 0, 0, 0, 0 } +}; + + +PALETTE default_palette = +{ + { 0, 0, 0, 0 }, { 0, 0, 42, 0 }, { 0, 42, 0, 0 }, { 0, 42, 42, 0 }, + { 42, 0, 0, 0 }, { 42, 0, 42, 0 }, { 42, 21, 0, 0 }, { 42, 42, 42, 0 }, + { 21, 21, 21, 0 }, { 21, 21, 63, 0 }, { 21, 63, 21, 0 }, { 21, 63, 63, 0 }, + { 63, 21, 21, 0 }, { 63, 21, 63, 0 }, { 63, 63, 21, 0 }, { 63, 63, 63, 0 }, + { 0, 0, 0, 0 }, { 5, 5, 5, 0 }, { 8, 8, 8, 0 }, { 11, 11, 11, 0 }, + { 14, 14, 14, 0 }, { 17, 17, 17, 0 }, { 20, 20, 20, 0 }, { 24, 24, 24, 0 }, + { 28, 28, 28, 0 }, { 32, 32, 32, 0 }, { 36, 36, 36, 0 }, { 40, 40, 40, 0 }, + { 45, 45, 45, 0 }, { 50, 50, 50, 0 }, { 56, 56, 56, 0 }, { 63, 63, 63, 0 }, + { 0, 0, 63, 0 }, { 16, 0, 63, 0 }, { 31, 0, 63, 0 }, { 47, 0, 63, 0 }, + { 63, 0, 63, 0 }, { 63, 0, 47, 0 }, { 63, 0, 31, 0 }, { 63, 0, 16, 0 }, + { 63, 0, 0, 0 }, { 63, 16, 0, 0 }, { 63, 31, 0, 0 }, { 63, 47, 0, 0 }, + { 63, 63, 0, 0 }, { 47, 63, 0, 0 }, { 31, 63, 0, 0 }, { 16, 63, 0, 0 }, + { 0, 63, 0, 0 }, { 0, 63, 16, 0 }, { 0, 63, 31, 0 }, { 0, 63, 47, 0 }, + { 0, 63, 63, 0 }, { 0, 47, 63, 0 }, { 0, 31, 63, 0 }, { 0, 16, 63, 0 }, + { 31, 31, 63, 0 }, { 39, 31, 63, 0 }, { 47, 31, 63, 0 }, { 55, 31, 63, 0 }, + { 63, 31, 63, 0 }, { 63, 31, 55, 0 }, { 63, 31, 47, 0 }, { 63, 31, 39, 0 }, + { 63, 31, 31, 0 }, { 63, 39, 31, 0 }, { 63, 47, 31, 0 }, { 63, 55, 31, 0 }, + { 63, 63, 31, 0 }, { 55, 63, 31, 0 }, { 47, 63, 31, 0 }, { 39, 63, 31, 0 }, + { 31, 63, 31, 0 }, { 31, 63, 39, 0 }, { 31, 63, 47, 0 }, { 31, 63, 55, 0 }, + { 31, 63, 63, 0 }, { 31, 55, 63, 0 }, { 31, 47, 63, 0 }, { 31, 39, 63, 0 }, + { 45, 45, 63, 0 }, { 49, 45, 63, 0 }, { 54, 45, 63, 0 }, { 58, 45, 63, 0 }, + { 63, 45, 63, 0 }, { 63, 45, 58, 0 }, { 63, 45, 54, 0 }, { 63, 45, 49, 0 }, + { 63, 45, 45, 0 }, { 63, 49, 45, 0 }, { 63, 54, 45, 0 }, { 63, 58, 45, 0 }, + { 63, 63, 45, 0 }, { 58, 63, 45, 0 }, { 54, 63, 45, 0 }, { 49, 63, 45, 0 }, + { 45, 63, 45, 0 }, { 45, 63, 49, 0 }, { 45, 63, 54, 0 }, { 45, 63, 58, 0 }, + { 45, 63, 63, 0 }, { 45, 58, 63, 0 }, { 45, 54, 63, 0 }, { 45, 49, 63, 0 }, + { 0, 0, 28, 0 }, { 7, 0, 28, 0 }, { 14, 0, 28, 0 }, { 21, 0, 28, 0 }, + { 28, 0, 28, 0 }, { 28, 0, 21, 0 }, { 28, 0, 14, 0 }, { 28, 0, 7, 0 }, + { 28, 0, 0, 0 }, { 28, 7, 0, 0 }, { 28, 14, 0, 0 }, { 28, 21, 0, 0 }, + { 28, 28, 0, 0 }, { 21, 28, 0, 0 }, { 14, 28, 0, 0 }, { 7, 28, 0, 0 }, + { 0, 28, 0, 0 }, { 0, 28, 7, 0 }, { 0, 28, 14, 0 }, { 0, 28, 21, 0 }, + { 0, 28, 28, 0 }, { 0, 21, 28, 0 }, { 0, 14, 28, 0 }, { 0, 7, 28, 0 }, + { 14, 14, 28, 0 }, { 17, 14, 28, 0 }, { 21, 14, 28, 0 }, { 24, 14, 28, 0 }, + { 28, 14, 28, 0 }, { 28, 14, 24, 0 }, { 28, 14, 21, 0 }, { 28, 14, 17, 0 }, + { 28, 14, 14, 0 }, { 28, 17, 14, 0 }, { 28, 21, 14, 0 }, { 28, 24, 14, 0 }, + { 28, 28, 14, 0 }, { 24, 28, 14, 0 }, { 21, 28, 14, 0 }, { 17, 28, 14, 0 }, + { 14, 28, 14, 0 }, { 14, 28, 17, 0 }, { 14, 28, 21, 0 }, { 14, 28, 24, 0 }, + { 14, 28, 28, 0 }, { 14, 24, 28, 0 }, { 14, 21, 28, 0 }, { 14, 17, 28, 0 }, + { 20, 20, 28, 0 }, { 22, 20, 28, 0 }, { 24, 20, 28, 0 }, { 26, 20, 28, 0 }, + { 28, 20, 28, 0 }, { 28, 20, 26, 0 }, { 28, 20, 24, 0 }, { 28, 20, 22, 0 }, + { 28, 20, 20, 0 }, { 28, 22, 20, 0 }, { 28, 24, 20, 0 }, { 28, 26, 20, 0 }, + { 28, 28, 20, 0 }, { 26, 28, 20, 0 }, { 24, 28, 20, 0 }, { 22, 28, 20, 0 }, + { 20, 28, 20, 0 }, { 20, 28, 22, 0 }, { 20, 28, 24, 0 }, { 20, 28, 26, 0 }, + { 20, 28, 28, 0 }, { 20, 26, 28, 0 }, { 20, 24, 28, 0 }, { 20, 22, 28, 0 }, + { 0, 0, 16, 0 }, { 4, 0, 16, 0 }, { 8, 0, 16, 0 }, { 12, 0, 16, 0 }, + { 16, 0, 16, 0 }, { 16, 0, 12, 0 }, { 16, 0, 8, 0 }, { 16, 0, 4, 0 }, + { 16, 0, 0, 0 }, { 16, 4, 0, 0 }, { 16, 8, 0, 0 }, { 16, 12, 0, 0 }, + { 16, 16, 0, 0 }, { 12, 16, 0, 0 }, { 8, 16, 0, 0 }, { 4, 16, 0, 0 }, + { 0, 16, 0, 0 }, { 0, 16, 4, 0 }, { 0, 16, 8, 0 }, { 0, 16, 12, 0 }, + { 0, 16, 16, 0 }, { 0, 12, 16, 0 }, { 0, 8, 16, 0 }, { 0, 4, 16, 0 }, + { 8, 8, 16, 0 }, { 10, 8, 16, 0 }, { 12, 8, 16, 0 }, { 14, 8, 16, 0 }, + { 16, 8, 16, 0 }, { 16, 8, 14, 0 }, { 16, 8, 12, 0 }, { 16, 8, 10, 0 }, + { 16, 8, 8, 0 }, { 16, 10, 8, 0 }, { 16, 12, 8, 0 }, { 16, 14, 8, 0 }, + { 16, 16, 8, 0 }, { 14, 16, 8, 0 }, { 12, 16, 8, 0 }, { 10, 16, 8, 0 }, + { 8, 16, 8, 0 }, { 8, 16, 10, 0 }, { 8, 16, 12, 0 }, { 8, 16, 14, 0 }, + { 8, 16, 16, 0 }, { 8, 14, 16, 0 }, { 8, 12, 16, 0 }, { 8, 10, 16, 0 }, + { 11, 11, 16, 0 }, { 12, 11, 16, 0 }, { 13, 11, 16, 0 }, { 15, 11, 16, 0 }, + { 16, 11, 16, 0 }, { 16, 11, 15, 0 }, { 16, 11, 13, 0 }, { 16, 11, 12, 0 }, + { 16, 11, 11, 0 }, { 16, 12, 11, 0 }, { 16, 13, 11, 0 }, { 16, 15, 11, 0 }, + { 16, 16, 11, 0 }, { 15, 16, 11, 0 }, { 13, 16, 11, 0 }, { 12, 16, 11, 0 }, + { 11, 16, 11, 0 }, { 11, 16, 12, 0 }, { 11, 16, 13, 0 }, { 11, 16, 15, 0 }, + { 11, 16, 16, 0 }, { 11, 15, 16, 0 }, { 11, 13, 16, 0 }, { 11, 12, 16, 0 }, + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 63, 63, 63, 0 } +}; + + +/* colors for the standard GUI dialogs (alerts, file selector, etc) */ +int gui_fg_color = 255; +int gui_mg_color = 8; +int gui_bg_color = 0; + + +/* a block of temporary working memory */ +void *_scratch_mem = NULL; +int _scratch_mem_size = 0; + + +/* SVGA bank switching tables */ +int _last_bank_1 = -1; +int _last_bank_2 = -1; +int *_gfx_bank = NULL; + + +/* debugging stuff */ +static int debug_assert_virgin = TRUE; +static int debug_trace_virgin = TRUE; + +static FILE *assert_file = NULL; +static FILE *trace_file = NULL; + +static int (*assert_handler)(AL_CONST char *msg) = NULL; +int (*_al_trace_handler)(AL_CONST char *msg) = NULL; + + +/* Module linking system stuff: if an object file is linked in, then its + * constructor function is executed; this function should fill in the + * data structures below (declared in aintern.h). If the module is not + * linked in, then the structure pointers will be null, so we don't need + * to bother with that bit of code elsewhere. + */ +struct _AL_LINKER_MIDI *_al_linker_midi = NULL; +struct _AL_LINKER_MOUSE *_al_linker_mouse = NULL; + + +/* dynamic registration system for cleanup code */ +struct al_exit_func { + void (*funcptr)(void); + AL_CONST char *desc; + struct al_exit_func *next; +}; + +static struct al_exit_func *exit_func_list = NULL; + + + +/* _add_exit_func: + * Adds a function to the list that need to be called by allegro_exit(). + * `desc' should point to a statically allocated string to help with + * debugging. + */ +void _add_exit_func(void (*func)(void), AL_CONST char *desc) +{ + struct al_exit_func *n; + + for (n = exit_func_list; n; n = n->next) + if (n->funcptr == func) + return; + + n = _AL_MALLOC(sizeof(struct al_exit_func)); + if (!n) + return; + + n->next = exit_func_list; + n->funcptr = func; + n->desc = desc; + exit_func_list = n; +} + + + +/* _remove_exit_func: + * Removes a function from the list that need to be called by allegro_exit(). + */ +void _remove_exit_func(void (*func)(void)) +{ + struct al_exit_func *iter = exit_func_list, *prev = NULL; + + while (iter) { + if (iter->funcptr == func) { + if (prev) + prev->next = iter->next; + else + exit_func_list = iter->next; + _AL_FREE(iter); + return; + } + prev = iter; + iter = iter->next; + } +} + + + +/* allegro_exit_stub: + * Stub function registered by the library via atexit. + */ +static void allegro_exit_stub(void) +{ + _allegro_in_exit = TRUE; + + allegro_exit(); +} + + + +/* _install_allegro: + * Initialises the Allegro library, activating the system driver. + */ +static int _install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)(void (*func)(void))) +{ + RGB black_rgb = {0, 0, 0, 0}; + char tmp1[64], tmp2[64]; + int i; + + #ifndef ALLEGRO_USE_CONSTRUCTOR + /* call constructor functions manually */ + _register_bitmap_file_type_init(); + #endif + + if (errno_ptr) + allegro_errno = errno_ptr; + else + allegro_errno = &errno; + + /* set up default palette structures */ + for (i=0; i<256; i++) + black_palette[i] = black_rgb; + + for (i=16; i<256; i++) + desktop_palette[i] = desktop_palette[i & 15]; + + /* lock some important variables */ + LOCK_VARIABLE(_last_bank_1); + LOCK_VARIABLE(_last_bank_2); + LOCK_VARIABLE(_gfx_bank); + LOCK_VARIABLE(_drawing_mode); + LOCK_VARIABLE(_drawing_pattern); + LOCK_VARIABLE(_drawing_x_anchor); + LOCK_VARIABLE(_drawing_y_anchor); + LOCK_VARIABLE(_drawing_x_mask); + LOCK_VARIABLE(_drawing_y_mask); + LOCK_VARIABLE(_current_palette); + + /* initialise the system driver */ + usetc(allegro_error, 0); + + /* install shutdown handler */ + if (_allegro_count == 0) { + if (atexit_ptr) + atexit_ptr(allegro_exit_stub); + } + + _allegro_count++; + + TRACE(PREFIX_I "Allegro initialised (instance %d)\n", _allegro_count); + return 0; +} + + + +/* _install_allegro_version_check: + * Initialises the Allegro library, but return with an error if an + * incompatible version is found. + */ +int _install_allegro_version_check(int system_id, int *errno_ptr, + int (*atexit_ptr)(void (*func)(void)), int version) +{ + int r = _install_allegro(system_id, errno_ptr, atexit_ptr); + + int build_wip = version & 255; + int build_ver = version & ~255; + + int version_ok; + + if (r != 0) { + /* failed */ + return r; + } + +#if ALLEGRO_SUB_VERSION & 1 + /* This is a WIP runtime, so enforce strict compatibility. */ + version_ok = version == MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION); +#else + /* This is a stable runtime, so the runtime should be at least as new + * as the build headers (otherwise we may get a crash, since some + * functions may have been used which aren't available in this runtime). + */ + version_ok = (MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, 0) == build_ver) && + (ALLEGRO_WIP_VERSION >= build_wip); +#endif + + if (!version_ok) { + uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, + "The detected dynamic Allegro library (%d.%d.%d) is " + "not compatible with this program (%d.%d.%d).", + ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION, + build_ver >> 16, (build_ver >> 8) & 255, build_wip); + return -1; + } + return 0; +} + + + +/* allegro_exit: + * Closes down the Allegro system. + */ +void allegro_exit(void) +{ + while (exit_func_list) { + void (*func)(void) = exit_func_list->funcptr; + _remove_exit_func(func); + (*func)(); + } + + if (_scratch_mem) { + _AL_FREE(_scratch_mem); + _scratch_mem = NULL; + _scratch_mem_size = 0; + } +} + + + +/* allegro_message: + * Displays a message in whatever form the current platform requires. + */ +void allegro_message(AL_CONST char *msg, ...) +{ + char *buf = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE); + char *tmp = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE); + va_list ap; + ASSERT(msg); + va_start(ap, msg); + uvszprintf(buf, ALLEGRO_MESSAGE_SIZE, msg, ap); + va_end(ap); + + fputs(uconvert(buf, U_CURRENT, tmp, U_ASCII_CP, ALLEGRO_MESSAGE_SIZE), stdout); + + _AL_FREE(buf); + _AL_FREE(tmp); +} + + + +/* debug_exit: + * Closes the debugging output files. + */ +static void debug_exit(void) +{ + if (assert_file) { + fclose(assert_file); + assert_file = NULL; + } + + if (trace_file) { + fclose(trace_file); + trace_file = NULL; + } + + debug_assert_virgin = TRUE; + debug_trace_virgin = TRUE; + + _remove_exit_func(debug_exit); +} + + + +/* al_assert: + * Raises an assert (uses ASCII strings). + */ +void al_assert(AL_CONST char *file, int line) +{ + static int asserted = FALSE; + int olderr = errno; + char buf[128]; + char *s; + + if (asserted) + return; + + /* todo, some day: use snprintf (C99) */ + sprintf(buf, "Assert failed at line %d of %s", line, file); + + if (assert_handler) { + if (assert_handler(buf)) + return; + } + + if (debug_assert_virgin) { + s = getenv("ALLEGRO_ASSERT"); + + if (s) + assert_file = fopen(s, "w"); + else + assert_file = NULL; + + if (debug_trace_virgin) + _add_exit_func(debug_exit, "debug_exit"); + + debug_assert_virgin = FALSE; + } + + if (assert_file) { + fprintf(assert_file, "%s\n", buf); + fflush(assert_file); + } + else { + asserted = TRUE; + + { + allegro_exit(); + fprintf(stderr, "%s\n", buf); + abort(); + } + } + + errno = olderr; +} + + + +/* al_trace: + * Outputs a trace message (uses ASCII strings). + */ +void al_trace(AL_CONST char *msg, ...) +{ + int olderr = errno; + char buf[512]; + char *s; + + /* todo, some day: use vsnprintf (C99) */ + va_list ap; + va_start(ap, msg); + vsprintf(buf, msg, ap); + va_end(ap); + + if (_al_trace_handler) { + if (_al_trace_handler(buf)) + return; + } + + if (debug_trace_virgin) { + s = getenv("ALLEGRO_TRACE"); + + if (s) + trace_file = fopen(s, "w"); + else + trace_file = fopen(LOGFILE, "w"); + + if (debug_assert_virgin) + _add_exit_func(debug_exit, "debug_exit"); + + debug_trace_virgin = FALSE; + } + + if (trace_file) { + fwrite(buf, sizeof(char), strlen(buf), trace_file); + fflush(trace_file); + } + + errno = olderr; +} + + + +/* register_assert_handler: + * Installs a user handler for assert failures. + */ +void register_assert_handler(int (*handler)(AL_CONST char *msg)) +{ + assert_handler = handler; +} + + + +/* register_trace_handler: + * Installs a user handler for trace output. + */ +void register_trace_handler(int (*handler)(AL_CONST char *msg)) +{ + _al_trace_handler = handler; +} + + + +/* _al_malloc: + * Wrapper for when a program needs to manipulate memory that has been + * allocated by the Allegro DLL. + */ +void *_al_malloc(size_t size) +{ + return malloc(size); +} + + + +/* _al_free: + * Wrapper for when a program needs to manipulate memory that has been + * allocated by the Allegro DLL. + */ +void _al_free(void *mem) +{ + free(mem); +} + + + +/* _al_realloc: + * Wrapper for when a program needs to manipulate memory that has been + * allocated by the Allegro DLL. + */ +void *_al_realloc(void *mem, size_t size) +{ + return realloc(mem, size); +} + + + +/* _al_strdup: + * Wrapper for when a program needs to duplicate a string in a way that + * uses any user overloaded memory allocation system in use. + * The result of this function _must_ be freed with _AL_FREE(). + */ +char *_al_strdup(AL_CONST char *string) +{ + char *newstring = _AL_MALLOC(strlen(string) + 1); + + if (newstring) + strcpy(newstring, string); + + return newstring; +} + diff --git a/libsrc/allegro/src/blit.c b/libsrc/allegro/src/blit.c new file mode 100644 index 00000000000..dd4d29f90dc --- /dev/null +++ b/libsrc/allegro/src/blit.c @@ -0,0 +1,760 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Blitting functions. + * + * By Shawn Hargreaves. + * + * Dithering code by James Hyman. + * + * Transparency preserving code by Elias Pschernig. + * + * See readme.txt for copyright information. + */ + + +#include +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* get_replacement_mask_color: + * Helper function to get a replacement color for the bitmap's mask color. + */ +static int get_replacement_mask_color(BITMAP *bmp) +{ + int depth, c, g = 0; + + depth = bitmap_color_depth(bmp); + + if (depth == 8) { + if (rgb_map) + return rgb_map->data[31][1][31]; + else + return bestfit_color(_current_palette, 63, 1, 63); + } + else { + do + c = makecol_depth(depth, 255, ++g, 255); + while (c == bitmap_mask_color(bmp)); + + return c; + } +} + + + +/* blit_from_256: + * Expands 256 color images onto a truecolor destination. + */ +static void blit_from_256(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + #ifdef ALLEGRO_COLOR8 + + int *dest_palette_color; + uintptr_t s, d; + unsigned char *ss; + int x, y, c, rc; + + /* lookup table avoids repeated color format conversions */ + if (_color_conv & COLORCONV_KEEP_TRANS) { + dest_palette_color = _AL_MALLOC_ATOMIC(256*sizeof(int)); + memcpy(dest_palette_color, _palette_expansion_table(bitmap_color_depth(dest)), 256*sizeof(int)); + + rc = get_replacement_mask_color(dest); + + dest_palette_color[MASK_COLOR_8] = bitmap_mask_color(dest); + + for (c=0; c<256; c++) { + if ((c != MASK_COLOR_8) && + (dest_palette_color[c] == bitmap_mask_color(dest))) + dest_palette_color[c] = rc; + } + } + else + dest_palette_color = _palette_expansion_table(bitmap_color_depth(dest)); + + /* worker macro */ + #define EXPAND_BLIT(bits, dsize) \ + { \ + if (is_memory_bitmap(src)) { \ + /* fast version when reading from memory bitmap */ \ + bmp_select(dest); \ + \ + for (y=0; yline[s_y+y] + s_x; \ + d = bmp_write_line(dest, d_y+y) + d_x*dsize; \ + \ + for (x=0; x 255) + n[i] = 255; + + if (n[i] < 0) + n[i] = 0; + } + + /* find the nearest matching colour */ + nc = makecol8(n[0], n[1], n[2]); + if (_color_conv & COLORCONV_KEEP_TRANS) { + if (c == bitmap_mask_color(src)) + putpixel(dest, d_x+x, d_y+y, bitmap_mask_color(dest)); + else if (nc == bitmap_mask_color(dest)) + putpixel(dest, d_x+x, d_y+y, rc); + else + putpixel(dest, d_x+x, d_y+y, nc); + } + else { + putpixel(dest, d_x+x, d_y+y, nc); + } + v[0] = getr8(nc); + v[1] = getg8(nc); + v[2] = getb8(nc); + + /* calculate the error and store it */ + for (i=0; i<3; i++) { + e[i] = n[i] - v[i]; + errpixel[i] = (int)((e[i] * 3)/8); + errnextline[i][x] += errpixel[i]; + + if (x != w-1) + errnextline[i][x+1] = (int)(e[i]/4); + } + } + + /* update error buffers */ + for (i=0; i<3; i++) { + memcpy(errline[i], errnextline[i], sizeof(int) * w); + memset(errnextline[i], 0, sizeof(int) * w); + } + } + + _drawing_mode = prev_drawmode; + + getout: + + for (i=0; i<3; i++) { + if (errline[i]) + _AL_FREE(errline[i]); + + if (errnextline[i]) + _AL_FREE(errnextline[i]); + } +} + +#endif + + + +/* blit_from_15: + * Converts 15 bpp images onto some other destination format. + */ +static void blit_from_15(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + #ifdef ALLEGRO_COLOR16 + + int x, y, c, r, g, b; + uintptr_t s, d; + + switch (bitmap_color_depth(dest)) { + + #ifdef ALLEGRO_COLOR8 + case 8: + if (_color_conv & COLORCONV_DITHER_PAL) + dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); + else + CONVERT_BLIT(15, sizeof(int16_t), 8, 1) + break; + #endif + + case 16: + CONVERT_BLIT(15, sizeof(int16_t), 16, sizeof(int16_t)) + break; + + #ifdef ALLEGRO_COLOR24 + case 24: + CONVERT_BLIT(15, sizeof(int16_t), 24, 3) + break; + #endif + + #ifdef ALLEGRO_COLOR32 + case 32: + CONVERT_BLIT(15, sizeof(int16_t), 32, sizeof(int32_t)) + break; + #endif + } + + #endif +} + + + +/* blit_from_16: + * Converts 16 bpp images onto some other destination format. + */ +static void blit_from_16(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + #ifdef ALLEGRO_COLOR16 + + int x, y, c, r, g, b; + uintptr_t s, d; + + switch (bitmap_color_depth(dest)) { + + #ifdef ALLEGRO_COLOR8 + case 8: + if (_color_conv & COLORCONV_DITHER_PAL) + dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); + else + CONVERT_BLIT(16, sizeof(int16_t), 8, 1) + break; + #endif + + case 15: + CONVERT_BLIT(16, sizeof(int16_t), 15, sizeof(int16_t)) + break; + + #ifdef ALLEGRO_COLOR24 + case 24: + CONVERT_BLIT(16, sizeof(int16_t), 24, 3) + break; + #endif + + #ifdef ALLEGRO_COLOR32 + case 32: + CONVERT_BLIT(16, sizeof(int16_t), 32, sizeof(int32_t)) + break; + #endif + } + + #endif +} + + + +/* blit_from_24: + * Converts 24 bpp images onto some other destination format. + */ +static void blit_from_24(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + #ifdef ALLEGRO_COLOR24 + + int x, y, c, r, g, b; + uintptr_t s, d; + + switch (bitmap_color_depth(dest)) { + + #ifdef ALLEGRO_COLOR8 + case 8: + if (_color_conv & COLORCONV_DITHER_PAL) + dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); + else + CONVERT_BLIT(24, 3, 8, 1); + break; + #endif + + #ifdef ALLEGRO_COLOR16 + case 15: + if (_color_conv & COLORCONV_DITHER_HI) + CONVERT_DITHER_BLIT(24, 3, 15, sizeof(int16_t)) + else + CONVERT_BLIT(24, 3, 15, sizeof(int16_t)) + break; + + case 16: + if (_color_conv & COLORCONV_DITHER_HI) + CONVERT_DITHER_BLIT(24, 3, 16, sizeof(int16_t)) + else + CONVERT_BLIT(24, 3, 16, sizeof(int16_t)) + break; + #endif + + #ifdef ALLEGRO_COLOR32 + case 32: + CONVERT_BLIT(24, 3, 32, sizeof(int32_t)) + break; + #endif + } + + #endif +} + + + +/* blit_from_32: + * Converts 32 bpp images onto some other destination format. + */ +static void blit_from_32(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + #ifdef ALLEGRO_COLOR32 + + int x, y, c, r, g, b; + uintptr_t s, d; + + switch (bitmap_color_depth(dest)) { + + #ifdef ALLEGRO_COLOR8 + case 8: + if (_color_conv & COLORCONV_DITHER_PAL) + dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); + else + CONVERT_BLIT(32, sizeof(int32_t), 8, 1) + break; + #endif + + #ifdef ALLEGRO_COLOR16 + case 15: + if (_color_conv & COLORCONV_DITHER_HI) + CONVERT_DITHER_BLIT(32, sizeof(int32_t), 15, sizeof(int16_t)) + else + CONVERT_BLIT(32, sizeof(int32_t), 15, sizeof(int16_t)) + break; + + case 16: + if (_color_conv & COLORCONV_DITHER_HI) + CONVERT_DITHER_BLIT(32, sizeof(int32_t), 16, sizeof(int16_t)) + else + CONVERT_BLIT(32, sizeof(int32_t), 16, sizeof(int16_t)) + break; + #endif + + #ifdef ALLEGRO_COLOR24 + case 24: + CONVERT_BLIT(32, sizeof(int32_t), 24, 3) + break; + #endif + } + + #endif +} + + + +/* blit_to_or_from_modex: + * Converts between truecolor and planar mode-X bitmaps. This function is + * painfully slow, but I don't think it is something that people will need + * to do very often... + */ +static void blit_to_or_from_modex(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + #ifdef ALLEGRO_GFX_HAS_VGA + + int x, y, c, r, g, b; + int src_depth = bitmap_color_depth(src); + int dest_depth = bitmap_color_depth(dest); + + int prev_drawmode = _drawing_mode; + _drawing_mode = DRAW_MODE_SOLID; + + if ((src_depth != 8) && (_color_conv & COLORCONV_DITHER_PAL)) + dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); + else { + for (y=0; yid & BMP_ID_NOBLIT) { + /* with single-banked cards we have to use a temporary bitmap */ + tmp = create_bitmap(w, h); + if (tmp) { + src->vtable->blit_to_memory(src, tmp, s_x, s_y, 0, 0, w, h); + dest->vtable->blit_from_memory(tmp, dest, 0, 0, d_x, d_y, w, h); + destroy_bitmap(tmp); + } + } + else { + /* check which way round to do the blit */ + sx = s_x + src->x_ofs; + sy = s_y + src->y_ofs; + + dx = d_x + dest->x_ofs; + dy = d_y + dest->y_ofs; + + if ((sx+w <= dx) || (dx+w <= sx) || (sy+h <= dy) || (dy+h <= sy)) + dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); + else if ((sy > dy) || ((sy == dy) && (sx > dx))) + dest->vtable->blit_to_self_forward(src, dest, s_x, s_y, d_x, d_y, w, h); + else if ((sx != dx) || (sy != dy)) + dest->vtable->blit_to_self_backward(src, dest, s_x, s_y, d_x, d_y, w, h); + } +} + + + +/* helper for clipping a blit rectangle */ +#define BLIT_CLIP() \ + /* check for ridiculous cases */ \ + if ((s_x >= src->w) || (s_y >= src->h) || \ + (d_x >= dest->cr) || (d_y >= dest->cb)) \ + return; \ + \ + /* clip src left */ \ + if (s_x < 0) { \ + w += s_x; \ + d_x -= s_x; \ + s_x = 0; \ + } \ + \ + /* clip src top */ \ + if (s_y < 0) { \ + h += s_y; \ + d_y -= s_y; \ + s_y = 0; \ + } \ + \ + /* clip src right */ \ + if (s_x+w > src->w) \ + w = src->w - s_x; \ + \ + /* clip src bottom */ \ + if (s_y+h > src->h) \ + h = src->h - s_y; \ + \ + /* clip dest left */ \ + if (d_x < dest->cl) { \ + d_x -= dest->cl; \ + w += d_x; \ + s_x -= d_x; \ + d_x = dest->cl; \ + } \ + \ + /* clip dest top */ \ + if (d_y < dest->ct) { \ + d_y -= dest->ct; \ + h += d_y; \ + s_y -= d_y; \ + d_y = dest->ct; \ + } \ + \ + /* clip dest right */ \ + if (d_x+w > dest->cr) \ + w = dest->cr - d_x; \ + \ + /* clip dest bottom */ \ + if (d_y+h > dest->cb) \ + h = dest->cb - d_y; \ + \ + /* bottle out if zero size */ \ + if ((w <= 0) || (h <= 0)) \ + return; + + + +/* blit: + * Copies an area of the source bitmap to the destination bitmap. s_x and + * s_y give the top left corner of the area of the source bitmap to copy, + * and d_x and d_y give the position in the destination bitmap. w and h + * give the size of the area to blit. This routine respects the clipping + * rectangle of the destination bitmap, and will work correctly even when + * the two memory areas overlap (ie. src and dest are the same). + */ +void blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + ASSERT(src); + ASSERT(dest); + BLIT_CLIP(); + + if (src->vtable->color_depth != dest->vtable->color_depth) { + /* need to do a color conversion */ + dest->vtable->blit_between_formats(src, dest, s_x, s_y, d_x, d_y, w, h); + } + else if (is_same_bitmap(src, dest)) { + /* special handling for overlapping regions */ + blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); + } + else if (is_video_bitmap(dest)) { + /* drawing onto video bitmaps */ + if (is_video_bitmap(src)) + dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); + else if (is_system_bitmap(src)) + dest->vtable->blit_from_system(src, dest, s_x, s_y, d_x, d_y, w, h); + else + dest->vtable->blit_from_memory(src, dest, s_x, s_y, d_x, d_y, w, h); + } + else if (is_system_bitmap(dest)) { + /* drawing onto system bitmaps */ + if (is_video_bitmap(src)) + src->vtable->blit_to_system(src, dest, s_x, s_y, d_x, d_y, w, h); + else if (is_system_bitmap(src)) + dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); + else + dest->vtable->blit_from_memory(src, dest, s_x, s_y, d_x, d_y, w, h); + } + else { + /* drawing onto memory bitmaps */ + if ((is_video_bitmap(src)) || (is_system_bitmap(src))) + src->vtable->blit_to_memory(src, dest, s_x, s_y, d_x, d_y, w, h); + else + dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); + } +} + +END_OF_FUNCTION(blit); + + + +/* masked_blit: + * Version of blit() that skips zero pixels. The source must be a memory + * bitmap, and the source and dest regions must not overlap. + */ +void masked_blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) +{ + ASSERT(src); + ASSERT(dest); + ASSERT(src->vtable->color_depth == dest->vtable->color_depth); + + BLIT_CLIP(); + + dest->vtable->masked_blit(src, dest, s_x, s_y, d_x, d_y, w, h); +} diff --git a/libsrc/allegro/src/bmp.c b/libsrc/allegro/src/bmp.c new file mode 100644 index 00000000000..30080ae1270 --- /dev/null +++ b/libsrc/allegro/src/bmp.c @@ -0,0 +1,873 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * BMP reader. + * + * By Seymour Shlien. + * + * OS/2 BMP support and BMP save function by Jonas Petersen. + * + * See readme.txt for copyright information. + */ + + +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#define BI_BITFIELDS 3 + +#define OS2INFOHEADERSIZE 12 +#define WININFOHEADERSIZE 40 + + +typedef struct BITMAPFILEHEADER +{ + unsigned long bfType; + unsigned long bfSize; + unsigned short bfReserved1; + unsigned short bfReserved2; + unsigned long bfOffBits; +} BITMAPFILEHEADER; + + +/* Used for both OS/2 and Windows BMP. + * Contains only the parameters needed to load the image + */ +typedef struct BITMAPINFOHEADER +{ + unsigned long biWidth; + signed long biHeight; + unsigned short biBitCount; + unsigned long biCompression; +} BITMAPINFOHEADER; + + +typedef struct WINBMPINFOHEADER /* size: 40 */ +{ + unsigned long biWidth; + signed long biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + unsigned long biCompression; + unsigned long biSizeImage; + unsigned long biXPelsPerMeter; + unsigned long biYPelsPerMeter; + unsigned long biClrUsed; + unsigned long biClrImportant; +} WINBMPINFOHEADER; + + +typedef struct OS2BMPINFOHEADER /* size: 12 */ +{ + unsigned short biWidth; + unsigned short biHeight; + unsigned short biPlanes; + unsigned short biBitCount; +} OS2BMPINFOHEADER; + + + +/* read_bmfileheader: + * Reads a BMP file header and check that it has the BMP magic number. + */ +static int read_bmfileheader(PACKFILE *f, BITMAPFILEHEADER *fileheader) +{ + fileheader->bfType = pack_igetw(f); + fileheader->bfSize= pack_igetl(f); + fileheader->bfReserved1= pack_igetw(f); + fileheader->bfReserved2= pack_igetw(f); + fileheader->bfOffBits= pack_igetl(f); + + if (fileheader->bfType != 19778) + return -1; + + return 0; +} + + + +/* read_win_bminfoheader: + * Reads information from a BMP file header. + */ +static int read_win_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader) +{ + WINBMPINFOHEADER win_infoheader; + + win_infoheader.biWidth = pack_igetl(f); + win_infoheader.biHeight = pack_igetl(f); + win_infoheader.biPlanes = pack_igetw(f); + win_infoheader.biBitCount = pack_igetw(f); + win_infoheader.biCompression = pack_igetl(f); + win_infoheader.biSizeImage = pack_igetl(f); + win_infoheader.biXPelsPerMeter = pack_igetl(f); + win_infoheader.biYPelsPerMeter = pack_igetl(f); + win_infoheader.biClrUsed = pack_igetl(f); + win_infoheader.biClrImportant = pack_igetl(f); + + infoheader->biWidth = win_infoheader.biWidth; + infoheader->biHeight = win_infoheader.biHeight; + infoheader->biBitCount = win_infoheader.biBitCount; + infoheader->biCompression = win_infoheader.biCompression; + + return 0; +} + + + +/* read_os2_bminfoheader: + * Reads information from an OS/2 format BMP file header. + */ +static int read_os2_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader) +{ + OS2BMPINFOHEADER os2_infoheader; + + os2_infoheader.biWidth = pack_igetw(f); + os2_infoheader.biHeight = pack_igetw(f); + os2_infoheader.biPlanes = pack_igetw(f); + os2_infoheader.biBitCount = pack_igetw(f); + + infoheader->biWidth = os2_infoheader.biWidth; + infoheader->biHeight = os2_infoheader.biHeight; + infoheader->biBitCount = os2_infoheader.biBitCount; + infoheader->biCompression = 0; + + return 0; +} + + + +/* read_bmicolors: + * Loads the color palette for 1,4,8 bit formats. + */ +static void read_bmicolors(int bytes, RGB *pal, PACKFILE *f, int win_flag) +{ + int i, j; + + for (i=j=0; (i+3 <= bytes && j < PAL_SIZE); j++) { + pal[j].b = pack_getc(f) / 4; + pal[j].g = pack_getc(f) / 4; + pal[j].r = pack_getc(f) / 4; + + i += 3; + + if (win_flag && i < bytes) { + pack_getc(f); + i++; + } + } + + for (; i> 1; + } + } + pix = b[j]; + bmp->line[line][i] = pix; + } +} + + + +/* read_4bit_line: + * Support function for reading the 4 bit bitmap file format. + */ +static void read_4bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) +{ + unsigned char b[8]; + unsigned long n; + int i, j, k; + int temp; + int pix; + + for (i=0; i> 4; + b[k*2] = temp & 15; + n = n >> 8; + } + } + pix = b[j]; + bmp->line[line][i] = pix; + } +} + + + +/* read_8bit_line: + * Support function for reading the 8 bit bitmap file format. + */ +static void read_8bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) +{ + unsigned char b[4]; + unsigned long n; + int i, j, k; + int pix; + + for (i=0; i> 8; + } + } + pix = b[j]; + bmp->line[line][i] = pix; + } +} + + + +/* read_16bit_line: + * Support function for reading the 16 bit bitmap file format, doing + * our best to convert it down to a 256 color palette. + */ +static void read_16bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) +{ + int i, w; + RGB c; + + for (i=0; i> 10) & 0x1f; + c.g = (w >> 5) & 0x1f; + c.b = w & 0x1f; + + bmp_write16(bmp->line[line]+i*2, + makecol16(_rgb_scale_5[c.r], + _rgb_scale_5[c.g], + _rgb_scale_5[c.b])); + } + + /* padding */ + i = (i * 2) % 4; + if (i != 0) { + while (i++ < 4) + pack_getc(f); + } +} + + + +/* read_24bit_line: + * Support function for reading the 24 bit bitmap file format, doing + * our best to convert it down to a 256 color palette. + */ +static void read_24bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) +{ + int i; + RGB c; + + for (i=0; iline[line]+i*3, makecol24(c.r, c.g, c.b)); + } + + /* padding */ + i = (i * 3) % 4; + if (i != 0) { + while (i++ < 4) + pack_getc(f); + } +} + + + +/* read_32bit_line: + * Support function for reading the 32 bit bitmap file format, doing + * our best to convert it down to a 256 color palette. + */ +static void read_32bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) +{ + int i; + RGB c; + char a; + + for (i=0; iline[line]+i*4, makeacol32(c.r, c.g, c.b, a)); + } +} + + + +/* read_bitfields_image: + * For reading the bitfield compressed BMP image format. + */ +static void read_bitfields_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) +{ + int k, i, line, height, dir; + int bpp; + int bytes_per_pixel; + int red, grn, blu; + unsigned long buffer; + + height = infoheader->biHeight; + line = height < 0 ? 0 : height-1; + dir = height < 0 ? 1 : -1; + height = ABS(height); + + bpp = bitmap_color_depth(bmp); + bytes_per_pixel = BYTES_PER_PIXEL(bpp); + + for (i=0; ibiWidth; k++) { + + pack_fread(&buffer, bytes_per_pixel, f); + + if (bpp == 15) { + red = (buffer >> 10) & 0x1f; + grn = (buffer >> 5) & 0x1f; + blu = (buffer) & 0x1f; + buffer = (red << _rgb_r_shift_15) | + (grn << _rgb_g_shift_15) | + (blu << _rgb_b_shift_15); + } + else if (bpp == 16) { + red = (buffer >> 11) & 0x1f; + grn = (buffer >> 5) & 0x3f; + blu = (buffer) & 0x1f; + buffer = (red << _rgb_r_shift_16) | + (grn << _rgb_g_shift_16) | + (blu << _rgb_b_shift_16); + } + else { + red = (buffer >> 16) & 0xff; + grn = (buffer >> 8) & 0xff; + blu = (buffer) & 0xff; + buffer = (red << _rgb_r_shift_32) | + (grn << _rgb_g_shift_32) | + (blu << _rgb_b_shift_32); + } + + memcpy(&bmp->line[line][k * bytes_per_pixel], &buffer, bytes_per_pixel); + } + + /* padding */ + k = (k * bytes_per_pixel) % 4; + if (k > 0) { + while (k++ < 4) + pack_getc(f); + } + } +} + + +/* read_image: + * For reading the noncompressed BMP image format. + */ +static void read_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) +{ + int i, line, height, dir; + + height = infoheader->biHeight; + line = height < 0 ? 0: height-1; + dir = height < 0 ? 1: -1; + height = ABS(height); + + for (i=0; ibiBitCount) { + + case 1: + read_1bit_line(infoheader->biWidth, f, bmp, line); + break; + + case 4: + read_4bit_line(infoheader->biWidth, f, bmp, line); + break; + + case 8: + read_8bit_line(infoheader->biWidth, f, bmp, line); + break; + + case 16: + read_16bit_line(infoheader->biWidth, f, bmp, line); + break; + + case 24: + read_24bit_line(infoheader->biWidth, f, bmp, line); + break; + + case 32: + read_32bit_line(infoheader->biWidth, f, bmp, line); + break; + } + } +} + + + +/* read_RLE8_compressed_image: + * For reading the 8 bit RLE compressed BMP image format. + */ +static void read_RLE8_compressed_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) +{ + unsigned char count, val, val0; + int j, pos, line; + int eolflag, eopicflag; + + eopicflag = 0; + line = infoheader->biHeight - 1; + + while (eopicflag == 0) { + pos = 0; /* x position in bitmap */ + eolflag = 0; /* end of line flag */ + + while ((eolflag == 0) && (eopicflag == 0)) { + count = pack_getc(f); + val = pack_getc(f); + + if (count > 0) { /* repeat pixel count times */ + for (j=0;jline[line][pos] = val; + pos++; + } + } + else { + switch (val) { + + case 0: /* end of line flag */ + eolflag=1; + break; + + case 1: /* end of picture flag */ + eopicflag=1; + break; + + case 2: /* displace picture */ + count = pack_getc(f); + val = pack_getc(f); + pos += count; + line -= val; + break; + + default: /* read in absolute mode */ + for (j=0; jline[line][pos] = val0; + pos++; + } + + if (j%2 == 1) + val0 = pack_getc(f); /* align on word boundary */ + break; + + } + } + + if (pos-1 > (int)infoheader->biWidth) + eolflag=1; + } + + line--; + if (line < 0) + eopicflag = 1; + } +} + + + +/* read_RLE4_compressed_image: + * For reading the 4 bit RLE compressed BMP image format. + */ +static void read_RLE4_compressed_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) +{ + unsigned char b[8]; + unsigned char count; + unsigned short val0, val; + int j, k, pos, line; + int eolflag, eopicflag; + + eopicflag = 0; /* end of picture flag */ + line = infoheader->biHeight - 1; + + while (eopicflag == 0) { + pos = 0; + eolflag = 0; /* end of line flag */ + + while ((eolflag == 0) && (eopicflag == 0)) { + count = pack_getc(f); + val = pack_getc(f); + + if (count > 0) { /* repeat pixels count times */ + b[1] = val & 15; + b[0] = (val >> 4) & 15; + for (j=0; jline[line][pos] = b[j%2]; + pos++; + } + } + else { + switch (val) { + + case 0: /* end of line */ + eolflag=1; + break; + + case 1: /* end of picture */ + eopicflag=1; + break; + + case 2: /* displace image */ + count = pack_getc(f); + val = pack_getc(f); + pos += count; + line -= val; + break; + + default: /* read in absolute mode */ + for (j=0; j> 4; + b[2*k] = val0 & 15; + val0 = val0 >> 4; + } + } + bmp->line[line][pos] = b[j%4]; + pos++; + } + break; + } + } + + if (pos-1 > (int)infoheader->biWidth) + eolflag=1; + } + + line--; + if (line < 0) + eopicflag = 1; + } +} + + + +/* load_bmp: + * Loads a Windows BMP file, returning a bitmap structure and storing + * the palette data in the specified palette (this should be an array of + * at least 256 RGB structures). + * + * Thanks to Seymour Shlien for contributing this function. + */ +BITMAP *load_bmp(AL_CONST char *filename, RGB *pal) +{ + PACKFILE *f; + BITMAP *bmp; + ASSERT(filename); + + f = pack_fopen(filename, F_READ); + if (!f) + return NULL; + + bmp = load_bmp_pf(f, pal); + + pack_fclose(f); + + return bmp; +} + + + +/* load_bmp_pf: + * Like load_bmp, but starts loading from the current place in the PACKFILE + * specified. If successful the offset into the file will be left just after + * the image data. If unsuccessful the offset into the file is unspecified, + * i.e. you must either reset the offset to some known place or close the + * packfile. The packfile is not closed by this function. + */ +BITMAP *load_bmp_pf(PACKFILE *f, RGB *pal) +{ + BITMAPFILEHEADER fileheader; + BITMAPINFOHEADER infoheader; + BITMAP *bmp; + PALETTE tmppal; + int want_palette = TRUE; + unsigned long biSize; + int bpp, dest_depth; + ASSERT(f); + + /* we really need a palette */ + if (!pal) { + want_palette = FALSE; + pal = tmppal; + } + + if (read_bmfileheader(f, &fileheader) != 0) { + return NULL; + } + + biSize = pack_igetl(f); + + if (biSize == WININFOHEADERSIZE) { + if (read_win_bminfoheader(f, &infoheader) != 0) { + return NULL; + } + if (infoheader.biCompression != BI_BITFIELDS) + read_bmicolors(fileheader.bfOffBits - 54, pal, f, 1); + } + else if (biSize == OS2INFOHEADERSIZE) { + if (read_os2_bminfoheader(f, &infoheader) != 0) { + return NULL; + } + if (infoheader.biCompression != BI_BITFIELDS) + read_bmicolors(fileheader.bfOffBits - 26, pal, f, 0); + } + else { + return NULL; + } + + if (infoheader.biBitCount == 24) + bpp = 24; + else if (infoheader.biBitCount == 16) + bpp = 16; + else if (infoheader.biBitCount == 32) + bpp = 32; + else + bpp = 8; + + if (infoheader.biCompression == BI_BITFIELDS) { + unsigned long redMask = pack_igetl(f); + unsigned long grnMask = pack_igetl(f); + unsigned long bluMask = pack_igetl(f); + + (void)grnMask; + + if ((bluMask == 0x001f) && (redMask == 0x7C00)) + bpp = 15; + else if ((bluMask == 0x001f) && (redMask == 0xF800)) + bpp = 16; + else if ((bluMask == 0x0000FF) && (redMask == 0xFF0000)) + bpp = 32; + else { + /* Unrecognised bit masks/depth, refuse to load. */ + return NULL; + } + } + + + dest_depth = _color_load_depth(bpp, FALSE); + + bmp = create_bitmap_ex(bpp, infoheader.biWidth, ABS(infoheader.biHeight)); + if (!bmp) { + return NULL; + } + + clear_bitmap(bmp); + + switch (infoheader.biCompression) { + + case BI_RGB: + read_image(f, bmp, &infoheader); + break; + + case BI_RLE8: + read_RLE8_compressed_image(f, bmp, &infoheader); + break; + + case BI_RLE4: + read_RLE4_compressed_image(f, bmp, &infoheader); + break; + + case BI_BITFIELDS: + read_bitfields_image(f, bmp, &infoheader); + break; + + default: + destroy_bitmap(bmp); + bmp = NULL; + } + + if (dest_depth != bpp) { + /* restore original palette except if it comes from the bitmap */ + if ((bpp != 8) && (!want_palette)) + pal = NULL; + + if (bmp) { + bmp = _fixup_loaded_bitmap(bmp, pal, dest_depth); + } + } + + /* construct a fake palette if 8-bit mode is not involved */ + if ((bpp != 8) && (dest_depth != 8) && want_palette) + generate_332_palette(pal); + + return bmp; +} + + + +/* save_bmp: + * Writes a bitmap into a BMP file, using the specified palette (this + * should be an array of at least 256 RGB structures). + */ +int save_bmp(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) +{ + PACKFILE *f; + int ret; + ASSERT(filename); + + f = pack_fopen(filename, F_WRITE); + if (!f) + return -1; + + ret = save_bmp_pf(f, bmp, pal); + + pack_fclose(f); + + return ret; +} + + + +/* save_bmp_pf: + * Like save_bmp but writes into the PACKFILE given instead of a new file. + * The packfile is not closed after writing is completed. On success the + * offset into the file is left after the TGA file just written. On failure + * the offset is left at the end of whatever incomplete data was written. + */ +int save_bmp_pf(PACKFILE *f, BITMAP *bmp, AL_CONST RGB *pal) +{ + PALETTE tmppal; + int bfSize; + int biSizeImage; + int depth; + int bpp; + int filler; + int c, i, j; + ASSERT(f); + ASSERT(bmp); + + depth = bitmap_color_depth(bmp); + bpp = (depth == 8) ? 8 : 24; + filler = 3 - ((bmp->w*(bpp/8)-1) & 3); + + if (!pal) { + get_palette(tmppal); + pal = tmppal; + } + + if (bpp == 8) { + biSizeImage = (bmp->w + filler) * bmp->h; + bfSize = (54 /* header */ + + 256*4 /* palette */ + + biSizeImage); /* image data */ + } + else { + biSizeImage = (bmp->w*3 + filler) * bmp->h; + bfSize = 54 + biSizeImage; /* header + image data */ + } + + *allegro_errno = 0; + + /* file_header */ + pack_iputw(0x4D42, f); /* bfType ("BM") */ + pack_iputl(bfSize, f); /* bfSize */ + pack_iputw(0, f); /* bfReserved1 */ + pack_iputw(0, f); /* bfReserved2 */ + + if (bpp == 8) /* bfOffBits */ + pack_iputl(54+256*4, f); + else + pack_iputl(54, f); + + /* info_header */ + pack_iputl(40, f); /* biSize */ + pack_iputl(bmp->w, f); /* biWidth */ + pack_iputl(bmp->h, f); /* biHeight */ + pack_iputw(1, f); /* biPlanes */ + pack_iputw(bpp, f); /* biBitCount */ + pack_iputl(0, f); /* biCompression */ + pack_iputl(biSizeImage, f); /* biSizeImage */ + pack_iputl(0xB12, f); /* biXPelsPerMeter (0xB12 = 72 dpi) */ + pack_iputl(0xB12, f); /* biYPelsPerMeter */ + + if (bpp == 8) { + pack_iputl(256, f); /* biClrUsed */ + pack_iputl(256, f); /* biClrImportant */ + + /* palette */ + for (i=0; i<256; i++) { + pack_putc(_rgb_scale_6[pal[i].b], f); + pack_putc(_rgb_scale_6[pal[i].g], f); + pack_putc(_rgb_scale_6[pal[i].r], f); + pack_putc(0, f); + } + } + else { + pack_iputl(0, f); /* biClrUsed */ + pack_iputl(0, f); /* biClrImportant */ + } + + /* image data */ + for (i=bmp->h-1; i>=0; i--) { + for (j=0; jw; j++) { + if (bpp == 8) { + pack_putc(getpixel(bmp, j, i), f); + } + else { + c = getpixel(bmp, j, i); + pack_putc(getb_depth(depth, c), f); + pack_putc(getg_depth(depth, c), f); + pack_putc(getr_depth(depth, c), f); + } + } + + for (j=0; j +#endif + + + +/* _linear_clear_to_color: + * Fills a linear bitmp with the specified color. + */ +void FUNC_LINEAR_CLEAR_TO_COLOR(BITMAP *dst, int color) +{ + int x, y; + int w; + + ASSERT(dst); + + w = dst->cr - dst->cl; + + bmp_select(dst); + + for (y = dst->ct; y < dst->cb; y++) { + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, y), dst->cl); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { + PUT_PIXEL(d, color); + } + } + + bmp_unwrite_line(dst); +} + + + +/* _linear_blit: + * Normal forward blitting for linear bitmaps. + */ +void FUNC_LINEAR_BLIT(BITMAP *src, BITMAP *dst, int sx, int sy, + int dx, int dy, int w, int h) +{ + int y; +#ifndef USE_MEMMOVE + int x; +#endif + + ASSERT(src); + ASSERT(dst); + + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx); + +#ifndef USE_MEMMOVE + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { + unsigned long c; + + bmp_select(src); + c = GET_PIXEL(s); + + bmp_select(dst); + PUT_PIXEL(d, c); + } +#else + memmove(d, s, w * sizeof(*s) * PTR_PER_PIXEL); +#endif + } + + bmp_unwrite_line(src); + bmp_unwrite_line(dst); +} + + + +/* _linear_blit_backward: + * Reverse blitting routine, for overlapping linear bitmaps. + */ +void FUNC_LINEAR_BLIT_BACKWARD(BITMAP *src, BITMAP *dst, int sx, int sy, + int dx, int dy, int w, int h) +{ + int y; +#ifndef USE_MEMMOVE + int x; +#endif + + ASSERT(src); + ASSERT(dst); + + for (y = h - 1; y >= 0; y--) { +#ifndef USE_MEMMOVE + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx + w - 1); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx + w - 1); + + for (x = w - 1; x >= 0; DEC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { + unsigned long c; + + bmp_select(src); + c = GET_PIXEL(s); + + bmp_select(dst); + PUT_PIXEL(d, c); + } +#else + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx); + + memmove(d, s, w * sizeof(*s) * PTR_PER_PIXEL); +#endif + } + + bmp_unwrite_line(src); + bmp_unwrite_line(dst); +} + +void FUNC_LINEAR_BLIT_END(void) { } + + + +/* _linear_masked_blit: + * Masked (skipping transparent pixels) blitting routine for linear bitmaps. + */ +void FUNC_LINEAR_MASKED_BLIT(BITMAP *src, BITMAP *dst, int sx, int sy, + int dx, int dy, int w, int h) +{ + int x, y; + unsigned long mask_color; + + ASSERT(src); + ASSERT(dst); + + mask_color = bitmap_mask_color(dst); + + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { + unsigned long c; + + bmp_select(src); + c = GET_PIXEL(s); + + if (c != mask_color) { + bmp_select(dst); + PUT_PIXEL(d, c); + } + } + } + + bmp_unwrite_line(src); + bmp_unwrite_line(dst); +} + +#endif /* !__bma_cblit_h */ + diff --git a/libsrc/allegro/src/c/cblit16.c b/libsrc/allegro/src/c/cblit16.c new file mode 100644 index 00000000000..46a978875ef --- /dev/null +++ b/libsrc/allegro/src/c/cblit16.c @@ -0,0 +1,27 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 16 bit color bitmap blitting functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR16 + +#include "cdefs16.h" +#include "cblit.h" + +#endif + diff --git a/libsrc/allegro/src/c/cblit24.c b/libsrc/allegro/src/c/cblit24.c new file mode 100644 index 00000000000..b6a536117c6 --- /dev/null +++ b/libsrc/allegro/src/c/cblit24.c @@ -0,0 +1,27 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 24 bit color bitmap blitting functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR24 + +#include "cdefs24.h" +#include "cblit.h" + +#endif + diff --git a/libsrc/allegro/src/c/cblit32.c b/libsrc/allegro/src/c/cblit32.c new file mode 100644 index 00000000000..f7fd1e98606 --- /dev/null +++ b/libsrc/allegro/src/c/cblit32.c @@ -0,0 +1,27 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 32 bit color bitmap blitting functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR32 + +#include "cdefs32.h" +#include "cblit.h" + +#endif + diff --git a/libsrc/allegro/src/c/cblit8.c b/libsrc/allegro/src/c/cblit8.c new file mode 100644 index 00000000000..4be553b026b --- /dev/null +++ b/libsrc/allegro/src/c/cblit8.c @@ -0,0 +1,27 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 256 color bitmap blitting functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR8 + +#include "cdefs8.h" +#include "cblit.h" + +#endif + diff --git a/libsrc/allegro/src/c/cdefs15.h b/libsrc/allegro/src/c/cdefs15.h new file mode 100644 index 00000000000..2274c5840a3 --- /dev/null +++ b/libsrc/allegro/src/c/cdefs15.h @@ -0,0 +1,102 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Defines for 15 bit color graphics primitives. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cdefs15_h +#define __bma_cdefs15_h + +#define PP_DEPTH 15 + +#define PIXEL_PTR unsigned short* +#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) +#define INC_PIXEL_PTR(p) ((p)++) +#define INC_PIXEL_PTR_N(p,d) ((p) += d) +#define DEC_PIXEL_PTR(p) ((p)--) + +#define PUT_PIXEL(p,c) bmp_write15((uintptr_t) (p), (c)) +#define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) +#define PUT_RGB(p,r,g,b) bmp_write15((uintptr_t) (p), makecol15((r), (g), (b))) +#define GET_PIXEL(p) bmp_read15((uintptr_t) (p)) +#define GET_MEMORY_PIXEL(p) (*(p)) + +#define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_15) +#define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == MASK_COLOR_15) + +/* Blender for putpixel (DRAW_MODE_TRANS). */ +#define PP_BLENDER BLENDER_FUNC +#define MAKE_PP_BLENDER(c) _blender_func15 +#define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_trans_*_sprite. */ +#define DTS_BLENDER BLENDER_FUNC +#define MAKE_DTS_BLENDER() _blender_func15 +#define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_lit_*_sprite. */ +#define DLS_BLENDER BLENDER_FUNC +#define MAKE_DLS_BLENDER(a) _blender_func15 +#define DLS_BLEND(b,a,n) ((*(b))(_blender_col_15, (n), (a))) +#define DLSX_BLEND(b,n) ((*(b))(_blender_col_15, (n), _blender_alpha)) + +/* Blender for RGBA sprites. */ +#define RGBA_BLENDER BLENDER_FUNC +#define MAKE_RGBA_BLENDER() _blender_func15x +#define RGBA_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for poly_scanline_*_lit. */ +#define PS_BLENDER BLENDER_FUNC +#define MAKE_PS_BLENDER() _blender_func15 +#define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_15, (o))) +#define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) + +#define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ + & _drawing_y_mask]) +#define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ + ((x) - _drawing_x_anchor) & _drawing_x_mask)) + +#define RLE_PTR signed short* +#define RLE_IS_EOL(c) ((unsigned short) (c) == MASK_COLOR_15) + +#define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color15 +#define FUNC_LINEAR_BLIT _linear_blit15 +#define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward15 +#define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit15 + +#define FUNC_LINEAR_PUTPIXEL _linear_putpixel15 +#define FUNC_LINEAR_GETPIXEL _linear_getpixel15 +#define FUNC_LINEAR_HLINE _linear_hline15 +#define FUNC_LINEAR_VLINE _linear_vline15 + +#define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite15 +#define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex15 +#define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite15 +#define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip15 +#define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip15 +#define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip15 +#define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite15 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite15 +#define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite15 +#define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character15 +#define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite15 +#define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite15 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite15 +#define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite15 + +#define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite15_end +#define FUNC_LINEAR_BLIT_END _linear_blit15_end + +#endif /* !__bma_cdefs15_h */ + diff --git a/libsrc/allegro/src/c/cdefs16.h b/libsrc/allegro/src/c/cdefs16.h new file mode 100644 index 00000000000..d552803dcdc --- /dev/null +++ b/libsrc/allegro/src/c/cdefs16.h @@ -0,0 +1,103 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Defines for 16 bit color graphics primitives. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cdefs16_h +#define __bma_cdefs16_h + +#define PP_DEPTH 16 + +#define PIXEL_PTR unsigned short* +#define PTR_PER_PIXEL 1 +#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) +#define INC_PIXEL_PTR(p) ((p)++) +#define INC_PIXEL_PTR_N(p,d) ((p) += d) +#define DEC_PIXEL_PTR(p) ((p)--) + +#define PUT_PIXEL(p,c) bmp_write16((uintptr_t) (p), (c)) +#define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) +#define PUT_RGB(p,r,g,b) bmp_write16((uintptr_t) (p), makecol16((r), (g), (b))) +#define GET_PIXEL(p) bmp_read16((uintptr_t) (p)) +#define GET_MEMORY_PIXEL(p) (*(p)) + +#define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_16) +#define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == (unsigned long) (b)->vtable->mask_color) + +/* Blender for putpixel (DRAW_MODE_TRANS). */ +#define PP_BLENDER BLENDER_FUNC +#define MAKE_PP_BLENDER(c) _blender_func16 +#define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_trans_*_sprite. */ +#define DTS_BLENDER BLENDER_FUNC +#define MAKE_DTS_BLENDER() _blender_func16 +#define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_lit_*_sprite. */ +#define DLS_BLENDER BLENDER_FUNC +#define MAKE_DLS_BLENDER(a) _blender_func16 +#define DLS_BLEND(b,a,n) ((*(b))(_blender_col_16, (n), (a))) +#define DLSX_BLEND(b,n) ((*(b))(_blender_col_16, (n), _blender_alpha)) + +/* Blender for RGBA sprites. */ +#define RGBA_BLENDER BLENDER_FUNC +#define MAKE_RGBA_BLENDER() _blender_func16x +#define RGBA_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for poly_scanline_*_lit. */ +#define PS_BLENDER BLENDER_FUNC +#define MAKE_PS_BLENDER() _blender_func16 +#define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_16, (o))) +#define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) + +#define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ + & _drawing_y_mask]) +#define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ + ((x) - _drawing_x_anchor) & _drawing_x_mask)) + +#define RLE_PTR signed short* +#define RLE_IS_EOL(c) ((unsigned short) (c) == MASK_COLOR_16) + +#define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color16 +#define FUNC_LINEAR_BLIT _linear_blit16 +#define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward16 +#define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit16 + +#define FUNC_LINEAR_PUTPIXEL _linear_putpixel16 +#define FUNC_LINEAR_GETPIXEL _linear_getpixel16 +#define FUNC_LINEAR_HLINE _linear_hline16 +#define FUNC_LINEAR_VLINE _linear_vline16 + +#define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite16 +#define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex16 +#define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite16 +#define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip16 +#define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip16 +#define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip16 +#define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite16 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite16 +#define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite16 +#define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character16 +#define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite16 +#define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite16 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite16 +#define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite16 + +#define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite16_end +#define FUNC_LINEAR_BLIT_END _linear_blit16_end + +#endif /* !__bma_cdefs16_h */ + diff --git a/libsrc/allegro/src/c/cdefs24.h b/libsrc/allegro/src/c/cdefs24.h new file mode 100644 index 00000000000..13fb2d621a8 --- /dev/null +++ b/libsrc/allegro/src/c/cdefs24.h @@ -0,0 +1,102 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Defines for 24 bit color graphics primitives. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cdefs24_h +#define __bma_cdefs24_h + +#define PP_DEPTH 24 + +#define PIXEL_PTR unsigned char* +#define PTR_PER_PIXEL 3 +#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + 3 * (x)) +#define INC_PIXEL_PTR(p) ((p) += 3) +#define INC_PIXEL_PTR_N(p,d) ((p) += 3 * d) +#define DEC_PIXEL_PTR(p) ((p) -= 3) + +#define PUT_PIXEL(p,c) bmp_write24((uintptr_t) (p), (c)) +#define PUT_MEMORY_PIXEL(p,c) WRITE3BYTES((p), (c)) +#define PUT_RGB(p,r,g,b) bmp_write24((uintptr_t) (p), makecol24((r), (g), (b))) +#define GET_PIXEL(p) bmp_read24((uintptr_t) (p)) +#define GET_MEMORY_PIXEL(p) READ3BYTES((p)) +#define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_24) +#define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == MASK_COLOR_24) + +/* Blender for putpixel (DRAW_MODE_TRANS). */ +#define PP_BLENDER BLENDER_FUNC +#define MAKE_PP_BLENDER(c) _blender_func24 +#define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_trans_*_sprite. */ +#define DTS_BLENDER BLENDER_FUNC +#define MAKE_DTS_BLENDER() _blender_func24 +#define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_lit_*_sprite. */ +#define DLS_BLENDER BLENDER_FUNC +#define MAKE_DLS_BLENDER(a) _blender_func24 +#define DLS_BLEND(b,a,n) ((*(b))(_blender_col_24, (n), (a))) +#define DLSX_BLEND(b,n) ((*(b))(_blender_col_24, (n), _blender_alpha)) + +/* Blender for RGBA sprites. */ +#define RGBA_BLENDER BLENDER_FUNC +#define MAKE_RGBA_BLENDER() _blender_func24x +#define RGBA_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for poly_scanline_*_lit. */ +#define PS_BLENDER BLENDER_FUNC +#define MAKE_PS_BLENDER() _blender_func24 +#define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_24, (o))) +#define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) + +#define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ + & _drawing_y_mask]) +#define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ + ((x) - _drawing_x_anchor) & _drawing_x_mask)) + +#define RLE_PTR int32_t* +#define RLE_IS_EOL(c) ((unsigned long) (c) == MASK_COLOR_24) + +#define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color24 +#define FUNC_LINEAR_BLIT _linear_blit24 +#define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward24 +#define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit24 + +#define FUNC_LINEAR_PUTPIXEL _linear_putpixel24 +#define FUNC_LINEAR_GETPIXEL _linear_getpixel24 +#define FUNC_LINEAR_HLINE _linear_hline24 +#define FUNC_LINEAR_VLINE _linear_vline24 + +#define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite24 +#define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex24 +#define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite24 +#define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip24 +#define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip24 +#define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip24 +#define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite24 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite24 +#define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite24 +#define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character24 +#define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite24 +#define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite24 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite24 +#define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite24 + +#define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite24_end +#define FUNC_LINEAR_BLIT_END _linear_blit24_end + +#endif /* !__bma_cdefs24_h */ + diff --git a/libsrc/allegro/src/c/cdefs32.h b/libsrc/allegro/src/c/cdefs32.h new file mode 100644 index 00000000000..3feb8eb3450 --- /dev/null +++ b/libsrc/allegro/src/c/cdefs32.h @@ -0,0 +1,98 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Defines for 32 bit color graphics primitives. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cdefs32_h +#define __bma_cdefs32_h + +#define PP_DEPTH 32 + +#define PIXEL_PTR uint32_t* +#define PTR_PER_PIXEL 1 +#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) +#define INC_PIXEL_PTR(p) ((p)++) +#define INC_PIXEL_PTR_N(p,d) ((p) += d) +#define DEC_PIXEL_PTR(p) ((p)--) + +#define PUT_PIXEL(p,c) bmp_write32((uintptr_t) (p), (c)) +#define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) +#define PUT_RGB(p,r,g,b) bmp_write32((uintptr_t) (p), makecol32((r), (g), (b))) +#define GET_PIXEL(p) bmp_read32((uintptr_t) (p)) +#define GET_MEMORY_PIXEL(p) (*(p)) + +#define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_32) +#define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == MASK_COLOR_32) + +/* Blender for putpixel (DRAW_MODE_TRANS). */ +#define PP_BLENDER BLENDER_FUNC +#define MAKE_PP_BLENDER(c) _blender_func32 +#define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_trans_*_sprite. */ +#define DTS_BLENDER BLENDER_FUNC +#define MAKE_DTS_BLENDER() _blender_func32 +#define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) + +/* Blender for draw_lit_*_sprite. */ +#define DLS_BLENDER BLENDER_FUNC +#define MAKE_DLS_BLENDER(a) _blender_func32 +#define DLS_BLEND(b,a,n) ((*(b))(_blender_col_32, (n), (a))) +#define DLSX_BLEND(b,n) ((*(b))(_blender_col_32, (n), _blender_alpha)) + +/* Blender for poly_scanline_*_lit. */ +#define PS_BLENDER BLENDER_FUNC +#define MAKE_PS_BLENDER() _blender_func32 +#define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_32, (o))) +#define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) + +#define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ + & _drawing_y_mask]) +#define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ + ((x) - _drawing_x_anchor) & _drawing_x_mask)) + +#define RLE_PTR int32_t* +#define RLE_IS_EOL(c) ((unsigned long) (c) == MASK_COLOR_32) + +#define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color32 +#define FUNC_LINEAR_BLIT _linear_blit32 +#define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward32 +#define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit32 + +#define FUNC_LINEAR_PUTPIXEL _linear_putpixel32 +#define FUNC_LINEAR_GETPIXEL _linear_getpixel32 +#define FUNC_LINEAR_HLINE _linear_hline32 +#define FUNC_LINEAR_VLINE _linear_vline32 + +#define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite32 +#define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex32 +#define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite32 +#define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip32 +#define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip32 +#define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip32 +#define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite32 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite32 +#define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite32 +#define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character32 +#define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite32 +#define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite32 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite32 +#define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite32 + +#define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite32_end +#define FUNC_LINEAR_BLIT_END _linear_blit32_end + +#endif /* !__bma_cdefs32_h */ + diff --git a/libsrc/allegro/src/c/cdefs8.h b/libsrc/allegro/src/c/cdefs8.h new file mode 100644 index 00000000000..24898382158 --- /dev/null +++ b/libsrc/allegro/src/c/cdefs8.h @@ -0,0 +1,97 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Defines for 256 color graphics primitives. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cdefs8_h +#define __bma_cdefs8_h + +#define PP_DEPTH 8 + +#define PIXEL_PTR unsigned char* +#define PTR_PER_PIXEL 1 +#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) +#define INC_PIXEL_PTR(p) ((p)++) +#define INC_PIXEL_PTR_N(p,d) ((p) += d) +#define DEC_PIXEL_PTR(p) ((p)--) + +#define PUT_PIXEL(p,c) bmp_write8((uintptr_t) (p), (c)) +#define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) +#define PUT_RGB(p,r,g,b) bmp_write8((uintptr_t) (p), makecol8((r), (g), (b))) +#define GET_PIXEL(p) bmp_read8((uintptr_t) (p)) +#define GET_MEMORY_PIXEL(p) (*(p)) + +#define IS_MASK(c) ((c) == 0) +#define IS_SPRITE_MASK(b,c) ((c) == 0) + +/* Blender for putpixel (DRAW_MODE_TRANS). */ +#define PP_BLENDER unsigned char* +#define MAKE_PP_BLENDER(c) (color_map->data[(c) & 0xFF]) +#define PP_BLEND(b,o,n) ((b)[(o) & 0xFF]) + +/* Blender for draw_trans_*_sprite. */ +#define DTS_BLENDER COLOR_MAP* +#define MAKE_DTS_BLENDER() color_map +#define DTS_BLEND(b,o,n) ((b)->data[(n)& 0xFF][(o) & 0xFF]) + +/* Blender for draw_lit_*_sprite. */ +#define DLS_BLENDER unsigned char* +#define MAKE_DLS_BLENDER(a) (color_map->data[(a) & 0xFF]) +#define DLS_BLEND(b,a,c) ((b)[(c) & 0xFF]) +#define DLSX_BLEND(b,c) ((b)[(c) & 0xFF]) + +/* Blender for poly_scanline_*_lit. */ +#define PS_BLENDER COLOR_MAP* +#define MAKE_PS_BLENDER() color_map +#define PS_BLEND(b,o,c) ((b)->data[(o) & 0xFF][(c) & 0xFF]) +#define PS_ALPHA_BLEND(b,o,c) ((b)->data[(o) & 0xFF][(c) & 0xFF]) + +#define PATTERN_LINE(y) _drawing_pattern->line[((y) - _drawing_y_anchor) & _drawing_y_mask] +#define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ + ((x) - _drawing_x_anchor) & _drawing_x_mask)) + +#define RLE_PTR signed char* +#define RLE_IS_EOL(c) ((c) == 0) + +#define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color8 +#define FUNC_LINEAR_BLIT _linear_blit8 +#define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward8 +#define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit8 + +#define FUNC_LINEAR_PUTPIXEL _linear_putpixel8 +#define FUNC_LINEAR_GETPIXEL _linear_getpixel8 +#define FUNC_LINEAR_HLINE _linear_hline8 +#define FUNC_LINEAR_VLINE _linear_vline8 + +#define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite8 +#define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex8 +#define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite8 +#define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip8 +#define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip8 +#define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip8 +#define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite8 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite8 +#define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite8 +#define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character8 +#define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite8 +#define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite8 +#define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite8 +#define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite8 + +#define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite8_end +#define FUNC_LINEAR_BLIT_END _linear_blit8_end + +#endif /* !__bma_cdefs8_h */ + diff --git a/libsrc/allegro/src/c/cgfx.h b/libsrc/allegro/src/c/cgfx.h new file mode 100644 index 00000000000..5f1c68824fb --- /dev/null +++ b/libsrc/allegro/src/c/cgfx.h @@ -0,0 +1,264 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Linear graphics functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cgfx_h +#define __bma_cgfx_h + +/* _linear_putpixel: + * Draws a pixel onto a linear bitmap. + */ +void FUNC_LINEAR_PUTPIXEL(BITMAP *dst, int dx, int dy, int color) +{ + ASSERT(dst); + + if (dst->clip && ((dx < dst->cl) || (dx >= dst->cr) || (dy < dst->ct) || (dy >= dst->cb))) + return; + + bmp_select(dst); + + if (_drawing_mode == DRAW_MODE_SOLID) { + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); + PUT_PIXEL(d, color); + } + else if (_drawing_mode == DRAW_MODE_XOR) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); + unsigned long c = GET_PIXEL(s) ^ color; + PUT_PIXEL(d, c); + } + else if (_drawing_mode == DRAW_MODE_TRANS) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); + PP_BLENDER blender = MAKE_PP_BLENDER(color); + unsigned long c = PP_BLEND(blender, GET_PIXEL(s), color); + PUT_PIXEL(d, c); + } + else { + unsigned long c = GET_PATTERN_PIXEL(dx, dy); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); + + if (_drawing_mode == DRAW_MODE_COPY_PATTERN) { + PUT_PIXEL(d, c); + } + else if (_drawing_mode == DRAW_MODE_SOLID_PATTERN) { + if (!IS_MASK(c)) { + PUT_PIXEL(d, color); + } + else { + PUT_PIXEL(d, c); + } + } + else if (_drawing_mode == DRAW_MODE_MASKED_PATTERN) { + if (!IS_MASK(c)) { + PUT_PIXEL(d, color); + } + } + } + + bmp_unwrite_line(dst); +} + + + +/* _linear_getpixel: + * Reads a pixel from a linear bitmap. + */ +int FUNC_LINEAR_GETPIXEL(BITMAP *src, int sx, int sy) +{ + ASSERT(src); + + if ((sx < 0) || (sx >= src->w) || (sy < 0) || (sy >= src->h)) + return -1; + else { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy), sx); + unsigned long c; + + bmp_select(src); + c = GET_PIXEL(s); + bmp_unwrite_line(src); + + return c; + } +} + + + +/* _linear_hline: + * Draws a horizontal line onto a linear bitmap. + */ +void FUNC_LINEAR_HLINE(BITMAP *dst, int dx1, int dy, int dx2, int color) +{ + int w; + + ASSERT(dst); + + if (dx1 > dx2) { + int tmp = dx1; + dx1 = dx2; + dx2 = tmp; + } + if (dst->clip) { + if (dx1 < dst->cl) + dx1 = dst->cl; + if (dx2 >= dst->cr) + dx2 = dst->cr - 1; + if ((dx1 > dx2) || (dy < dst->ct) || (dy >= dst->cb)) + return; + } + + w = dx2 - dx1; + + bmp_select(dst); + + if (_drawing_mode == DRAW_MODE_SOLID) { + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); + do { + PUT_PIXEL(d, color); + INC_PIXEL_PTR(d); + } while (--w >= 0); + } + else if (_drawing_mode == DRAW_MODE_XOR) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx1); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); + do { + unsigned long c = GET_PIXEL(s) ^ color; + PUT_PIXEL(d, c); + INC_PIXEL_PTR(s); + INC_PIXEL_PTR(d); + } while (--w >= 0); + } + else if (_drawing_mode == DRAW_MODE_TRANS) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx1); + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); + PP_BLENDER blender = MAKE_PP_BLENDER(color); + do { + unsigned long c = PP_BLEND(blender, GET_PIXEL(s), color); + PUT_PIXEL(d, c); + INC_PIXEL_PTR(s); + INC_PIXEL_PTR(d); + } while (--w >= 0); + } + else { + int x, curw; + PIXEL_PTR sline = PATTERN_LINE(dy); + PIXEL_PTR s; + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); + + x = (dx1 - _drawing_x_anchor) & _drawing_x_mask; + s = OFFSET_PIXEL_PTR(sline, x); + w++; + curw = _drawing_x_mask + 1 - x; + if (curw > w) + curw = w; + + if (_drawing_mode == DRAW_MODE_COPY_PATTERN) { + do { + w -= curw; + do { + unsigned long c = GET_MEMORY_PIXEL(s); + PUT_PIXEL(d, c); + INC_PIXEL_PTR(s); + INC_PIXEL_PTR(d); + } while (--curw > 0); + s = sline; + curw = MIN(w, (int)_drawing_x_mask+1); + } while (curw > 0); + } + else if (_drawing_mode == DRAW_MODE_SOLID_PATTERN) { + do { + w -= curw; + do { + unsigned long c = GET_MEMORY_PIXEL(s); + if (!IS_MASK(c)) { + PUT_PIXEL(d, color); + } + else { + PUT_PIXEL(d, c); + } + INC_PIXEL_PTR(s); + INC_PIXEL_PTR(d); + } while (--curw > 0); + s = sline; + curw = MIN(w, (int)_drawing_x_mask+1); + } while (curw > 0); + } + else if (_drawing_mode == DRAW_MODE_MASKED_PATTERN) { + do { + w -= curw; + do { + unsigned long c = GET_MEMORY_PIXEL(s); + if (!IS_MASK(c)) { + PUT_PIXEL(d, color); + } + INC_PIXEL_PTR(s); + INC_PIXEL_PTR(d); + } while (--curw > 0); + s = sline; + curw = MIN(w, (int)_drawing_x_mask+1); + } while (curw > 0); + } + } + + bmp_unwrite_line(dst); +} + + + +/* _linear_vline: + * Draws a vertical line onto a linear bitmap. + */ +void FUNC_LINEAR_VLINE(BITMAP *dst, int dx, int dy1, int dy2, int color) +{ + int y; + + ASSERT(dst); + + if (dy1 > dy2) { + int tmp = dy1; + dy1 = dy2; + dy2 = tmp; + } + if (dst->clip) { + if (dy1 < dst->ct) + dy1 = dst->ct; + if (dy2 >= dst->cb) + dy2 = dst->cb - 1; + if ((dx < dst->cl) || (dx >= dst->cr) || (dy1 > dy2)) + return; + } + + if (_drawing_mode == DRAW_MODE_SOLID) { + bmp_select(dst); + for (y = dy1; y <= dy2; y++) { + PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, y), dx); + PUT_PIXEL(d, color); + } + bmp_unwrite_line(dst); + } + else { + int clip = dst->clip; + + dst->clip = 0; + for (y = dy1; y <= dy2; y++) { + FUNC_LINEAR_PUTPIXEL(dst, dx, y, color); + } + dst->clip = clip; + } +} + +#endif /* !__bma_cgfx_h */ + diff --git a/libsrc/allegro/src/c/cgfx15.c b/libsrc/allegro/src/c/cgfx15.c new file mode 100644 index 00000000000..4594c486637 --- /dev/null +++ b/libsrc/allegro/src/c/cgfx15.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 15 bit color linear graphics functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR16 + +#include "allegro/internal/aintern.h" +#include "cdefs15.h" +#include "cgfx.h" + +#endif + diff --git a/libsrc/allegro/src/c/cgfx16.c b/libsrc/allegro/src/c/cgfx16.c new file mode 100644 index 00000000000..84642cb73ce --- /dev/null +++ b/libsrc/allegro/src/c/cgfx16.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 16 bit color linear graphics functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR16 + +#include "allegro/internal/aintern.h" +#include "cdefs16.h" +#include "cgfx.h" + +#endif + diff --git a/libsrc/allegro/src/c/cgfx24.c b/libsrc/allegro/src/c/cgfx24.c new file mode 100644 index 00000000000..788ace6a584 --- /dev/null +++ b/libsrc/allegro/src/c/cgfx24.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 24 bit color linear graphics functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR24 + +#include "allegro/internal/aintern.h" +#include "cdefs24.h" +#include "cgfx.h" + +#endif + diff --git a/libsrc/allegro/src/c/cgfx32.c b/libsrc/allegro/src/c/cgfx32.c new file mode 100644 index 00000000000..bc6d0e58fa7 --- /dev/null +++ b/libsrc/allegro/src/c/cgfx32.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 32 bit color linear graphics functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR32 + +#include "allegro/internal/aintern.h" +#include "cdefs32.h" +#include "cgfx.h" + +#endif + diff --git a/libsrc/allegro/src/c/cgfx8.c b/libsrc/allegro/src/c/cgfx8.c new file mode 100644 index 00000000000..b205b8bbcdd --- /dev/null +++ b/libsrc/allegro/src/c/cgfx8.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 256 color linear graphics functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR8 + +#include "allegro/internal/aintern.h" +#include "cdefs8.h" +#include "cgfx.h" + +#endif + diff --git a/libsrc/allegro/src/c/cmisc.c b/libsrc/allegro/src/c/cmisc.c new file mode 100644 index 00000000000..d4168731e08 --- /dev/null +++ b/libsrc/allegro/src/c/cmisc.c @@ -0,0 +1,50 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Math routines, etc. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#ifdef ALLEGRO_NO_ASM +/* Empty bank switch routines. Should be used with C calling convention. */ + +uintptr_t _stub_bank_switch(BITMAP *bmp, int y) +{ + return (uintptr_t)bmp->line[y]; +} + +void _stub_unbank_switch(BITMAP *bmp) +{ +} + +void _stub_bank_switch_end(void) +{ +} + +#else + +/* + * For ASM calling convention: + * Unix version uses bank switch routines from src/i386/imisc.s. + * DOS version uses bank switch routines from -#- or src/c/cmiscs.s. + */ + +#endif + + diff --git a/libsrc/allegro/src/c/cspr.h b/libsrc/allegro/src/c/cspr.h new file mode 100644 index 00000000000..45fb5a82982 --- /dev/null +++ b/libsrc/allegro/src/c/cspr.h @@ -0,0 +1,567 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Sprite drawing functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +#ifndef __bma_cspr_h +#define __bma_cspr_h + +/* _linear_draw_sprite: + * Draws a sprite onto a linear bitmap at the specified x, y position, + * using a masked drawing mode where zero pixels are not output. + */ +void FUNC_LINEAR_DRAW_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx; + dybeg = dy; + } + + { + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { + unsigned long c = GET_MEMORY_PIXEL(s); + if (!IS_SPRITE_MASK(src, c)) { + PUT_MEMORY_PIXEL(d, c); + } + } + } + } +} + +void FUNC_LINEAR_DRAW_SPRITE_END(void) { } + + + +/* _linear_draw_256_sprite: + * Draws a 256 coor sprite onto a linear bitmap at the specified x, y + * position, using a masked drawing mode where zero pixels are not output. + */ +void FUNC_LINEAR_DRAW_256_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + int *table; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx; + dybeg = dy; + } + + table = _palette_expansion_table(bitmap_color_depth(dst)); + ASSERT(table); + + { + for (y = 0; y < h; y++) { + unsigned char *s = src->line[sybeg + y] + sxbeg; + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); + + for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) { + unsigned long c = *s; + if (c != 0) { + c = table[c]; + PUT_MEMORY_PIXEL(d, c); + } + } + } + } +} + + + +/* _linear_draw_sprite_v_flip: + * Draws a sprite to a linear bitmap, flipping vertically. + */ +void FUNC_LINEAR_DRAW_SPRITE_V_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + + /* use backward drawing onto dst */ + sybeg = src->h - (sybeg + h); + dybeg += h - 1; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx; + dybeg = dy + h - 1; + } + + { + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg - y], dxbeg); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { + unsigned long c = GET_MEMORY_PIXEL(s); + if (!IS_SPRITE_MASK(src, c)) { + PUT_MEMORY_PIXEL(d, c); + } + } + } + } +} + + + +/* _linear_draw_sprite_h_flip: + * Draws a sprite to a linear bitmap, flipping horizontally. + */ +void FUNC_LINEAR_DRAW_SPRITE_H_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + /* use backward drawing onto dst */ + sxbeg = src->w - (sxbeg + w); + dxbeg += w - 1; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx + w - 1; + dybeg = dy; + } + + { + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { + unsigned long c = GET_MEMORY_PIXEL(s); + if (!IS_SPRITE_MASK(src, c)) { + PUT_MEMORY_PIXEL(d, c); + } + } + } + } +} + + + +/* _linear_draw_sprite_vh_flip: + * Draws a sprite to a linear bitmap, flipping both vertically and horizontally. + */ +void FUNC_LINEAR_DRAW_SPRITE_VH_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + /* use backward drawing onto dst */ + sxbeg = src->w - (sxbeg + w); + dxbeg += w - 1; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + + /* use backward drawing onto dst */ + sybeg = src->h - (sybeg + h); + dybeg += h - 1; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx + w - 1; + dybeg = dy + h - 1; + } + + { + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg - y], dxbeg); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { + unsigned long c = GET_MEMORY_PIXEL(s); + if (!IS_SPRITE_MASK(src, c)) { + PUT_MEMORY_PIXEL(d, c); + } + } + } + } +} + + + +/* _linear_draw_trans_sprite: + * Draws a translucent sprite onto a linear bitmap. + */ +void FUNC_LINEAR_DRAW_TRANS_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + DTS_BLENDER blender; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx; + dybeg = dy; + } + + blender = MAKE_DTS_BLENDER(); + + if ((src->vtable->color_depth == 8) && (dst->vtable->color_depth != 8)) { + bmp_select(dst); + + for (y = 0; y < h; y++) { + unsigned char *s = src->line[sybeg + y] + sxbeg; + PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); + PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); + + for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { + unsigned long c = *s; +#if PP_DEPTH == 8 + c = DTS_BLEND(blender, GET_PIXEL(ds), c); + PUT_PIXEL(dd, c); +#else + if (!IS_SPRITE_MASK(src, c)) { + c = DTS_BLEND(blender, GET_PIXEL(ds), c); + PUT_PIXEL(dd, c); + } +#endif + } + } + + bmp_unwrite_line(dst); + } + else { + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { + unsigned long c = GET_MEMORY_PIXEL(s); +#if PP_DEPTH == 8 + c = DTS_BLEND(blender, GET_MEMORY_PIXEL(d), c); + PUT_MEMORY_PIXEL(d, c); +#else + if (!IS_SPRITE_MASK(src, c)) { + c = DTS_BLEND(blender, GET_MEMORY_PIXEL(d), c); + PUT_MEMORY_PIXEL(d, c); + } +#endif + } + } + } +} + + + +#if (PP_DEPTH != 8) && (PP_DEPTH != 32) + +/* _linear_draw_trans_rgba_sprite: + * Draws a translucent RGBA sprite onto a linear bitmap. + */ +void FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + RGBA_BLENDER blender; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx; + dybeg = dy; + } + + blender = MAKE_RGBA_BLENDER(); + + bmp_select(dst); + + for (y = 0; y < h; y++) { + uint32_t *s = (uint32_t *)src->line[sybeg + y] + sxbeg; + PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); + PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); + + for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { + unsigned long c = *s; + + if (c != MASK_COLOR_32) { + c = RGBA_BLEND(blender, GET_PIXEL(ds), c); + PUT_PIXEL(dd, c); + } + } + } + + bmp_unwrite_line(dst); +} + +#endif + + + +/* _linear_draw_lit_sprite: + * Draws a lit sprite onto a linear bitmap. + */ +void FUNC_LINEAR_DRAW_LIT_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy, int color) +{ + int x, y, w, h; + int dxbeg, dybeg; + int sxbeg, sybeg; + DLS_BLENDER blender; + + ASSERT(dst); + ASSERT(src); + + if (dst->clip) { + int tmp; + + tmp = dst->cl - dx; + sxbeg = ((tmp < 0) ? 0 : tmp); + dxbeg = sxbeg + dx; + + tmp = dst->cr - dx; + w = ((tmp > src->w) ? src->w : tmp) - sxbeg; + if (w <= 0) + return; + + tmp = dst->ct - dy; + sybeg = ((tmp < 0) ? 0 : tmp); + dybeg = sybeg + dy; + + tmp = dst->cb - dy; + h = ((tmp > src->h) ? src->h : tmp) - sybeg; + if (h <= 0) + return; + } + else { + w = src->w; + h = src->h; + sxbeg = 0; + sybeg = 0; + dxbeg = dx; + dybeg = dy; + } + + blender = MAKE_DLS_BLENDER(color); + + { + for (y = 0; y < h; y++) { + PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); + PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); + + for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { + unsigned long c = GET_MEMORY_PIXEL(s); + + if (!IS_MASK(c)) { + c = DLS_BLEND(blender, color, c); + PUT_MEMORY_PIXEL(d, c); + } + } + } + } +} + +#endif /* !__bma_cspr_h */ + diff --git a/libsrc/allegro/src/c/cspr15.c b/libsrc/allegro/src/c/cspr15.c new file mode 100644 index 00000000000..bcb960248a8 --- /dev/null +++ b/libsrc/allegro/src/c/cspr15.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 15 bit color sprite drawing functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR16 + +#include "allegro/internal/aintern.h" +#include "cdefs15.h" +#include "cspr.h" + +#endif + diff --git a/libsrc/allegro/src/c/cspr16.c b/libsrc/allegro/src/c/cspr16.c new file mode 100644 index 00000000000..ca90ffff4d2 --- /dev/null +++ b/libsrc/allegro/src/c/cspr16.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 16 bit color sprite drawing functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR16 + +#include "allegro/internal/aintern.h" +#include "cdefs16.h" +#include "cspr.h" + +#endif + diff --git a/libsrc/allegro/src/c/cspr24.c b/libsrc/allegro/src/c/cspr24.c new file mode 100644 index 00000000000..5e6610a0e6f --- /dev/null +++ b/libsrc/allegro/src/c/cspr24.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 24 bit color sprite drawing functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR24 + +#include "allegro/internal/aintern.h" +#include "cdefs24.h" +#include "cspr.h" + +#endif + diff --git a/libsrc/allegro/src/c/cspr32.c b/libsrc/allegro/src/c/cspr32.c new file mode 100644 index 00000000000..787cd43c51d --- /dev/null +++ b/libsrc/allegro/src/c/cspr32.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 32 bit color sprite drawing functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR32 + +#include "allegro/internal/aintern.h" +#include "cdefs32.h" +#include "cspr.h" + +#endif + diff --git a/libsrc/allegro/src/c/cspr8.c b/libsrc/allegro/src/c/cspr8.c new file mode 100644 index 00000000000..0334779f4fd --- /dev/null +++ b/libsrc/allegro/src/c/cspr8.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 256 color sprite drawing functions. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#ifdef ALLEGRO_COLOR8 + +#include "allegro/internal/aintern.h" +#include "cdefs8.h" +#include "cspr.h" + +#endif + diff --git a/libsrc/allegro/src/c/cstretch.c b/libsrc/allegro/src/c/cstretch.c new file mode 100644 index 00000000000..71cc6c3cdcd --- /dev/null +++ b/libsrc/allegro/src/c/cstretch.c @@ -0,0 +1,460 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Bitmap stretching functions. + * + * By Michael Bukin. + * Fixed and improved in 2007 by Trent Gamblin. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + + + +/* Information for stretching line */ +static struct { + int xcstart; /* x counter start */ + int sxinc; /* amount to increment src x every time */ + int xcdec; /* amount to deccrement counter by, increase sptr when this reaches 0 */ + int xcinc; /* amount to increment counter by when it reaches 0 */ + int linesize; /* size of a whole row of pixels */ +} _al_stretch; + + + +/* Stretcher macros */ +#define DECLARE_STRETCHER(type, size, put, get) \ + int xc = _al_stretch.xcstart; \ + uintptr_t dend = dptr + _al_stretch.linesize; \ + ASSERT(dptr); \ + ASSERT(sptr); \ + for (; dptr < dend; dptr += size, sptr += _al_stretch.sxinc) { \ + put(dptr, get((type*)sptr)); \ + if (xc <= 0) { \ + sptr += size; \ + xc += _al_stretch.xcinc; \ + } \ + else \ + xc -= _al_stretch.xcdec; \ + } + + + +#define DECLARE_MASKED_STRETCHER(type, size, put, get, mask) \ + int xc = _al_stretch.xcstart; \ + uintptr_t dend = dptr + _al_stretch.linesize; \ + ASSERT(dptr); \ + ASSERT(sptr); \ + for (; dptr < dend; dptr += size, sptr += _al_stretch.sxinc) { \ + int color = get((type*)sptr); \ + if (color != mask) \ + put(dptr, get((type*)sptr)); \ + if (xc <= 0) { \ + sptr += size; \ + xc += _al_stretch.xcinc; \ + } \ + else \ + xc -= _al_stretch.xcdec; \ + } + + + +#ifdef ALLEGRO_GFX_HAS_VGA +/* + * Mode-X line stretcher. + */ +static void stretch_linex(uintptr_t dptr, unsigned char *sptr) +{ + int plane; + int first_xc = _al_stretch.xcstart; + int dw = _al_stretch.linesize; + + ASSERT(dptr); + ASSERT(sptr); + + for (plane = 0; plane < 4; plane++) { + int xc = first_xc; + unsigned char *s = sptr; + uintptr_t d = dptr / 4; + uintptr_t dend = (dptr + dw) / 4; + + outportw(0x3C4, (0x100 << (dptr & 3)) | 2); + + for (; d < dend; d++, s += 4 * _al_stretch.sxinc) { + bmp_write8(d, *s); + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + } + + /* Move to the beginning of next plane. */ + if (first_xc <= 0) { + sptr++; + first_xc += _al_stretch.xcinc; + } + else + first_xc -= _al_stretch.xcdec; + + dptr++; + sptr += _al_stretch.sxinc; + dw--; + } +} + +/* + * Mode-X masked line stretcher. + */ +static void stretch_masked_linex(uintptr_t dptr, unsigned char *sptr) +{ + int plane; + int dw = _al_stretch.linesize; + int first_xc = _al_stretch.xcstart; + + ASSERT(dptr); + ASSERT(sptr); + + for (plane = 0; plane < 4; plane++) { + int xc = first_xc; + unsigned char *s = sptr; + uintptr_t d = dptr / 4; + uintptr_t dend = (dptr + dw) / 4; + + outportw(0x3C4, (0x100 << (dptr & 3)) | 2); + + for (; d < dend; d++, s += 4 * _al_stretch.sxinc) { + unsigned long color = *s; + if (color != 0) + bmp_write8(d, color); + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + if (xc <= 0) s++, xc += _al_stretch.xcinc; + else xc -= _al_stretch.xcdec; + } + + /* Move to the beginning of next plane. */ + if (first_xc <= 0) { + sptr++; + first_xc += _al_stretch.xcinc; + } + else + first_xc -= _al_stretch.xcdec; + + dptr++; + sptr += _al_stretch.sxinc; + dw--; + } +} +#endif + + + +#ifdef ALLEGRO_COLOR8 +static void stretch_line8(uintptr_t dptr, unsigned char *sptr) +{ + DECLARE_STRETCHER(unsigned char, 1, bmp_write8, *); +} + +static void stretch_masked_line8(uintptr_t dptr, unsigned char *sptr) +{ + DECLARE_MASKED_STRETCHER(unsigned char, 1, bmp_write8, *, 0); +} +#endif + + + +#ifdef ALLEGRO_COLOR16 +static void stretch_line15(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_STRETCHER(unsigned short, 2, bmp_write15, *); +} + +static void stretch_line16(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_STRETCHER(unsigned short, 2, bmp_write16, *); +} + +static void stretch_masked_line15(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_MASKED_STRETCHER(unsigned short, 2, bmp_write15, *, MASK_COLOR_15); +} + +static void stretch_masked_line16(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_MASKED_STRETCHER(unsigned short, 2, bmp_write16, *, MASK_COLOR_16); +} +#endif + + + +#ifdef ALLEGRO_COLOR24 +static void stretch_line24(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_STRETCHER(unsigned char, 3, bmp_write24, READ3BYTES); +} + +static void stretch_masked_line24(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_MASKED_STRETCHER(unsigned char, 3, bmp_write24, READ3BYTES, MASK_COLOR_24); +} +#endif + + + +#ifdef ALLEGRO_COLOR32 +static void stretch_line32(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_STRETCHER(uint32_t, 4, bmp_write32, *); +} + +static void stretch_masked_line32(uintptr_t dptr, unsigned char* sptr) +{ + DECLARE_MASKED_STRETCHER(uint32_t, 4, bmp_write32, *, MASK_COLOR_32); +} +#endif + + + +/* + * Stretch blit work-horse. + */ +static void _al_stretch_blit(BITMAP *src, BITMAP *dst, + int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, + int masked) +{ + int y; /* current dst y */ + int yc; /* y counter */ + int sxofs, dxofs; /* start offsets */ + int syinc; /* amount to increment src y each time */ + int ycdec; /* amount to deccrement counter by, increase sy when this reaches 0 */ + int ycinc; /* amount to increment counter by when it reaches 0 */ + int size = 0; /* pixel size */ + int dxbeg, dxend; /* clipping information */ + int dybeg, dyend; + int i; + + void (*stretch_line)(uintptr_t, unsigned char*) = 0; + + ASSERT(src); + ASSERT(dst); + + /* vtable hook; not called if dest is a memory surface */ + if (src->vtable->do_stretch_blit && !is_memory_bitmap(dst)) { + src->vtable->do_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, masked); + return; + } + + if ((sw <= 0) || (sh <= 0) || (dw <= 0) || (dh <= 0)) + return; + + /* Find out which stretcher should be used */ + if (masked) { + switch (bitmap_color_depth(dst)) { +#ifdef ALLEGRO_COLOR8 + case 8: + if (is_linear_bitmap(dst)) + stretch_line = stretch_masked_line8; +#ifdef ALLEGRO_GFX_HAS_VGA + else + stretch_line = stretch_masked_linex; +#endif + size = 1; + break; +#endif +#ifdef ALLEGRO_COLOR16 + case 15: + stretch_line = stretch_masked_line15; + size = 2; + break; + case 16: + stretch_line = stretch_masked_line16; + size = 2; + break; +#endif +#ifdef ALLEGRO_COLOR24 + case 24: + stretch_line = stretch_masked_line24; + size = 3; + break; +#endif +#ifdef ALLEGRO_COLOR32 + case 32: + stretch_line = stretch_masked_line32; + size = 4; + break; +#endif + } + } + else { + switch (bitmap_color_depth(dst)) { +#ifdef ALLEGRO_COLOR8 + case 8: + if (is_linear_bitmap(dst)) + stretch_line = stretch_line8; +#ifdef ALLEGRO_GFX_HAS_VGA + else + stretch_line = stretch_linex; +#endif + size = 1; + break; +#endif +#ifdef ALLEGRO_COLOR16 + case 15: + stretch_line = stretch_line15; + size = 2; + break; + case 16: + stretch_line = stretch_line16; + size = 2; + break; +#endif +#ifdef ALLEGRO_COLOR24 + case 24: + stretch_line = stretch_line24; + size = 3; + break; +#endif +#ifdef ALLEGRO_COLOR32 + case 32: + stretch_line = stretch_line32; + size = 4; + break; +#endif + } + } + + ASSERT(stretch_line); + + if (dst->clip) { + dybeg = ((dy > dst->ct) ? dy : dst->ct); + dyend = (((dy + dh) < dst->cb) ? (dy + dh) : dst->cb); + if (dybeg >= dyend) + return; + + dxbeg = ((dx > dst->cl) ? dx : dst->cl); + dxend = (((dx + dw) < dst->cr) ? (dx + dw) : dst->cr); + if (dxbeg >= dxend) + return; + } + else { + dxbeg = dx; + dxend = dx + dw; + dybeg = dy; + dyend = dy + dh; + } + + syinc = sh / dh; + ycdec = sh - (syinc*dh); + ycinc = dh - ycdec; + yc = ycinc; + sxofs = sx * size; + dxofs = dx * size; + + _al_stretch.sxinc = sw / dw * size; + _al_stretch.xcdec = sw - ((sw/dw)*dw); + _al_stretch.xcinc = dw - _al_stretch.xcdec; + _al_stretch.linesize = (dxend-dxbeg)*size; + + /* get start state (clip) */ + _al_stretch.xcstart = _al_stretch.xcinc; + for (i = 0; i < dxbeg-dx; i++, sxofs += _al_stretch.sxinc) { + if (_al_stretch.xcstart <= 0) { + _al_stretch.xcstart += _al_stretch.xcinc; + sxofs += size; + } + else + _al_stretch.xcstart -= _al_stretch.xcdec; + } + + dxofs += i * size; + + /* skip clipped lines */ + for (y = dy; y < dybeg; y++, sy += syinc) { + if (yc <= 0) { + sy++; + yc += ycinc; + } + else + yc -= ycdec; + } + + /* Stretch it */ + + bmp_select(dst); + + for (; y < dyend; y++, sy += syinc) { + (*stretch_line)(bmp_write_line(dst, y) + dxofs, src->line[sy] + sxofs); + if (yc <= 0) { + sy++; + yc += ycinc; + } + else + yc -= ycdec; + } + + bmp_unwrite_line(dst); +} + + + +/* stretch_blit: + * Opaque bitmap scaling function. + */ +void stretch_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int sw, int sh, + int dx, int dy, int dw, int dh) +{ + ASSERT(src); + ASSERT(dst); + + #ifdef ALLEGRO_MPW + if (is_system_bitmap(src) && is_system_bitmap(dst)) + system_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh); + else + #endif + _al_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, 0); +} + + + +/* masked_stretch_blit: + * Masked bitmap scaling function. + */ +void masked_stretch_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int sw, int sh, + int dx, int dy, int dw, int dh) +{ + ASSERT(src); + ASSERT(dst); + + _al_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, 1); +} + + + +/* stretch_sprite: + * Masked version of stretch_blit(). + */ +void stretch_sprite(BITMAP *dst, BITMAP *src, int x, int y, int w, int h) +{ + ASSERT(src); + ASSERT(dst); + + _al_stretch_blit(src, dst, 0, 0, src->w, src->h, x, y, w, h, 1); +} diff --git a/libsrc/allegro/src/colblend.c b/libsrc/allegro/src/colblend.c new file mode 100644 index 00000000000..a9b9a3be013 --- /dev/null +++ b/libsrc/allegro/src/colblend.c @@ -0,0 +1,446 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Interpolation routines for hicolor and truecolor pixels. + * + * By Cloud Wu and Burton Radons. + * + * Alpha blending optimised by Peter Cech. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#define BLEND(bpp, r, g, b) _blender_trans##bpp(makecol##bpp(r, g, b), y, n) + +#define T(x, y, n) (((y) - (x)) * (n) / 255 + (x)) + + + +/* _blender_black: + * Fallback routine for when we don't have anything better to do. + */ +unsigned long _blender_black(unsigned long x, unsigned long y, unsigned long n) +{ + return 0; +} + + + +#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) + + + +#if (defined ALLEGRO_NO_ASM) || (!defined ALLEGRO_I386) + /* i386 asm version is in imisc.s */ + + +/* _blender_trans24: + * 24 bit trans blender function. + */ +unsigned long _blender_trans24(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long res, g; + + if (n) + n++; + + res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; + y &= 0xFF00; + x &= 0xFF00; + g = (x - y) * n / 256 + y; + + res &= 0xFF00FF; + g &= 0xFF00; + + return res | g; +} + + +#endif /* C version */ + + + +/* _blender_alpha24: + * Combines a 32 bit RGBA sprite with a 24 bit RGB destination. + */ +unsigned long _blender_alpha24(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long xx = makecol24(getr32(x), getg32(x), getb32(x)); + unsigned long res, g; + + n = geta32(x); + + if (n) + n++; + + res = ((xx & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; + y &= 0xFF00; + xx &= 0xFF00; + g = (xx - y) * n / 256 + y; + + res &= 0xFF00FF; + g &= 0xFF00; + + return res | g; +} + + + +/* _blender_alpha32: + * Combines a 32 bit RGBA sprite with a 32 bit RGB destination. + */ +unsigned long _blender_alpha32(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long res, g; + + n = geta32(x); + + if (n) + n++; + + res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; + y &= 0xFF00; + x &= 0xFF00; + g = (x - y) * n / 256 + y; + + res &= 0xFF00FF; + g &= 0xFF00; + + return res | g; +} + + + +/* _blender_alpha24_bgr: + * Combines a 32 bit RGBA sprite with a 24 bit RGB destination, optimised + * for when one is in a BGR format and the other is RGB. + */ +unsigned long _blender_alpha24_bgr(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long res, g; + + n = x >> 24; + + if (n) + n++; + + x = ((x>>16)&0xFF) | (x&0xFF00) | ((x<<16)&0xFF0000); + + res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; + y &= 0xFF00; + x &= 0xFF00; + g = (x - y) * n / 256 + y; + + res &= 0xFF00FF; + g &= 0xFF00; + + return res | g; +} + +#endif /* end of 24/32 bit routines */ + + +#if (defined ALLEGRO_COLOR15) || (defined ALLEGRO_COLOR16) + + + +/* _blender_trans16: + * 16 bit trans blender function. + */ +unsigned long _blender_trans16(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + if (n) + n = (n + 1) / 8; + + x = ((x & 0xFFFF) | (x << 16)) & 0x7E0F81F; + y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; + + result = ((x - y) * n / 32 + y) & 0x7E0F81F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + + +/* _blender_alpha16: + * Combines a 32 bit RGBA sprite with a 16 bit RGB destination. + */ +unsigned long _blender_alpha16(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + n = geta32(x); + + if (n) + n = (n + 1) / 8; + + x = makecol16(getr32(x), getg32(x), getb32(x)); + + x = (x | (x << 16)) & 0x7E0F81F; + y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; + + result = ((x - y) * n / 32 + y) & 0x7E0F81F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + + +/* _blender_alpha16_rgb + * Combines a 32 bit RGBA sprite with a 16 bit RGB destination, optimised + * for when both pixels are in an RGB layout. + */ +unsigned long _blender_alpha16_rgb(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + n = x >> 24; + + if (n) + n = (n + 1) / 8; + + x = ((x>>3)&0x001F) | ((x>>5)&0x07E0) | ((x>>8)&0xF800); + + x = (x | (x << 16)) & 0x7E0F81F; + y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; + + result = ((x - y) * n / 32 + y) & 0x7E0F81F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + + +/* _blender_alpha16_bgr + * Combines a 32 bit RGBA sprite with a 16 bit RGB destination, optimised + * for when one pixel is in an RGB layout and the other is BGR. + */ +unsigned long _blender_alpha16_bgr(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + n = x >> 24; + + if (n) + n = (n + 1) / 8; + + x = ((x>>19)&0x001F) | ((x>>5)&0x07E0) | ((x<<8)&0xF800); + + x = (x | (x << 16)) & 0x7E0F81F; + y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; + + result = ((x - y) * n / 32 + y) & 0x7E0F81F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + +/* _blender_trans15: + * 15 bit trans blender function. + */ +unsigned long _blender_trans15(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + if (n) + n = (n + 1) / 8; + + x = ((x & 0xFFFF) | (x << 16)) & 0x3E07C1F; + y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; + + result = ((x - y) * n / 32 + y) & 0x3E07C1F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + + +/* _blender_alpha15: + * Combines a 32 bit RGBA sprite with a 15 bit RGB destination. + */ +unsigned long _blender_alpha15(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + n = geta32(x); + + if (n) + n = (n + 1) / 8; + + x = makecol15(getr32(x), getg32(x), getb32(x)); + + x = (x | (x << 16)) & 0x3E07C1F; + y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; + + result = ((x - y) * n / 32 + y) & 0x3E07C1F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + + +/* _blender_alpha15_rgb + * Combines a 32 bit RGBA sprite with a 15 bit RGB destination, optimised + * for when both pixels are in an RGB layout. + */ +unsigned long _blender_alpha15_rgb(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + n = x >> 24; + + if (n) + n = (n + 1) / 8; + + x = ((x>>3)&0x001F) | ((x>>6)&0x03E0) | ((x>>9)&0xEC00); + + x = (x | (x << 16)) & 0x3E07C1F; + y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; + + result = ((x - y) * n / 32 + y) & 0x3E07C1F; + + return ((result & 0xFFFF) | (result >> 16)); +} + + + +/* _blender_alpha15_bgr + * Combines a 32 bit RGBA sprite with a 15 bit RGB destination, optimised + * for when one pixel is in an RGB layout and the other is BGR. + */ +unsigned long _blender_alpha15_bgr(unsigned long x, unsigned long y, unsigned long n) +{ + unsigned long result; + + n = x >> 24; + + if (n) + n = (n + 1) / 8; + + x = ((x>>19)&0x001F) | ((x>>6)&0x03E0) | ((x<<7)&0xEC00); + + x = (x | (x << 16)) & 0x3E07C1F; + y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; + + result = ((x - y) * n / 32 + y) & 0x3E07C1F; + + return ((result & 0xFFFF) | (result >> 16)); +} + +#endif /* end of 15/16 bit routines */ + + + +#ifdef ALLEGRO_COLOR16 + #define BF16(name) name +#else + #define BF16(name) _blender_black +#endif + + +#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) + #define BF24(name) name +#else + #define BF24(name) _blender_black +#endif + + + +/* these functions are all the same, so we can generate them with a macro */ +#define SET_BLENDER_FUNC(name) \ + void set_##name##_blender(int r, int g, int b, int a) \ + { \ + set_blender_mode(BF16(_blender_##name##15), \ + BF16(_blender_##name##16), \ + BF24(_blender_##name##24), \ + r, g, b, a); \ + } + + +SET_BLENDER_FUNC(trans); + + + +/* set_alpha_blender: + * Sets the special RGBA blending mode. + */ +void set_alpha_blender(void) +{ + BLENDER_FUNC f15, f16, f24, f32; + int r, b; + + /* check which way around the 32 bit pixels are */ + if ((_rgb_g_shift_32 == 8) && (_rgb_a_shift_32 == 24)) { + r = (_rgb_r_shift_32) ? 1 : 0; + b = (_rgb_b_shift_32) ? 1 : 0; + } + else + r = b = 0; + + #ifdef ALLEGRO_COLOR16 + + /* decide which 15 bit blender to use */ + if ((_rgb_r_shift_15 == r*10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == b*10)) + f15 = _blender_alpha15_rgb; + else if ((_rgb_r_shift_15 == b*10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == r*10)) + f15 = _blender_alpha15_bgr; + else + f15 = _blender_alpha15; + + /* decide which 16 bit blender to use */ + if ((_rgb_r_shift_16 == r*11) && (_rgb_g_shift_16 == 5) && (_rgb_b_shift_16 == b*11)) + f16 = _blender_alpha16_rgb; + else if ((_rgb_r_shift_16 == b*11) && (_rgb_g_shift_16 == 5) && (_rgb_b_shift_16 == r*11)) + f16 = _blender_alpha16_bgr; + else + f16 = _blender_alpha16; + + #else + + /* hicolor not included in this build */ + f15 = _blender_black; + f16 = _blender_black; + + #endif + + #ifdef ALLEGRO_COLOR24 + + /* decide which 24 bit blender to use */ + if ((_rgb_r_shift_24 == r*16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == b*16)) + f24 = _blender_alpha32; + else if ((_rgb_r_shift_24 == b*16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == r*16)) + f24 = _blender_alpha24_bgr; + else + f24 = _blender_alpha24; + + #else + + /* 24 bit color not included in this build */ + f24 = _blender_black; + + #endif + + #ifdef ALLEGRO_COLOR32 + f32 = _blender_alpha32; + #else + f32 = _blender_black; + #endif + + set_blender_mode_ex(_blender_black, _blender_black, _blender_black, + f32, f15, f16, f24, 0, 0, 0, 0); +} diff --git a/libsrc/allegro/src/color.c b/libsrc/allegro/src/color.c new file mode 100644 index 00000000000..ce0da817544 --- /dev/null +++ b/libsrc/allegro/src/color.c @@ -0,0 +1,889 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Color manipulation routines (blending, format conversion, lighting + * table construction, etc). + * + * By Shawn Hargreaves. + * + * Dave Thomson contributed the RGB <-> HSV conversion routines. + * + * Jan Hubicka wrote the super-fast version of create_rgb_table(). + * + * Michael Bevin and Sven Sandberg optimised the create_trans_table() + * function. + * + * Sven Sandberg optimised the create_light_table() function. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* makecol_depth: + * Converts R, G, and B values (ranging 0-255) to whatever pixel format + * is required by the specified color depth. + */ +int makecol_depth(int color_depth, int r, int g, int b) +{ + switch (color_depth) { + + case 8: + return makecol8(r, g, b); + + case 15: + return makecol15(r, g, b); + + case 16: + return makecol16(r, g, b); + + case 24: + return makecol24(r, g, b); + + case 32: + return makecol32(r, g, b); + } + + return 0; +} + + + +/* makeacol_depth: + * Converts R, G, B, and A values (ranging 0-255) to whatever pixel format + * is required by the specified color depth. + */ +int makeacol_depth(int color_depth, int r, int g, int b, int a) +{ + switch (color_depth) { + + case 8: + return makecol8(r, g, b); + + case 15: + return makecol15(r, g, b); + + case 16: + return makecol16(r, g, b); + + case 24: + return makecol24(r, g, b); + + case 32: + return makeacol32(r, g, b, a); + } + + return 0; +} + + + +/* makecol: + * Converts R, G, and B values (ranging 0-255) to whatever pixel format + * is required by the current video mode. + */ +int makecol(int r, int g, int b) +{ + return makecol_depth(_color_depth, r, g, b); +} + + + +/* makeacol: + * Converts R, G, B, and A values (ranging 0-255) to whatever pixel format + * is required by the current video mode. + */ +int makeacol(int r, int g, int b, int a) +{ + return makeacol_depth(_color_depth, r, g, b, a); +} + + + +/* getr_depth: + * Extracts the red component (ranging 0-255) from a pixel in the format + * being used by the specified color depth. + */ +int getr_depth(int color_depth, int c) +{ + switch (color_depth) { + + case 8: + return getr8(c); + + case 15: + return getr15(c); + + case 16: + return getr16(c); + + case 24: + return getr24(c); + + case 32: + return getr32(c); + } + + return 0; +} + + + +/* getg_depth: + * Extracts the green component (ranging 0-255) from a pixel in the format + * being used by the specified color depth. + */ +int getg_depth(int color_depth, int c) +{ + switch (color_depth) { + + case 8: + return getg8(c); + + case 15: + return getg15(c); + + case 16: + return getg16(c); + + case 24: + return getg24(c); + + case 32: + return getg32(c); + } + + return 0; +} + + + +/* getb_depth: + * Extracts the blue component (ranging 0-255) from a pixel in the format + * being used by the specified color depth. + */ +int getb_depth(int color_depth, int c) +{ + switch (color_depth) { + + case 8: + return getb8(c); + + case 15: + return getb15(c); + + case 16: + return getb16(c); + + case 24: + return getb24(c); + + case 32: + return getb32(c); + } + + return 0; +} + + + +/* geta_depth: + * Extracts the alpha component (ranging 0-255) from a pixel in the format + * being used by the specified color depth. + */ +int geta_depth(int color_depth, int c) +{ + if (color_depth == 32) + return geta32(c); + + return 0; +} + + + +/* getr: + * Extracts the red component (ranging 0-255) from a pixel in the format + * being used by the current video mode. + */ +int getr(int c) +{ + return getr_depth(_color_depth, c); +} + + + +/* getg: + * Extracts the green component (ranging 0-255) from a pixel in the format + * being used by the current video mode. + */ +int getg(int c) +{ + return getg_depth(_color_depth, c); +} + + + +/* getb: + * Extracts the blue component (ranging 0-255) from a pixel in the format + * being used by the current video mode. + */ +int getb(int c) +{ + return getb_depth(_color_depth, c); +} + + + +/* geta: + * Extracts the alpha component (ranging 0-255) from a pixel in the format + * being used by the current video mode. + */ +int geta(int c) +{ + return geta_depth(_color_depth, c); +} + + + +/* 1.5k lookup table for color matching */ +static unsigned int col_diff[3*128]; + + + +/* bestfit_init: + * Color matching is done with weighted squares, which are much faster + * if we pregenerate a little lookup table... + */ +static void bestfit_init(void) +{ + int i; + + for (i=1; i<64; i++) { + int k = i * i; + col_diff[0 +i] = col_diff[0 +128-i] = k * (59 * 59); + col_diff[128+i] = col_diff[128+128-i] = k * (30 * 30); + col_diff[256+i] = col_diff[256+128-i] = k * (11 * 11); + } +} + + + +/* bestfit_color: + * Searches a palette for the color closest to the requested R, G, B value. + */ +int bestfit_color(AL_CONST PALETTE pal, int r, int g, int b) +{ + int i, coldiff, lowest, bestfit; + + ASSERT(r >= 0 && r <= 63); + ASSERT(g >= 0 && g <= 63); + ASSERT(b >= 0 && b <= 63); + + if (col_diff[1] == 0) + bestfit_init(); + + bestfit = 0; + lowest = INT_MAX; + + /* only the transparent (pink) color can be mapped to index 0 */ + if ((r == 63) && (g == 0) && (b == 63)) + i = 0; + else + i = 1; + + while (ig - g) & 0x7F ]; + if (coldiff < lowest) { + coldiff += (col_diff + 128) [ (rgb->r - r) & 0x7F ]; + if (coldiff < lowest) { + coldiff += (col_diff + 256) [ (rgb->b - b) & 0x7F ]; + if (coldiff < lowest) { + bestfit = rgb - pal; /* faster than `bestfit = i;' */ + if (coldiff == 0) + return bestfit; + lowest = coldiff; + } + } + } + i++; + } + + return bestfit; +} + + + +/* makecol8: + * Converts R, G, and B values (ranging 0-255) to an 8 bit paletted color. + * If the global rgb_map table is initialised, it uses that, otherwise + * it searches through the current palette to find the best match. + */ +int makecol8(int r, int g, int b) +{ + if (rgb_map) + return rgb_map->data[r>>3][g>>3][b>>3]; + else + return bestfit_color(_current_palette, r>>2, g>>2, b>>2); +} + + + +/* hsv_to_rgb: + * Converts from HSV colorspace to RGB values. + */ +void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b) +{ + float f, x, y, z; + int i; + + ASSERT(s >= 0 && s <= 1); + ASSERT(v >= 0 && v <= 1); + + v *= 255.0f; + + if (s == 0.0f) { /* ok since we don't divide by s, and faster */ + *r = *g = *b = v + 0.5f; + } + else { + h = fmod(h, 360.0f) / 60.0f; + if (h < 0.0f) + h += 6.0f; + + i = (int)h; + f = h - i; + x = v * s; + y = x * f; + v += 0.5f; /* round to the nearest integer below */ + z = v - x; + + switch (i) { + + case 6: + case 0: + *r = v; + *g = z + y; + *b = z; + break; + + case 1: + *r = v - y; + *g = v; + *b = z; + break; + + case 2: + *r = z; + *g = v; + *b = z + y; + break; + + case 3: + *r = z; + *g = v - y; + *b = v; + break; + + case 4: + *r = z + y; + *g = z; + *b = v; + break; + + case 5: + *r = v; + *g = z; + *b = v - y; + break; + } + } +} + + + +/* rgb_to_hsv: + * Converts an RGB value into the HSV colorspace. + */ +void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v) +{ + int delta; + + ASSERT(r >= 0 && r <= 255); + ASSERT(g >= 0 && g <= 255); + ASSERT(b >= 0 && b <= 255); + + if (r > g) { + if (b > r) { + /* b>r>g */ + delta = b-g; + *h = 240.0f + ((r-g) * 60) / (float)delta; + *s = (float)delta / (float)b; + *v = (float)b * (1.0f/255.0f); + } + else { + /* r>g and r>b */ + delta = r - MIN(g, b); + *h = ((g-b) * 60) / (float)delta; + if (*h < 0.0f) + *h += 360.0f; + *s = (float)delta / (float)r; + *v = (float)r * (1.0f/255.0f); + } + } + else { + if (b > g) { + /* b>g>=r */ + delta = b-r; + *h = 240.0f + ((r-g) * 60) / (float)delta; + *s = (float)delta / (float)b; + *v = (float)b * (1.0f/255.0f); + } + else { + /* g>=b and g>=r */ + delta = g - MIN(r, b); + if (delta == 0) { + *h = 0.0f; + if (g == 0) + *s = *v = 0.0f; + else { + *s = (float)delta / (float)g; + *v = (float)g * (1.0f/255.0f); + } + } + else { + *h = 120.0f + ((b-r) * 60) / (float)delta; + *s = (float)delta / (float)g; + *v = (float)g * (1.0f/255.0f); + } + } + } +} + + + +/* create_rgb_table: + * Fills an RGB_MAP lookup table with conversion data for the specified + * palette. This is the faster version by Jan Hubicka. + * + * Uses alg. similar to floodfill - it adds one seed per every color in + * palette to its best position. Then areas around seed are filled by + * same color because it is best approximation for them, and then areas + * about them etc... + * + * It does just about 80000 tests for distances and this is about 100 + * times better than normal 256*32000 tests so the calculation time + * is now less than one second at all computers I tested. + */ +void create_rgb_table(RGB_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) +{ + #define UNUSED 65535 + #define LAST 65532 + + /* macro add adds to single linked list */ + #define add(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \ + (first != LAST ? (next[last] = (i)) : (first = (i))), \ + (last = (i))) : 0) + + /* same but w/o checking for first element */ + #define add1(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \ + next[last] = (i), \ + (last = (i))) : 0) + + /* calculates distance between two colors */ + #define dist(a1, a2, a3, b1, b2, b3) \ + (col_diff[ ((a2) - (b2)) & 0x7F] + \ + (col_diff + 128)[((a1) - (b1)) & 0x7F] + \ + (col_diff + 256)[((a3) - (b3)) & 0x7F]) + + /* converts r,g,b to position in array and back */ + #define pos(r, g, b) \ + (((r) / 2) * 32 * 32 + ((g) / 2) * 32 + ((b) / 2)) + + #define depos(pal, r, g, b) \ + ((b) = ((pal) & 31) * 2, \ + (g) = (((pal) >> 5) & 31) * 2, \ + (r) = (((pal) >> 10) & 31) * 2) + + /* is current color better than pal1? */ + #define better(r1, g1, b1, pal1) \ + (((int)dist((r1), (g1), (b1), \ + (pal1).r, (pal1).g, (pal1).b)) > (int)dist2) + + /* checking of position */ + #define dopos(rp, gp, bp, ts) \ + if ((rp > -1 || r > 0) && (rp < 1 || r < 61) && \ + (gp > -1 || g > 0) && (gp < 1 || g < 61) && \ + (bp > -1 || b > 0) && (bp < 1 || b < 61)) { \ + i = first + rp * 32 * 32 + gp * 32 + bp; \ + if (!data[i]) { \ + data[i] = val; \ + add1(i); \ + } \ + else if ((ts) && (data[i] != val)) { \ + dist2 = (rp ? (col_diff+128)[(r+2*rp-pal[val].r) & 0x7F] : r2) + \ + (gp ? (col_diff )[(g+2*gp-pal[val].g) & 0x7F] : g2) + \ + (bp ? (col_diff+256)[(b+2*bp-pal[val].b) & 0x7F] : b2); \ + if (better((r+2*rp), (g+2*gp), (b+2*bp), pal[data[i]])) { \ + data[i] = val; \ + add1(i); \ + } \ + } \ + } + + int i, curr, r, g, b, val, dist2; + unsigned int r2, g2, b2; + unsigned short next[32*32*32]; + unsigned char *data; + int first = LAST; + int last = LAST; + int count = 0; + int cbcount = 0; + + #define AVERAGE_COUNT 18000 + + if (col_diff[1] == 0) + bestfit_init(); + + memset(next, 255, sizeof(next)); + memset(table->data, 0, sizeof(char)*32*32*32); + + data = (unsigned char *)table->data; + + /* add starting seeds for floodfill */ + for (i=1; i 0) && (data[first-1] == val)) { + b -= 2; + first--; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; + + dopos(-1, 0, 0, 0); + dopos( 1, 0, 0, 0); + dopos( 0,-1, 0, 0); + dopos( 0, 1, 0, 0); + + first++; + } + + /* get next from list */ + i = first; + first = next[first]; + next[i] = UNUSED; + + /* second version of loop */ + if (first != LAST) { + depos(first, r, g, b); + + val = data[first]; + r2 = (col_diff+128)[((pal[val].r)-(r)) & 0x7F]; + g2 = (col_diff )[((pal[val].g)-(g)) & 0x7F]; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; + + dopos( 0, 0, 1, 1); + dopos( 0, 0,-1, 1); + dopos( 1, 0, 0, 1); + dopos(-1, 0, 0, 1); + dopos( 0, 1, 0, 1); + dopos( 0,-1, 0, 1); + + if ((b < 61) && (data[first + 1] == val)) { + b += 2; + first++; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7f]; + + dopos(-1, 0, 0, 0); + dopos( 1, 0, 0, 0); + dopos( 0,-1, 0, 0); + dopos( 0, 1, 0, 0); + + first--; + } + + i = first; + first = next[first]; + next[i] = UNUSED; + } + + count++; + if (count == (cbcount+1)*AVERAGE_COUNT/256) { + if (cbcount < 256) { + if (callback) + callback(cbcount); + cbcount++; + } + } + } + + /* only the transparent (pink) color can be mapped to index 0 */ + if ((pal[0].r == 63) && (pal[0].g == 0) && (pal[0].b == 63)) + table->data[31][0][31] = 0; + + if (callback) + while (cbcount < 256) + callback(cbcount++); +} + + + +/* create_light_table: + * Constructs a lighting color table for the specified palette. At light + * intensity 255 the table will produce the palette colors directly, and + * at level 0 it will produce the specified R, G, B value for all colors + * (this is specified in 0-63 VGA format). If the callback function is + * not NULL, it will be called 256 times during the calculation, allowing + * you to display a progress indicator. + */ +void create_light_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) +{ + int r1, g1, b1, r2, g2, b2, x, y; + unsigned int t1, t2; + + ASSERT(table); + ASSERT(r >= 0 && r <= 63); + ASSERT(g >= 0 && g <= 63); + ASSERT(b >= 0 && b <= 63); + + if (rgb_map) { + for (x=0; x> 25; + g2 = (g1 + pal[y].g * t1) >> 25; + b2 = (b1 + pal[y].b * t1) >> 25; + + table->data[x][y] = rgb_map->data[r2][g2][b2]; + } + } + if (callback) + (*callback)(x); + } + else { + for (x=0; x> 24; + g2 = (g1 + pal[y].g * t1) >> 24; + b2 = (b1 + pal[y].b * t1) >> 24; + + table->data[x][y] = bestfit_color(pal, r2, g2, b2); + } + } + + if (callback) + (*callback)(x); + } + + for (y=0; ydata[255][y] = y; +} + + + +/* create_trans_table: + * Constructs a translucency color table for the specified palette. The + * r, g, and b parameters specifiy the solidity of each color component, + * ranging from 0 (totally transparent) to 255 (totally solid). Source + * color #0 is a special case, and is set to leave the destination + * unchanged, so that masked sprites will draw correctly. If the callback + * function is not NULL, it will be called 256 times during the calculation, + * allowing you to display a progress indicator. + */ +void create_trans_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) +{ + int tmp[768], *q; + int x, y, i, j, k; + unsigned char *p; + int tr, tg, tb; + int add; + + ASSERT(table); + ASSERT(r >= 0 && r <= 255); + ASSERT(g >= 0 && g <= 255); + ASSERT(b >= 0 && b <= 255); + + /* This is a bit ugly, but accounts for the solidity parameters + being in the range 0-255 rather than 0-256. Given that the + precision of r,g,b components is only 6 bits it shouldn't do any + harm. */ + if (r > 128) + r++; + if (g > 128) + g++; + if (b > 128) + b++; + + if (rgb_map) + add = 255; + else + add = 127; + + for (x=0; x<256; x++) { + tmp[x*3] = pal[x].r * (256-r) + add; + tmp[x*3+1] = pal[x].g * (256-g) + add; + tmp[x*3+2] = pal[x].b * (256-b) + add; + } + + for (x=1; xdata[x]; + q = tmp; + + if (rgb_map) { + for (y=0; y> 9; + tg = (j + *(q++)) >> 9; + tb = (k + *(q++)) >> 9; + p[y] = rgb_map->data[tr][tg][tb]; + } + } + else { + for (y=0; y> 8; + tg = (j + *(q++)) >> 8; + tb = (k + *(q++)) >> 8; + p[y] = bestfit_color(pal, tr, tg, tb); + } + } + + if (callback) + (*callback)(x-1); + } + + for (y=0; ydata[0][y] = y; + table->data[y][y] = y; + } + + if (callback) + (*callback)(255); +} + + + +/* create_color_table: + * Creates a color mapping table, using a user-supplied callback to blend + * each pair of colors. Your blend routine will be passed a pointer to the + * palette and the two colors to be blended (x is the source color, y is + * the destination), and should return the desired output RGB for this + * combination. If the callback function is not NULL, it will be called + * 256 times during the calculation, allowing you to display a progress + * indicator. + */ +void create_color_table(COLOR_MAP *table, AL_CONST PALETTE pal, void (*blend)(AL_CONST PALETTE pal, int x, int y, RGB *rgb), void (*callback)(int pos)) +{ + int x, y; + RGB c; + + for (x=0; xdata[x][y] = rgb_map->data[c.r>>1][c.g>>1][c.b>>1]; + else + table->data[x][y] = bestfit_color(pal, c.r, c.g, c.b); + } + + if (callback) + (*callback)(x); + } +} + + + +/* create_blender_table: + * Fills the specified color mapping table with lookup data for doing a + * paletted equivalent of whatever truecolor blender mode is currently + * selected. + */ +void create_blender_table(COLOR_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) +{ + int x, y, c; + int r, g, b; + int r1, g1, b1; + int r2, g2, b2; + + ASSERT(_blender_func24); + + for (x=0; x> 4); + g1 = (pal[x].g << 2) | ((pal[x].g & 0x30) >> 4); + b1 = (pal[x].b << 2) | ((pal[x].b & 0x30) >> 4); + + r2 = (pal[y].r << 2) | ((pal[y].r & 0x30) >> 4); + g2 = (pal[y].g << 2) | ((pal[y].g & 0x30) >> 4); + b2 = (pal[y].b << 2) | ((pal[y].b & 0x30) >> 4); + + c = _blender_func24(makecol24(r1, g1, b1), makecol24(r2, g2, b2), _blender_alpha); + + r = getr24(c); + g = getg24(c); + b = getb24(c); + + if (rgb_map) + table->data[x][y] = rgb_map->data[r>>3][g>>3][b>>3]; + else + table->data[x][y] = bestfit_color(pal, r>>2, g>>2, b>>2); + } + + if (callback) + (*callback)(x); + } +} + diff --git a/libsrc/allegro/src/dataregi.c b/libsrc/allegro/src/dataregi.c new file mode 100644 index 00000000000..ab675bbdb77 --- /dev/null +++ b/libsrc/allegro/src/dataregi.c @@ -0,0 +1,71 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Table of datafile loader routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* list of objects, and methods for loading and destroying them */ +DATAFILE_TYPE _datafile_type[MAX_DATAFILE_TYPES] = +{ + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, + { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL } +}; + + + +/* register_datafile_object: + * Registers a custom datafile object, providing functions for loading + * and destroying the objects. + */ +void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void (*destroy)(void *data)) +{ + int i; + + /* replacing an existing type? */ + for (i=0; i>3; + returned_g = g>>3; + returned_b = b>>3; + + y = dither_ytable[y&7]; + + bpos = (x+y)&7; + returned_r += (dither_table[r&7] >> bpos) & 1; + + bpos = (bpos+3)&7; + returned_b += (dither_table[b&7] >> bpos) & 1; + + bpos = (bpos+7)&7; + returned_g += (dither_table[g&7] >> bpos) & 1; + + returned_r -= returned_r>>5; + returned_g -= returned_g>>5; + returned_b -= returned_b>>5; + + return (returned_r<<_rgb_r_shift_15) | (returned_g<<_rgb_g_shift_15) | (returned_b<<_rgb_b_shift_15); +} + + + +/* makecol16_dither: + * Calculates a dithered 16 bit pixel value. + */ +int makecol16_dither(int r, int g, int b, int x, int y) +{ + int returned_r, returned_g, returned_b; + int bpos; + + returned_r = r>>3; + returned_g = g>>2; + returned_b = b>>3; + + y = dither_ytable[y&7]; + + bpos = (x+y)&7; + returned_r += (dither_table[r&7] >> bpos) & 1; + + bpos = (bpos+3)&7; + returned_b += (dither_table[b&7] >> bpos) & 1; + + bpos = (bpos+7)&7; + returned_g += (dither_table[(g&3)*2] >> bpos) & 1; + + returned_r -= returned_r>>5; + returned_g -= returned_g>>6; + returned_b -= returned_b>>5; + + return (returned_r<<_rgb_r_shift_16) | (returned_g<<_rgb_g_shift_16) | (returned_b<<_rgb_b_shift_16); +} + + diff --git a/libsrc/allegro/src/file.c b/libsrc/allegro/src/file.c new file mode 100644 index 00000000000..a4f17c493a2 --- /dev/null +++ b/libsrc/allegro/src/file.c @@ -0,0 +1,1663 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * File I/O. + * + * By Shawn Hargreaves. + * + * _pack_fdopen() and related modifications by Annie Testes. + * + * Evert Glebbeek added the support for relative filenames: + * make_absolute_filename(), make_relative_filename() and + * is_relative_filename(). + * + * Peter Wang added support for packfile vtables. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + +#ifndef ALLEGRO_MPW + #include +#endif + +#if defined (ALLEGRO_UNIX) || defined (ALLEGRO_MACOSX) + #include /* for tilde expansion */ +#endif + +#ifdef ALLEGRO_WINDOWS + #include "winalleg.h" /* for GetTempPath */ +#endif + +#ifndef O_BINARY + #define O_BINARY 0 +#endif + +/* permissions to use when opening files */ +#ifndef ALLEGRO_MPW + +/* some OSes have no concept of "group" and "other" */ +#ifndef S_IRGRP + #define S_IRGRP 0 + #define S_IWGRP 0 +#endif +#ifndef S_IROTH + #define S_IROTH 0 + #define S_IWOTH 0 +#endif + +#define OPEN_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) + +#endif /* !ALLEGRO_MPW */ + + + +static char the_password[256] = EMPTY_STRING; + +int _packfile_filesize = 0; +int _packfile_datasize = 0; + +int _packfile_type = 0; + +static PACKFILE_VTABLE normal_vtable; + +static int filename_encoding = U_ASCII; + + +#define FA_DAT_FLAGS (FA_RDONLY | FA_ARCH) + + + + + +/*************************************************** + ****************** Path handling ****************** + ***************************************************/ + + +/* fix_filename_case: + * Converts filename to upper case. + */ +char *fix_filename_case(char *filename) +{ + ASSERT(filename); + + if (!ALLEGRO_LFN) + ustrupr(filename); + + return filename; +} + + + +/* fix_filename_slashes: + * Converts '/' or '\' to system specific path separator. + */ +char *fix_filename_slashes(char *filename) +{ + int pos, c; + ASSERT(filename); + + for (pos=0; ugetc(filename+pos); pos+=uwidth(filename+pos)) { + c = ugetc(filename+pos); + if ((c == '/') || (c == '\\')) + usetat(filename+pos, 0, OTHER_PATH_SEPARATOR); + } + + return filename; +} + + + +/* Canonicalize_filename: + * Returns the canonical form of the specified filename, i.e. the + * minimal absolute filename describing the same file. + */ +char *canonicalize_filename(char *dest, AL_CONST char *filename, int size) +{ + int saved_errno = errno; + char buf[1024], buf2[1024]; + char *p; + int pos = 0; + int drive = -1; + int c1, i; + ASSERT(dest); + ASSERT(filename); + ASSERT(size >= 0); + + #if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0') + + /* check whether we have a drive letter */ + c1 = utolower(ugetc(filename)); + if ((c1 >= 'a') && (c1 <= 'z')) { + int c2 = ugetat(filename, 1); + if (c2 == DEVICE_SEPARATOR) { + drive = c1 - 'a'; + filename += uwidth(filename); + filename += uwidth(filename); + } + } + + /* if not, use the current drive */ + if (drive < 0) + drive = _al_getdrive(); + + pos += usetc(buf+pos, drive+'a'); + pos += usetc(buf+pos, DEVICE_SEPARATOR); + + #endif + + #if defined (ALLEGRO_UNIX) || defined (ALLEGRO_MACOSX) + + /* if the filename starts with ~ then it's relative to a home directory */ + if ((ugetc(filename) == '~')) { + AL_CONST char *tail = filename + uwidth(filename); /* could be the username */ + char *home = NULL; /* their home directory */ + + if (ugetc(tail) == '/' || !ugetc(tail)) { + /* easy */ + home = getenv("HOME"); + if (home) + home = _al_strdup(home); + } + else { + /* harder */ + char *username = (char *)tail, *ascii_username, *ch; + int userlen; + struct passwd *pwd; + + /* find the end of the username */ + tail = ustrchr(username, '/'); + if (!tail) + tail = ustrchr(username, '\0'); + + /* this ought to be the ASCII length, but I can't see a Unicode + * function to return the difference in characters between two + * pointers. This code is safe on the assumption that ASCII is + * the most efficient encoding, but wasteful of memory */ + userlen = tail - username + ucwidth('\0'); + ascii_username = _AL_MALLOC_ATOMIC(userlen); + + if (ascii_username) { + /* convert the username to ASCII, find the password entry, + * and copy their home directory. */ + do_uconvert(username, U_CURRENT, ascii_username, U_ASCII, userlen); + + if ((ch = strchr(ascii_username, '/'))) + *ch = '\0'; + + setpwent(); + + while (((pwd = getpwent()) != NULL) && + (strcmp(pwd->pw_name, ascii_username) != 0)) + ; + + _AL_FREE(ascii_username); + + if (pwd) + home = _al_strdup(pwd->pw_dir); + + endpwent(); + } + } + + /* If we got a home directory, prepend it to the filename. Otherwise + * we leave the filename alone, like bash but not tcsh; bash is better + * anyway. :) + */ + if (home) { + do_uconvert(home, U_ASCII, buf+pos, U_CURRENT, sizeof(buf)-pos); + _AL_FREE(home); + pos = ustrsize(buf); + filename = tail; + goto no_relativisation; + } + } + + #endif /* Unix */ + + /* if the filename is relative, make it absolute */ + if ((ugetc(filename) != '/') && (ugetc(filename) != OTHER_PATH_SEPARATOR) && (ugetc(filename) != '#')) { + _al_getdcwd(drive, buf2, sizeof(buf2) - ucwidth(OTHER_PATH_SEPARATOR)); + put_backslash(buf2); + + p = buf2; + if ((utolower(p[0]) >= 'a') && (utolower(p[0]) <= 'z') && (p[1] == DEVICE_SEPARATOR)) + p += 2; + + ustrzcpy(buf+pos, sizeof(buf)-pos, p); + pos = ustrsize(buf); + } + + #if defined (ALLEGRO_UNIX) || defined (ALLEGRO_MACOSX) + no_relativisation: + #endif + + /* add our filename, and clean it up a bit */ + ustrzcpy(buf+pos, sizeof(buf)-pos, filename); + + fix_filename_case(buf); + fix_filename_slashes(buf); + + /* remove duplicate slashes */ + pos = usetc(buf2, OTHER_PATH_SEPARATOR); + pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); + usetc(buf2+pos, 0); + + while ((p = ustrstr(buf, buf2)) != NULL) + uremove(p, 0); + + /* remove /./ patterns */ + pos = usetc(buf2, OTHER_PATH_SEPARATOR); + pos += usetc(buf2+pos, '.'); + pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); + usetc(buf2+pos, 0); + + while ((p = ustrstr(buf, buf2)) != NULL) { + uremove(p, 0); + uremove(p, 0); + } + + /* collapse /../ patterns */ + pos = usetc(buf2, OTHER_PATH_SEPARATOR); + pos += usetc(buf2+pos, '.'); + pos += usetc(buf2+pos, '.'); + pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); + usetc(buf2+pos, 0); + + while ((p = ustrstr(buf, buf2)) != NULL) { + for (i=0; buf+uoffset(buf, i) < p; i++) + ; + + while (--i > 0) { + c1 = ugetat(buf, i); + + if (c1 == OTHER_PATH_SEPARATOR) + break; + + if (c1 == DEVICE_SEPARATOR) { + i++; + break; + } + } + + if (i < 0) + i = 0; + + p += ustrsize(buf2); + memmove(buf+uoffset(buf, i+1), p, ustrsizez(p)); + } + + /* all done! */ + ustrzcpy(dest, size, buf); + + errno = saved_errno; + + return dest; +} + + + +/* make_relative_filename: + * Makes the relative filename corresponding to the specified absolute + * filename using the specified base (PATH is absolute and represents + * the base, FILENAME is the absolute filename), stores it in DEST + * whose size in bytes is SIZE and returns a pointer to it, or returns + * NULL if it cannot do so. + * It does not append '/' to the path. + */ +char *make_relative_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) +{ + char *my_path, *my_filename; + char *reduced_path = NULL, *reduced_filename = NULL; + char *p1, *p2; + int c, c1, c2, pos; + ASSERT(dest); + ASSERT(path); + ASSERT(filename); + ASSERT(size >= 0); + + /* The first check under DOS/Windows would be for the drive: since the + * paths are absolute, they will always contain a drive letter. Do this + * check under Unix too where the first character should always be '/' + * in order not to screw up existing DOS/Windows paths. + */ + if (ugetc(path) != ugetc(filename)) + return NULL; + + my_path = _al_ustrdup(path); + if (!my_path) + return NULL; + + my_filename = _al_ustrdup(filename); + if (!my_filename) { + _AL_FREE(my_path); + return NULL; + } + + /* Strip the filenames to keep only the directories. */ + usetc(get_filename(my_path), 0); + usetc(get_filename(my_filename), 0); + + /* Both paths are on the same device. There are three cases: + * - the filename is a "child" of the path in the directory tree, + * - the filename is a "brother" of the path, + * - the filename is only a "cousin" of the path. + * In the two former cases, we will only need to keep a suffix of the + * filename. In the latter case, we will need to back-paddle through + * the directory tree. + */ + p1 = my_path; + p2 = my_filename; + while (((c1=ugetx(&p1)) == (c2=ugetx(&p2))) && c1 && c2) { + if ((c1 == '/') || (c1 == OTHER_PATH_SEPARATOR)) { + reduced_path = p1; + reduced_filename = p2; + } + } + + if (!c1) { + /* If the path is exhausted, we are in one of the two former cases. */ + + if (!c2) { + /* If the filename is also exhausted, we are in the second case. + * Prepend './' to the reduced filename. + */ + pos = usetc(dest, '.'); + pos += usetc(dest+pos, OTHER_PATH_SEPARATOR); + usetc(dest+pos, 0); + } + else { + /* Otherwise we are in the first case. Nothing to do. */ + usetc(dest, 0); + } + } + else { + /* Bail out if previously something went wrong (eg. user supplied + * paths are not canonical and we can't understand them). */ + if (!reduced_path) { + _AL_FREE(my_path); + _AL_FREE(my_filename); + return NULL; + } + /* Otherwise, we are in the latter case and need to count the number + * of remaining directories in the reduced path and prepend the same + * number of '../' to the reduced filename. + */ + pos = 0; + while ((c=ugetx(&reduced_path))) { + if ((c == '/') || (c == OTHER_PATH_SEPARATOR)) { + pos += usetc(dest+pos, '.'); + pos += usetc(dest+pos, '.'); + pos += usetc(dest+pos, OTHER_PATH_SEPARATOR); + } + } + + usetc(dest+pos, 0); + } + + /* Bail out if previously something went wrong (eg. user supplied + * paths are not canonical and we can't understand them). */ + if (!reduced_filename) { + _AL_FREE(my_path); + _AL_FREE(my_filename); + return NULL; + } + + ustrzcat(dest, size, reduced_filename); + ustrzcat(dest, size, get_filename(filename)); + + _AL_FREE(my_path); + _AL_FREE(my_filename); + + /* Harmonize path separators. */ + return fix_filename_slashes(dest); +} + + + +/* is_relative_filename: + * Checks whether the specified filename is relative. + */ +int is_relative_filename(AL_CONST char *filename) +{ + ASSERT(filename); + + /* All filenames that start with a '.' are relative. */ + if (ugetc(filename) == '.') + return TRUE; + + /* Filenames that contain a device separator (DOS/Windows) + * or start with a '/' (Unix) are considered absolute. + */ +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) + if (ustrchr(filename, DEVICE_SEPARATOR)) + return FALSE; +#endif + + if ((ugetc(filename) == '/') || (ugetc(filename) == OTHER_PATH_SEPARATOR)) + return FALSE; + + return TRUE; +} + + + +/* append_filename: + * Append filename to path, adding separator if necessary. + */ +char *append_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) +{ + char tmp[1024]; + int pos, c; + ASSERT(dest); + ASSERT(path); + ASSERT(filename); + ASSERT(size >= 0); + + ustrzcpy(tmp, sizeof(tmp), path); + pos = ustrlen(tmp); + + if ((pos > 0) && (uoffset(tmp, pos) < ((int)sizeof(tmp) - ucwidth(OTHER_PATH_SEPARATOR) - ucwidth(0)))) { + c = ugetat(tmp, pos-1); + + if ((c != '/') && (c != OTHER_PATH_SEPARATOR) && (c != DEVICE_SEPARATOR)) { + pos = uoffset(tmp, pos); + pos += usetc(tmp+pos, OTHER_PATH_SEPARATOR); + usetc(tmp+pos, 0); + } + } + + ustrzcat(tmp, sizeof(tmp), filename); + + ustrzcpy(dest, size, tmp); + + return dest; +} + + + +/* get_filename: + * When passed a completely specified file path, this returns a pointer + * to the filename portion. Both '\' and '/' are recognized as directory + * separators. + */ +char *get_filename(AL_CONST char *path) +{ + int c; + const char *ptr, *ret; + ASSERT(path); + + ptr = path; + ret = ptr; + for (;;) { + c = ugetxc(&ptr); + if (!c) break; + if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) + ret = (char*)ptr; + } + return (char*)ret; +} + + + +/* get_extension: + * When passed a complete filename (with or without path information) + * this returns a pointer to the file extension. + */ +char *get_extension(AL_CONST char *filename) +{ + int pos, c; + ASSERT(filename); + + pos = ustrlen(filename); + + while (pos>0) { + c = ugetat(filename, pos-1); + if ((c == '.') || (c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) + break; + pos--; + } + + if ((pos>0) && (ugetat(filename, pos-1) == '.')) + return (char *)filename + uoffset(filename, pos); + + return (char *)filename + ustrsize(filename); +} + + + +/* put_backslash: + * If the last character of the filename is not a \, /, or #, or a device + * separator (eg. : under DOS), this routine will concatenate a \ or / on + * to it (depending on platform). + */ +void put_backslash(char *filename) +{ + int c; + ASSERT(filename); + + if (ugetc(filename)) { + c = ugetat(filename, -1); + + if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR) || (c == '#')) + return; + } + + filename += ustrsize(filename); + filename += usetc(filename, OTHER_PATH_SEPARATOR); + usetc(filename, 0); +} + + + +/*************************************************** + ******************* Filesystem ******************** + ***************************************************/ + + + +/* set_filename_encoding: + * Sets the encoding to use for filenames. By default, UTF8 is assumed. + */ +void set_filename_encoding(int encoding) +{ + filename_encoding = encoding; +} + + + +/* get_filename_encoding: + * Returns the encoding currently assumed for filenames. + */ +int get_filename_encoding(void) +{ + return filename_encoding ; +} + + + +/* file_exists: + * Checks whether a file matching the given name and attributes exists, + * returning non zero if it does. The file attribute may contain any of + * the FA_* constants from dir.h. If aret is not null, it will be set + * to the attributes of the matching file. If an error occurs the system + * error code will be stored in errno. + */ +int file_exists(AL_CONST char *filename, int attrib, int *aret) +{ + struct al_ffblk info; + ASSERT(filename); + + if (!_al_file_isok(filename)) + return FALSE; + + if (al_findfirst(filename, &info, attrib) != 0) { + /* no entry is not an error for file_exists() */ + if (*allegro_errno == ENOENT) + *allegro_errno = 0; + + return FALSE; + } + + al_findclose(&info); + + if (aret) + *aret = info.attrib; + + return TRUE; +} + + + +/* exists: + * Shortcut version of file_exists(). + */ +int exists(AL_CONST char *filename) +{ + ASSERT(filename); + return file_exists(filename, FA_ARCH | FA_RDONLY, NULL); +} + + + +/* file_size_ex: + * Returns the size of a file, in bytes. + * If the file does not exist or an error occurs, it will return zero + * and store the system error code in errno. + */ +uint64_t file_size_ex(AL_CONST char *filename) +{ + ASSERT(filename); + + if (!_al_file_isok(filename)) + return 0; + + return _al_file_size_ex(filename); +} + + + +/*************************************************** + ******************** Packfiles ******************** + ***************************************************/ + + +/* pack_fopen_datafile_object: + * Recursive helper to handle opening member objects from datafiles, + * given a fake filename in the form 'object_name[/nestedobject]'. + */ +static PACKFILE *pack_fopen_datafile_object(PACKFILE *f, AL_CONST char *objname) +{ + char buf[512]; /* text is read into buf as UTF-8 */ + char tmp[512*4]; /* this should be enough even when expanding to UCS-4 */ + char name[512]; + int use_next = FALSE; + int recurse = FALSE; + int type, size, pos, c; + + /* split up the object name */ + pos = 0; + + while ((c = ugetxc(&objname)) != 0) { + if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR)) { + recurse = TRUE; + break; + } + pos += usetc(name+pos, c); + } + + usetc(name+pos, 0); + + pack_mgetl(f); + + /* search for the requested object */ + while (!pack_feof(f)) { + type = pack_mgetl(f); + + if (type == DAT_PROPERTY) { + type = pack_mgetl(f); + size = pack_mgetl(f); + if (type == DAT_NAME) { + /* examine name property */ + pack_fread(buf, size, f); + buf[size] = 0; + if (ustricmp(uconvert(buf, U_UTF8, tmp, U_CURRENT, sizeof tmp), name) == 0) + use_next = TRUE; + } + else { + /* skip property */ + pack_fseek(f, size); + } + } + else { + if (use_next) { + /* found it! */ + if (recurse) { + if (type == DAT_FILE) + return pack_fopen_datafile_object(pack_fopen_chunk(f, FALSE), objname); + else + break; + } + else { + _packfile_type = type; + return pack_fopen_chunk(f, FALSE); + } + } + else { + /* skip unwanted object */ + size = pack_mgetl(f); + pack_fseek(f, size+4); + } + } + } + + /* oh dear, the object isn't there... */ + pack_fclose(f); + *allegro_errno = ENOENT; + return NULL; +} + + + +/* clone_password: + * Sets up a local password string for use by this packfile. + */ +static int clone_password(PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->is_normal_packfile); + + if (the_password[0]) { + if ((f->normal.passdata = _AL_MALLOC_ATOMIC(strlen(the_password)+1)) == NULL) { + *allegro_errno = ENOMEM; + return FALSE; + } + _al_sane_strncpy(f->normal.passdata, the_password, strlen(the_password)+1); + f->normal.passpos = f->normal.passdata; + } + else { + f->normal.passpos = NULL; + f->normal.passdata = NULL; + } + + return TRUE; +} + + + +/* create_packfile: + * Helper function for creating a PACKFILE structure. + */ +static PACKFILE *create_packfile(int is_normal_packfile) +{ + PACKFILE *f; + + if (is_normal_packfile) + f = _AL_MALLOC(sizeof(PACKFILE)); + else + f = _AL_MALLOC(sizeof(PACKFILE) - sizeof(struct _al_normal_packfile_details)); + + if (f == NULL) { + *allegro_errno = ENOMEM; + return NULL; + } + + if (!is_normal_packfile) { + f->vtable = NULL; + f->userdata = NULL; + f->is_normal_packfile = FALSE; + } + else { + f->vtable = &normal_vtable; + f->userdata = f; + f->is_normal_packfile = TRUE; + + f->normal.buf_pos = f->normal.buf; + f->normal.flags = 0; + f->normal.buf_size = 0; + f->normal.filename = NULL; + f->normal.passdata = NULL; + f->normal.passpos = NULL; + f->normal.parent = NULL; + f->normal.pack_data = NULL; + f->normal.unpack_data = NULL; + f->normal.todo = 0; + } + + return f; +} + + + +/* free_packfile: + * Helper function for freeing the PACKFILE struct. + */ +static void free_packfile(PACKFILE *f) +{ + if (f) { + /* These are no longer the responsibility of this function, but + * these assertions help catch instances of old code which still + * rely on the old behaviour. + */ + if (f->is_normal_packfile) { + ASSERT(!f->normal.pack_data); + ASSERT(!f->normal.unpack_data); + ASSERT(!f->normal.passdata); + ASSERT(!f->normal.passpos); + } + + _AL_FREE(f); + } +} + + + +/* _pack_fdopen: + * Converts the given file descriptor into a PACKFILE. The mode can have + * the same values as for pack_fopen() and must be compatible with the + * mode of the file descriptor. Unlike the libc fdopen(), pack_fdopen() + * is unable to convert an already partially read or written file (i.e. + * the file offset must be 0). + * On success, it returns a pointer to a file structure, and on error it + * returns NULL and stores an error code in errno. An attempt to read + * a normal file in packed mode will cause errno to be set to EDOM. + */ +PACKFILE *_pack_fdopen(int fd, AL_CONST char *mode) +{ + PACKFILE *f, *f2; + int c; + + if ((f = create_packfile(TRUE)) == NULL) + return NULL; + + ASSERT(f->is_normal_packfile); + + while ((c = *(mode++)) != 0) { + switch (c) { + case 'r': case 'R': f->normal.flags &= ~PACKFILE_FLAG_WRITE; break; + } + } + + { + { + /* read a 'real' file */ + f->normal.todo = lseek(fd, 0, SEEK_END); /* size of the file */ + if (f->normal.todo < 0) { + *allegro_errno = errno; + free_packfile(f); + return NULL; + } + + lseek(fd, 0, SEEK_SET); + + if (!clone_password(f)) { + free_packfile(f); + return NULL; + } + + f->normal.hndl = fd; + } + } + + return f; +} + + + +/* pack_fopen: + * Opens a file according to mode, which may contain any of the flags: + * 'r': open file for reading. + * 'w': open file for writing, overwriting any existing data. + * 'p': open file in 'packed' mode. Data will be compressed as it is + * written to the file, and automatically uncompressed during read + * operations. Files created in this mode will produce garbage if + * they are read without this flag being set. + * '!': open file for writing in normal, unpacked mode, but add the value + * F_NOPACK_MAGIC to the start of the file, so that it can be opened + * in packed mode and Allegro will automatically detect that the + * data does not need to be decompressed. + * + * Instead of these flags, one of the constants F_READ, F_WRITE, + * F_READ_PACKED, F_WRITE_PACKED or F_WRITE_NOPACK may be used as the second + * argument to fopen(). + * + * On success, fopen() returns a pointer to a file structure, and on error + * it returns NULL and stores an error code in errno. An attempt to read a + * normal file in packed mode will cause errno to be set to EDOM. + */ +PACKFILE *pack_fopen(AL_CONST char *filename, AL_CONST char *mode) +{ + char tmp[1024]; + int fd; + ASSERT(filename); + + _packfile_type = 0; + + if (!_al_file_isok(filename)) + return NULL; + + if (strpbrk(mode, "wW")) /* write mode? */ + fd = _al_open(uconvert_tofilename(filename, tmp), O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, OPEN_PERMS); + else + fd = _al_open(uconvert_tofilename(filename, tmp), O_RDONLY | O_BINARY, OPEN_PERMS); + + if (fd < 0) { + *allegro_errno = errno; + return NULL; + } + + return _pack_fdopen(fd, mode); +} + + + +/* pack_fopen_vtable: + * Creates a new packfile structure that uses the functions specified in + * the vtable instead of the standard functions. On success, it returns a + * pointer to a file structure, and on error it returns NULL and + * stores an error code in errno. + * + * The vtable and userdata must remain available for the lifetime of the + * created packfile. + * + * Opening chunks using pack_fopen_chunk() on top of the returned packfile + * is not possible at this time. + * + * packfile_password() does not have any effect on packfiles opened + * with pack_fopen_vtable(). + */ +PACKFILE *pack_fopen_vtable(AL_CONST PACKFILE_VTABLE *vtable, void *userdata) +{ + PACKFILE *f; + ASSERT(vtable); + ASSERT(vtable->pf_fclose); + ASSERT(vtable->pf_getc); + ASSERT(vtable->pf_ungetc); + ASSERT(vtable->pf_fread); + ASSERT(vtable->pf_putc); + ASSERT(vtable->pf_fwrite); + ASSERT(vtable->pf_fseek); + ASSERT(vtable->pf_feof); + ASSERT(vtable->pf_ferror); + + if ((f = create_packfile(FALSE)) == NULL) + return NULL; + + f->vtable = vtable; + f->userdata = userdata; + ASSERT(!f->is_normal_packfile); + + return f; +} + + + +/* pack_fclose: + * Closes a file after it has been read or written. + * Returns zero on success. On error it returns an error code which is + * also stored in errno. This function can fail only when writing to + * files: if the file was opened in read mode it will always succeed. + */ +int pack_fclose(PACKFILE *f) +{ + int ret; + + if (!f) + return 0; + + ASSERT(f->vtable); + ASSERT(f->vtable->pf_fclose); + + ret = f->vtable->pf_fclose(f->userdata); + if (ret != 0) + *allegro_errno = errno; + + free_packfile(f); + + return ret; +} + + + +/* pack_fopen_chunk: + * Opens a sub-chunk of the specified file, for reading or writing depending + * on the type of the file. The returned file pointer describes the sub + * chunk, and replaces the original file, which will no longer be valid. + * When writing to a chunk file, data is sent to the original file, but + * is prefixed with two length counts (32 bit, big-endian). For uncompressed + * chunks these will both be set to the length of the data in the chunk. + * For compressed chunks, created by setting the pack flag, the first will + * contain the raw size of the chunk, and the second will be the negative + * size of the uncompressed data. When reading chunks, the pack flag is + * ignored, and the compression type is detected from the sign of the + * second size value. The file structure used to read chunks checks the + * chunk size, and will return EOF if you try to read past the end of + * the chunk. If you don't read all of the chunk data, when you call + * pack_fclose_chunk(), the parent file will advance past the unused data. + * When you have finished reading or writing a chunk, you should call + * pack_fclose_chunk() to return to your original file. + */ +PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack) +{ + PACKFILE *chunk; + char tmp[1024]; + char *name; + ASSERT(f); + + /* unsupported */ + if (!f->is_normal_packfile) { + *allegro_errno = EINVAL; + return NULL; + } + + { + /* read a sub-chunk */ + _packfile_filesize = pack_mgetl(f); + _packfile_datasize = pack_mgetl(f); + + if ((chunk = create_packfile(TRUE)) == NULL) + return NULL; + + chunk->normal.flags = PACKFILE_FLAG_CHUNK; + chunk->normal.parent = f; + + if (f->normal.flags & PACKFILE_FLAG_OLD_CRYPT) { + /* backward compatibility mode */ + if (f->normal.passdata) { + if ((chunk->normal.passdata = _AL_MALLOC_ATOMIC(strlen(f->normal.passdata)+1)) == NULL) { + *allegro_errno = ENOMEM; + _AL_FREE(chunk); + return NULL; + } + _al_sane_strncpy(chunk->normal.passdata, f->normal.passdata, strlen(f->normal.passdata)+1); + chunk->normal.passpos = chunk->normal.passdata + (long)f->normal.passpos - (long)f->normal.passdata; + f->normal.passpos = f->normal.passdata; + } + chunk->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; + } + + ASSERT(_packfile_datasize >= 0); + { + /* read an uncompressed chunk */ + chunk->normal.todo = _packfile_datasize; + } + } + + return chunk; +} + + + +/* pack_fseek: + * Like the stdio fseek() function, but only supports forward seeks + * relative to the current file position. + */ +int pack_fseek(PACKFILE *f, int offset) +{ + ASSERT(f); + ASSERT(offset >= 0); + + return f->vtable->pf_fseek(f->userdata, offset); +} + + + +/* pack_getc: + * Returns the next character from the stream f, or EOF if the end of the + * file has been reached. + */ +int pack_getc(PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_getc); + + return f->vtable->pf_getc(f->userdata); +} + + + +/* pack_putc: + * Puts a character in the stream f. + */ +int pack_putc(int c, PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_putc); + + return f->vtable->pf_putc(c, f->userdata); +} + + + +/* pack_feof: + * pack_feof() returns nonzero as soon as you reach the end of the file. It + * does not wait for you to attempt to read beyond the end of the file, + * contrary to the ISO C feof() function. + */ +int pack_feof(PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_feof); + + return f->vtable->pf_feof(f->userdata); +} + + + +/* pack_igetw: + * Reads a 16 bit word from a file, using intel byte ordering. + */ +int pack_igetw(PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + return ((b2 << 8) | b1); + + return EOF; +} + + + +/* pack_igetl: + * Reads a 32 bit long from a file, using intel byte ordering. + */ +long pack_igetl(PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + if ((b3 = pack_getc(f)) != EOF) + if ((b4 = pack_getc(f)) != EOF) + return (((long)b4 << 24) | ((long)b3 << 16) | + ((long)b2 << 8) | (long)b1); + + return EOF; +} + + + +/* pack_iputw: + * Writes a 16 bit int to a file, using intel byte ordering. + */ +int pack_iputw(int w, PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + b1 = (w & 0xFF00) >> 8; + b2 = w & 0x00FF; + + if (pack_putc(b2,f)==b2) + if (pack_putc(b1,f)==b1) + return w; + + return EOF; +} + + + +/* pack_iputl: + * Writes a 32 bit long to a file, using intel byte ordering. + */ +long pack_iputl(long l, PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + b1 = (int)((l & 0xFF000000L) >> 24); + b2 = (int)((l & 0x00FF0000L) >> 16); + b3 = (int)((l & 0x0000FF00L) >> 8); + b4 = (int)l & 0x00FF; + + if (pack_putc(b4,f)==b4) + if (pack_putc(b3,f)==b3) + if (pack_putc(b2,f)==b2) + if (pack_putc(b1,f)==b1) + return l; + + return EOF; +} + + + +/* pack_mgetw: + * Reads a 16 bit int from a file, using motorola byte-ordering. + */ +int pack_mgetw(PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + return ((b1 << 8) | b2); + + return EOF; +} + + + +/* pack_mgetl: + * Reads a 32 bit long from a file, using motorola byte-ordering. + */ +long pack_mgetl(PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + if ((b3 = pack_getc(f)) != EOF) + if ((b4 = pack_getc(f)) != EOF) + return (((long)b1 << 24) | ((long)b2 << 16) | + ((long)b3 << 8) | (long)b4); + + return EOF; +} + + + +/* pack_fread: + * Reads n bytes from f and stores them at memory location p. Returns the + * number of items read, which will be less than n if EOF is reached or an + * error occurs. Error codes are stored in errno. + */ +long pack_fread(void *p, long n, PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_fread); + ASSERT(p); + ASSERT(n >= 0); + + return f->vtable->pf_fread(p, n, f->userdata); +} + + + +/* pack_fputs: + * Writes a string to a text file, returning zero on success, -1 on error. + * The input string is converted from the current text encoding format + * to UTF-8 before writing. Newline characters (\n) are written as \r\n + * on DOS and Windows platforms. + */ +int pack_fputs(AL_CONST char *p, PACKFILE *f) +{ + char *buf, *s; + int bufsize; + ASSERT(f); + ASSERT(p); + + *allegro_errno = 0; + + bufsize = uconvert_size(p, U_CURRENT, U_UTF8); + buf = _AL_MALLOC_ATOMIC(bufsize); + if (!buf) + return -1; + + s = uconvert(p, U_CURRENT, buf, U_UTF8, bufsize); + + while (*s) { + #if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) + if (*s == '\n') + pack_putc('\r', f); + #endif + + pack_putc(*s, f); + s++; + } + + _AL_FREE(buf); + + if (*allegro_errno) + return -1; + else + return 0; +} + + + +/*************************************************** + ************ "Normal" packfile vtable ************* + *************************************************** + + Ideally this would be the only section which knows about the details + of "normal" packfiles. However, this ideal is still being violated in + many places (partly due to the API, and partly because it would be + quite a lot of work to move the _al_normal_packfile_details field + into the userdata field of the PACKFILE structure. +*/ + + +static int normal_fclose(void *_f); +static int normal_getc(void *_f); +static int normal_ungetc(int ch, void *_f); +static int normal_putc(int c, void *_f); +static long normal_fread(void *p, long n, void *_f); +static long normal_fwrite(AL_CONST void *p, long n, void *_f); +static int normal_fseek(void *_f, int offset); +static int normal_feof(void *_f); +static int normal_ferror(void *_f); + +static int normal_refill_buffer(PACKFILE *f); +static int normal_flush_buffer(PACKFILE *f, int last); + + + +static PACKFILE_VTABLE normal_vtable = +{ + normal_fclose, + normal_getc, + normal_ungetc, + normal_fread, + normal_putc, + normal_fwrite, + normal_fseek, + normal_feof, + normal_ferror +}; + + + +static int normal_fclose(void *_f) +{ + PACKFILE *f = _f; + int ret; + + if (f->normal.parent) { + ret = pack_fclose(f->normal.parent); + } + else { + ret = close(f->normal.hndl); + if (ret != 0) + *allegro_errno = errno; + } + + if (f->normal.passdata) { + _AL_FREE(f->normal.passdata); + f->normal.passdata = NULL; + f->normal.passpos = NULL; + } + + return ret; +} + + + +/* normal_no_more_input: + * Return non-zero if the number of bytes remaining in the file (todo) is + * less than or equal to zero. + * + * However, there is a special case. If we are reading from a LZSS + * compressed file, the latest call to lzss_read() may have suspended while + * writing out a sequence of bytes due to the output buffer being too small. + * In that case the `todo' count would be decremented (possibly to zero), + * but the output isn't yet completely written out. + */ +static INLINE int normal_no_more_input(PACKFILE *f) +{ + return (f->normal.todo <= 0); +} + + + +static int normal_getc(void *_f) +{ + PACKFILE *f = _f; + + f->normal.buf_size--; + if (f->normal.buf_size > 0) + return *(f->normal.buf_pos++); + + if (f->normal.buf_size == 0) { + if (normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + return *(f->normal.buf_pos++); + } + + return normal_refill_buffer(f); +} + + + +static int normal_ungetc(int c, void *_f) +{ + PACKFILE *f = _f; + + if (f->normal.buf_pos == f->normal.buf) { + return EOF; + } + else { + *(--f->normal.buf_pos) = (unsigned char)c; + f->normal.buf_size++; + f->normal.flags &= ~PACKFILE_FLAG_EOF; + return (unsigned char)c; + } +} + + + +static long normal_fread(void *p, long n, void *_f) +{ + PACKFILE *f = _f; + unsigned char *cp = (unsigned char *)p; + long i; + int c; + + for (i=0; inormal.buf_size + 1 >= F_BUF_SIZE) { + if (normal_flush_buffer(f, FALSE)) + return EOF; + } + + f->normal.buf_size++; + return (*(f->normal.buf_pos++) = c); +} + + + +static long normal_fwrite(AL_CONST void *p, long n, void *_f) +{ + PACKFILE *f = _f; + AL_CONST unsigned char *cp = (AL_CONST unsigned char *)p; + long i; + + for (i=0; inormal.buf_size > 0) { + i = MIN(offset, f->normal.buf_size); + f->normal.buf_size -= i; + f->normal.buf_pos += i; + offset -= i; + if ((f->normal.buf_size <= 0) && normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + } + + /* need to seek some more? */ + if (offset > 0) { + i = MIN(offset, f->normal.todo); + + if ((f->normal.passpos)) { + /* for compressed or encrypted files, we just have to read through the data */ + while (i > 0) { + pack_getc(f); + i--; + } + } + else { + if (f->normal.parent) { + /* pass the seek request on to the parent file */ + pack_fseek(f->normal.parent, i); + } + else { + /* do a real seek */ + lseek(f->normal.hndl, i, SEEK_CUR); + } + f->normal.todo -= i; + if (normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + } + } + + if (*allegro_errno) + return -1; + else + return 0; +} + + + +static int normal_feof(void *_f) +{ + PACKFILE *f = _f; + + return (f->normal.flags & PACKFILE_FLAG_EOF); +} + + + +static int normal_ferror(void *_f) +{ + PACKFILE *f = _f; + + return (f->normal.flags & PACKFILE_FLAG_ERROR); +} + + + +/* normal_refill_buffer: + * Refills the read buffer. The file must have been opened in read mode, + * and the buffer must be empty. + */ +static int normal_refill_buffer(PACKFILE *f) +{ + int i, sz, done, offset; + + if (f->normal.flags & PACKFILE_FLAG_EOF) + return EOF; + + if (normal_no_more_input(f)) { + f->normal.flags |= PACKFILE_FLAG_EOF; + return EOF; + } + + if (f->normal.parent) { + { + f->normal.buf_size = pack_fread(f->normal.buf, MIN(F_BUF_SIZE, f->normal.todo), f->normal.parent); + } + if (f->normal.parent->normal.flags & PACKFILE_FLAG_EOF) + f->normal.todo = 0; + if (f->normal.parent->normal.flags & PACKFILE_FLAG_ERROR) + goto Error; + } + else { + f->normal.buf_size = MIN(F_BUF_SIZE, f->normal.todo); + + offset = lseek(f->normal.hndl, 0, SEEK_CUR); + done = 0; + + errno = 0; + sz = read(f->normal.hndl, f->normal.buf, f->normal.buf_size); + + while (sz+done < f->normal.buf_size) { + if ((sz < 0) && ((errno != EINTR) && (errno != EAGAIN))) + goto Error; + + if (sz > 0) + done += sz; + + lseek(f->normal.hndl, offset+done, SEEK_SET); + errno = 0; + sz = read(f->normal.hndl, f->normal.buf+done, f->normal.buf_size-done); + } + + if ((f->normal.passpos) && (!(f->normal.flags & PACKFILE_FLAG_OLD_CRYPT))) { + for (i=0; inormal.buf_size; i++) { + f->normal.buf[i] ^= *(f->normal.passpos++); + if (!*f->normal.passpos) + f->normal.passpos = f->normal.passdata; + } + } + } + + f->normal.todo -= f->normal.buf_size; + f->normal.buf_pos = f->normal.buf; + f->normal.buf_size--; + if (f->normal.buf_size <= 0) + if (normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + + if (f->normal.buf_size < 0) + return EOF; + else + return *(f->normal.buf_pos++); + + Error: + *allegro_errno = EFAULT; + f->normal.flags |= PACKFILE_FLAG_ERROR; + return EOF; +} + + + +/* normal_flush_buffer: + * Flushes a file buffer to the disk. The file must be open in write mode. + */ +static int normal_flush_buffer(PACKFILE *f, int last) +{ + int i, sz, done, offset; + + if (f->normal.buf_size > 0) { + { + if ((f->normal.passpos) && (!(f->normal.flags & PACKFILE_FLAG_OLD_CRYPT))) { + for (i=0; inormal.buf_size; i++) { + f->normal.buf[i] ^= *(f->normal.passpos++); + if (!*f->normal.passpos) + f->normal.passpos = f->normal.passdata; + } + } + + offset = lseek(f->normal.hndl, 0, SEEK_CUR); + done = 0; + + errno = 0; + sz = write(f->normal.hndl, f->normal.buf, f->normal.buf_size); + + while (sz+done < f->normal.buf_size) { + if ((sz < 0) && ((errno != EINTR) && (errno != EAGAIN))) + goto Error; + + if (sz > 0) + done += sz; + + lseek(f->normal.hndl, offset+done, SEEK_SET); + errno = 0; + sz = write(f->normal.hndl, f->normal.buf+done, f->normal.buf_size-done); + } + } + f->normal.todo += f->normal.buf_size; + } + + f->normal.buf_pos = f->normal.buf; + f->normal.buf_size = 0; + return 0; + + Error: + *allegro_errno = EFAULT; + f->normal.flags |= PACKFILE_FLAG_ERROR; + return EOF; +} diff --git a/libsrc/allegro/src/fli.c b/libsrc/allegro/src/fli.c new file mode 100644 index 00000000000..8b5876aa0ae --- /dev/null +++ b/libsrc/allegro/src/fli.c @@ -0,0 +1,1053 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * FLI/FLC player. + * + * By Shawn Hargreaves, based on code provided by Jonathan Tarbox. + * + * Major portability and reliability improvements by Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + +#define FLI_MAGIC1 0xAF11 /* file header magic number */ +#define FLI_MAGIC2 0xAF12 /* file magic number (Pro) */ +#define FLI_FRAME_MAGIC 0xF1FA /* frame header magic number */ +#define FLI_FRAME_PREFIX 0xF100 /* FLC's prefix info */ +#define FLI_FRAME_USELESS 0x00A1 /* FLC's garbage frame */ + + + +typedef struct FLI_HEADER +{ + long size; + unsigned short type; + unsigned short frame_count; + unsigned short width; + unsigned short height; + unsigned short bits_a_pixel; + unsigned short flags; + unsigned short speed; + long next_head; + long frames_in_table; + char reserved[102]; +} FLI_HEADER; + +#define sizeof_FLI_HEADER (4+2+2+2+2+2+2+2+4+4+102) + + + +typedef struct FLI_FRAME +{ + unsigned long size; + unsigned short type; + unsigned short chunks; + char pad[8]; +} FLI_FRAME; + +#define sizeof_FLI_FRAME (4+2+2+8) + + + +typedef struct FLI_CHUNK +{ + unsigned long size; + unsigned short type; +} FLI_CHUNK; + +#define sizeof_FLI_CHUNK (4+2) + + + +static int fli_status = FLI_NOT_OPEN; /* current state of the FLI player */ + +BITMAP *fli_bitmap = NULL; /* current frame of the FLI */ +PALETTE fli_palette; /* current palette the FLI is using */ + +int fli_bmp_dirty_from = INT_MAX; /* what part of fli_bitmap is dirty */ +int fli_bmp_dirty_to = INT_MIN; +int fli_pal_dirty_from = INT_MAX; /* what part of fli_palette is dirty */ +int fli_pal_dirty_to = INT_MIN; + +int fli_frame = 0; /* current frame number in the FLI */ + +volatile int fli_timer = 0; /* for timing FLI playback */ + +static PACKFILE *fli_file = NULL; /* the file we are reading */ +static char *fli_filename = NULL; /* name of the file */ + +static void *fli_mem_data = NULL; /* the memory FLI we are playing */ +static int fli_mem_pos = 0; /* position in the memory FLI */ + +static FLI_HEADER fli_header; /* header structure */ +static FLI_FRAME frame_header; /* frame header structure */ + +static unsigned char _fli_broken_data[3 * 256]; /* data substituted for broken chunks */ + + + +/* fli_timer_callback: + * Timer interrupt handler for syncing FLI files. + */ +static void fli_timer_callback(void) +{ + fli_timer++; +} + +END_OF_STATIC_FUNCTION(fli_timer_callback); + + + +/* fli_read: + * Helper function to get a block of data from the FLI, which can read + * from disk or a copy of the FLI held in memory. If buf is set, that is + * where it stores the data, otherwise it uses the scratch buffer. Returns + * a pointer to the data, or NULL on error. + */ +static void *fli_read(void *buf, int size) +{ + int result; + + if (fli_mem_data) { + if (buf) + memcpy(buf, (char *)fli_mem_data+fli_mem_pos, size); + else + buf = (char *)fli_mem_data+fli_mem_pos; + + fli_mem_pos += size; + } + else { + if (!buf) { + _grow_scratch_mem(size); + buf = _scratch_mem; + } + + result = pack_fread(buf, size, fli_file); + if (result != size) + return NULL; + } + + return buf; +} + + + +/* fli_rewind: + * Helper function to rewind to the beginning of the FLI file data. + * Pass offset from the beginning of the data in bytes. + */ +static void fli_rewind(int offset) +{ + if (fli_mem_data) { + fli_mem_pos = offset; + } + else { + pack_fclose(fli_file); + fli_file = pack_fopen(fli_filename, F_READ); + if (fli_file) + pack_fseek(fli_file, offset); + else + fli_status = FLI_ERROR; + } +} + + + +/* fli_skip: + * Helper function to skip some bytes of the FLI file data. + * Pass number of bytes to skip. + */ +static void fli_skip(int bytes) +{ + if (fli_mem_data) { + fli_mem_pos += bytes; + } + else { + pack_fseek(fli_file, bytes); + } +} + + + +/* helpers for reading FLI chunk data */ +#if 0 +/* the "cast expression as lvalue" extension is deprecated in GCC 3.4 */ +#define READ_BYTE_NC(p) (*((unsigned char *)(p))++) +#define READ_CHAR_NC(p) (*((signed char *)(p))++) +#else +#define READ_BYTE_NC(p) (*(unsigned char *)(p)++) +#define READ_CHAR_NC(p) (*(signed char *)(p)++) +#endif + +#if (defined ALLEGRO_GCC) && (defined ALLEGRO_LITTLE_ENDIAN) && (!defined ALLEGRO_ARM) && (!defined ALLEGRO_PSP) + +#if 0 +/* the "cast expression as lvalue" extension is deprecated in GCC 3.4 */ +#define READ_WORD_NC(p) (*((uint16_t *)(p))++) +#define READ_SHORT_NC(p) (*((int16_t *)(p))++) +#define READ_ULONG_NC(p) (*((uint32_t *)(p))++) +#define READ_LONG_NC(p) (*((int32_t *)(p))++) +#else +/* we use the "statement-expression" extension instead */ +#define READ_WORD_NC(p) ({ uint16_t *__p = (uint16_t *)(p); p+=2; *__p; }) +#define READ_SHORT_NC(p) ({ int16_t *__p = (int16_t *)(p); p+=2; *__p; }) +#define READ_ULONG_NC(p) ({ uint32_t *__p = (uint32_t *)(p); p+=4; *__p; }) +#define READ_LONG_NC(p) ({ int32_t *__p = (int32_t *)(p); p+=4; *__p; }) +#endif + +#else + +static unsigned short _fli_read_word_nc(unsigned char **p) +{ + unsigned short t; + t = (((unsigned short) *((unsigned char*) (*p))) + | ((unsigned short) *((unsigned char*) (*p) + 1) << 8)); + *p += 2; + return t; +} + +static signed short _fli_read_short_nc(unsigned char **p) +{ + unsigned short t = _fli_read_word_nc(p); + if (t & (unsigned short) 0x8000) + return -(signed short) (~(t - 1) & (unsigned short) 0x7FFF); + else + return (signed short) t; +} + +static unsigned long _fli_read_ulong_nc(unsigned char **p) +{ + unsigned long t; + t = (((unsigned long) *((unsigned char*) (*p))) + | ((unsigned long) *((unsigned char*) (*p) + 1) << 8) + | ((unsigned long) *((unsigned char*) (*p) + 2) << 16) + | ((unsigned long) *((unsigned char*) (*p) + 3) << 24)); + *p += 4; + return t; +} + +static signed long _fli_read_long_nc(unsigned char **p) +{ + unsigned long t = _fli_read_ulong_nc(p); + if (t & (unsigned long) 0x80000000L) + return -(signed long) (~(t - 1) & (unsigned long) 0x7FFFFFFFL); + else + return (signed long) t; +} + +#define READ_WORD_NC(p) _fli_read_word_nc(&(p)) +#define READ_SHORT_NC(p) _fli_read_short_nc(&(p)) +#define READ_ULONG_NC(p) _fli_read_ulong_nc(&(p)) +#define READ_LONG_NC(p) _fli_read_long_nc(&(p)) + +#endif + +#define READ_BLOCK_NC(p,pos,size) \ +{ \ + memcpy((pos), (p), (size)); \ + (p) += (size); \ +} + +#define READ_RLE_BYTE_NC(p,pos,size) \ + memset((pos), READ_BYTE_NC(p), (size)) + +#if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) + +#define READ_RLE_WORD_NC(p,pos,size) \ +{ \ + int c; \ + uint16_t *ptr = (uint16_t*) (pos); \ + unsigned short v = READ_WORD_NC(p); \ + \ + for (c = 0; c < (size); c++) \ + *ptr++ = v; \ +} + +#else + +#define READ_RLE_WORD_NC(p,pos,size) \ +{ \ + int c; \ + unsigned char *ptr = (pos); \ + unsigned char v1 = READ_BYTE_NC(p); \ + unsigned char v2 = READ_BYTE_NC(p); \ + \ + for (c = 0; c < (size); c++) { \ + *ptr++ = v1; \ + *ptr++ = v2; \ + } \ +} + +#endif + + + +/* support for broken chunks (copy reminder of chunk and add zeros) + * this needs not be fast because FLI data should not be broken. + * p is a pointer to reminder of chunk data + * sz is a size of chunk after subtructing size bytes (known to be < 0) + * size is how much bytes we need + * (size + sz) is how much bytes is left in chunk */ +#define FLI_KLUDGE(p,sz,size) \ +{ \ + if (((size) + (sz)) <= 0) { \ + memset(_fli_broken_data, 0, (size)); \ + } \ + else { \ + memcpy(_fli_broken_data, (p), (size) + (sz)); \ + memset(_fli_broken_data + (size) + (sz), 0, -(sz)); \ + } \ + (p) = _fli_broken_data; \ +} + + + +/* do_fli_256_color: + * Processes an FLI 256_COLOR chunk + */ +static void do_fli_256_color(unsigned char *p, int sz) +{ + int packets; + int end; + int offset; + int length; + + offset = 0; + if ((sz -= 2) < 0) + return; + packets = READ_SHORT_NC(p); + + while (packets-- > 0) { + if ((sz -= 2) < 0) + return; + offset += READ_BYTE_NC(p); + length = READ_BYTE_NC(p); + if (length == 0) + length = 256; + + end = offset + length; + if (end > PAL_SIZE) + return; + else if ((sz -= length * 3) < 0) { + FLI_KLUDGE(p, sz, length * 3); + } + + fli_pal_dirty_from = MIN(fli_pal_dirty_from, offset); + fli_pal_dirty_to = MAX(fli_pal_dirty_to, end-1); + + for(; offset < end; offset++) { + fli_palette[offset].r = READ_BYTE_NC(p) / 4; + fli_palette[offset].g = READ_BYTE_NC(p) / 4; + fli_palette[offset].b = READ_BYTE_NC(p) / 4; + } + } +} + + + +/* do_fli_delta: + * Processes an FLI DELTA chunk + */ +static void do_fli_delta(unsigned char *p, int sz) +{ + int lines; + int packets; + int size; + int y; + unsigned char *curr; + unsigned char *bitmap_end = fli_bitmap->line[fli_bitmap->h-1] + fli_bitmap->w; + + y = 0; + if ((sz -= 2) < 0) + return; + lines = READ_SHORT_NC(p); + + while (lines-- > 0) { /* for each line... */ + if ((sz -= 2) < 0) + return; + packets = READ_SHORT_NC(p); + + while (packets < 0) { + if (packets & 0x4000) + y -= packets; + else if (y < fli_bitmap->h) + fli_bitmap->line[y][fli_bitmap->w-1] = packets & 0xFF; + + if ((sz -= 2) < 0) + return; + packets = READ_SHORT_NC(p); + } + if (y >= fli_bitmap->h) + return; + + curr = fli_bitmap->line[y]; + + fli_bmp_dirty_from = MIN(fli_bmp_dirty_from, y); + fli_bmp_dirty_to = MAX(fli_bmp_dirty_to, y); + + while (packets-- > 0) { + if ((sz -= 2) < 0) + return; + curr += READ_BYTE_NC(p); /* skip bytes */ + size = READ_CHAR_NC(p); + + if (size > 0) { /* copy size words */ + if ((curr + size * 2) > bitmap_end) + return; + else if ((sz -= size * 2) < 0) { + FLI_KLUDGE(p, sz, size * 2); + } + READ_BLOCK_NC(p, curr, size*2); + curr += size*2; + } + else if (size < 0) { /* repeat word -size times */ + size = -size; + if ((curr + size * 2) > bitmap_end) + return; + else if ((sz -= 2) < 0) { + FLI_KLUDGE(p, sz, 2); + } + READ_RLE_WORD_NC(p, curr, size); + curr += size*2; + } + } + + y++; + } +} + + + +/* do_fli_color: + * Processes an FLI COLOR chunk + */ +static void do_fli_color(unsigned char *p, int sz) +{ + int packets; + int end; + int offset; + int length; + + offset = 0; + if ((sz -= 2) < 0) + return; + packets = READ_SHORT_NC(p); + + while (packets-- > 0) { + if ((sz -= 2) < 0) + return; + offset += READ_BYTE_NC(p); + length = READ_BYTE_NC(p); + if (length == 0) + length = 256; + + end = offset + length; + if (end > PAL_SIZE) + return; + else if ((sz -= length * 3) < 0) { + FLI_KLUDGE(p, sz, length * 3); + } + + fli_pal_dirty_from = MIN(fli_pal_dirty_from, offset); + fli_pal_dirty_to = MAX(fli_pal_dirty_to, end-1); + + for(; offset < end; offset++) { + fli_palette[offset].r = READ_BYTE_NC(p); + fli_palette[offset].g = READ_BYTE_NC(p); + fli_palette[offset].b = READ_BYTE_NC(p); + } + } +} + + + +/* do_fli_lc: + * Processes an FLI LC chunk + */ +static void do_fli_lc(unsigned char *p, int sz) +{ + int lines; + int packets; + int size; + int y; + unsigned char *curr; + unsigned char *bitmap_end = fli_bitmap->line[fli_bitmap->h-1] + fli_bitmap->w; + + if ((sz -= 4) < 0) + return; + y = READ_WORD_NC(p); + lines = READ_SHORT_NC(p); + + if (y >= fli_bitmap->h) + return; + else if ((y + lines) > fli_bitmap->h) + lines = fli_bitmap->h - y; + + fli_bmp_dirty_from = MIN(fli_bmp_dirty_from, y); + fli_bmp_dirty_to = MAX(fli_bmp_dirty_to, y+lines-1); + + while (lines-- > 0) { /* for each line... */ + if ((sz -= 1) < 0) + return; + packets = READ_BYTE_NC(p); + curr = fli_bitmap->line[y]; + + while (packets-- > 0) { + if ((sz -= 2) < 0) + return; + curr += READ_BYTE_NC(p); /* skip bytes */ + size = READ_CHAR_NC(p); + + if (size > 0) { /* copy size bytes */ + if ((curr + size) > bitmap_end) + return; + else if ((sz -= size) < 0) { + FLI_KLUDGE(p, sz, size); + } + READ_BLOCK_NC(p, curr, size); + curr += size; + } + else if (size < 0) { /* repeat byte -size times */ + size = -size; + if ((curr + size) > bitmap_end) + return; + else if ((sz -= 1) < 0) { + FLI_KLUDGE(p, sz, 1); + } + READ_RLE_BYTE_NC(p, curr, size); + curr += size; + } + } + + y++; + } +} + + + +/* do_fli_black: + * Processes an FLI BLACK chunk + */ +static void do_fli_black(void) +{ + clear_bitmap(fli_bitmap); + + fli_bmp_dirty_from = 0; + fli_bmp_dirty_to = fli_bitmap->h-1; +} + + + +/* do_fli_brun: + * Processes an FLI BRUN chunk + */ +static void do_fli_brun(unsigned char *p, int sz) +{ + int packets; + int size; + int y; + unsigned char *curr; + unsigned char *bitmap_end = fli_bitmap->line[fli_bitmap->h-1] + fli_bitmap->w; + + fli_bmp_dirty_from = 0; + fli_bmp_dirty_to = fli_bitmap->h-1; + + for (y=0; yh; y++) { /* for each line... */ + if ((sz -= 1) < 0) + return; + packets = READ_BYTE_NC(p); + curr = fli_bitmap->line[y]; + + if (packets == 0) { /* FLC chunk (fills the whole line) */ + unsigned char *line_end = curr + fli_bitmap->w; + + while (curr < line_end) { + if ((sz -= 1) < 0) + return; + size = READ_CHAR_NC(p); + + if (size < 0) { /* copy -size bytes */ + size = -size; + if ((curr + size) > bitmap_end) + return; + else if ((sz -= size) < 0) { + FLI_KLUDGE(p, sz, size); + } + READ_BLOCK_NC(p, curr, size); + curr += size; + } + else if (size > 0) { /* repeat byte size times */ + if ((curr + size) > bitmap_end) + return; + else if ((sz -= 1) < 0) { + FLI_KLUDGE(p, sz, 1); + } + READ_RLE_BYTE_NC(p, curr, size); + curr += size; + } + } + } + else { + /* FLI chunk (uses packets count) */ + while (packets-- > 0) { + if ((sz -= 1) < 0) + return; + size = READ_CHAR_NC(p); + + if (size < 0) { /* copy -size bytes */ + size = -size; + if ((curr + size) > bitmap_end) + return; + if ((sz -= size) < 0) { + FLI_KLUDGE(p, sz, size); + } + READ_BLOCK_NC(p, curr, size); + curr += size; + } + else if (size > 0) { /* repeat byte size times */ + if ((curr + size) > bitmap_end) + return; + if ((sz -= 1) < 0) { + FLI_KLUDGE(p, sz, 1); + } + READ_RLE_BYTE_NC(p, curr, size); + curr += size; + } + } + } + } +} + + + +/* do_fli_copy: + * Processes an FLI COPY chunk + */ +static void do_fli_copy(unsigned char *p, int sz) +{ + int y; + + if ((sz -= (fli_bitmap->w * fli_bitmap->h)) < 0) + return; + + for (y=0; yh; y++) + READ_BLOCK_NC(p, fli_bitmap->line[y], fli_bitmap->w); + + fli_bmp_dirty_from = 0; + fli_bmp_dirty_to = fli_bitmap->h-1; +} + + + +/* _fli_read_header: + * Reads FLI file header (0 -- OK). + */ +static int _fli_read_header(FLI_HEADER *header) +{ + unsigned char *p = fli_read(NULL, sizeof_FLI_HEADER); + + if (!p) + return -1; + + header->size = READ_LONG_NC(p); + header->type = READ_WORD_NC(p); + header->frame_count = READ_WORD_NC(p); + header->width = READ_WORD_NC(p); + header->height = READ_WORD_NC(p); + header->bits_a_pixel = READ_WORD_NC(p); + header->flags = READ_WORD_NC(p); + header->speed = READ_WORD_NC(p); + header->next_head = READ_LONG_NC(p); + header->frames_in_table = READ_LONG_NC(p); + + return ((header->size < sizeof_FLI_HEADER) ? -1 : 0); +} + + + +/* _fli_read_frame: + * Reads FLI frame header (0 -- OK). + */ +static int _fli_read_frame(FLI_FRAME *frame) +{ + unsigned char *p = fli_read(NULL, sizeof_FLI_FRAME); + + if (!p) + return -1; + + frame->size = READ_ULONG_NC(p); + frame->type = READ_WORD_NC(p); + frame->chunks = READ_WORD_NC(p); + + return ((frame->size < sizeof_FLI_FRAME) ? -1 : 0); +} + + + +/* _fli_parse_chunk: + * Parses one FLI chunk. + */ +static int _fli_parse_chunk(FLI_CHUNK *chunk, unsigned char *p, unsigned long frame_size) +{ + if (frame_size < sizeof_FLI_CHUNK) + return -1; + + chunk->size = READ_ULONG_NC(p); + chunk->type = READ_WORD_NC(p); + + return (((chunk->size < sizeof_FLI_CHUNK) || (chunk->size > frame_size)) ? -1 : 0); +} + + + +/* read_frame: + * Advances to the next frame in the FLI. + */ +static void read_frame(void) +{ + unsigned char *p; + FLI_CHUNK chunk; + int c, sz, frame_size; + + if (fli_status != FLI_OK) + return; + + /* clear the first frame (we need it for looping, because we don't support ring frame) */ + if (fli_frame == 0) { + clear_bitmap(fli_bitmap); + fli_bmp_dirty_from = 0; + fli_bmp_dirty_to = fli_bitmap->h-1; + } + + get_another_frame: + + /* read the frame header */ + if (_fli_read_frame(&frame_header) != 0) { + fli_status = FLI_ERROR; + return; + } + + /* skip FLC's useless frame */ + if ((frame_header.type == FLI_FRAME_PREFIX) || (frame_header.type == FLI_FRAME_USELESS)) { + fli_skip(frame_header.size-sizeof_FLI_FRAME); + + if (++fli_frame >= fli_header.frame_count) + return; + + goto get_another_frame; + } + + if (frame_header.type != FLI_FRAME_MAGIC) { + fli_status = FLI_ERROR; + return; + } + + /* bytes left in this frame */ + frame_size = frame_header.size - sizeof_FLI_FRAME; + + /* return if there is no data in the frame */ + if (frame_size == 0) { + fli_frame++; + return; + } + + /* read the frame data */ + p = fli_read(NULL, frame_size); + if (!p) { + fli_status = FLI_ERROR; + return; + } + + /* now to decode it */ + for (c=0; c= fli_header.frame_count) { + if (loop) { + fli_rewind(sizeof_FLI_HEADER); + fli_frame = 0; + } + else { + fli_status = FLI_EOF; + return fli_status; + } + } + + /* read the next frame */ + read_frame(); + + return fli_status; +} + + + +/* reset_fli_variables: + * Clears the information about which parts of the FLI bitmap and palette + * are dirty, after the screen hardware has been updated. + */ +void reset_fli_variables(void) +{ + fli_bmp_dirty_from = INT_MAX; + fli_bmp_dirty_to = INT_MIN; + fli_pal_dirty_from = INT_MAX; + fli_pal_dirty_to = INT_MIN; +} + diff --git a/libsrc/allegro/src/flood.c b/libsrc/allegro/src/flood.c new file mode 100644 index 00000000000..48995f1c196 --- /dev/null +++ b/libsrc/allegro/src/flood.c @@ -0,0 +1,278 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * The floodfill routine. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +typedef struct FLOODED_LINE /* store segments which have been flooded */ +{ + short flags; /* status of the segment */ + short lpos, rpos; /* left and right ends of segment */ + short y; /* y coordinate of the segment */ + int next; /* linked list if several per line */ +} FLOODED_LINE; + +/* Note: a 'short' is not sufficient for 'next' above in some corner cases. */ + + +static int flood_count; /* number of flooded segments */ + +#define FLOOD_IN_USE 1 +#define FLOOD_TODO_ABOVE 2 +#define FLOOD_TODO_BELOW 4 + +#define FLOOD_LINE(c) (((FLOODED_LINE *)_scratch_mem) + c) + + + +/* flooder: + * Fills a horizontal line around the specified position, and adds it + * to the list of drawn segments. Returns the first x coordinate after + * the part of the line which it has dealt with. + */ +static int flooder(BITMAP *bmp, int x, int y, int src_color, int dest_color) +{ + FLOODED_LINE *p; + int left = 0, right = 0; + unsigned long addr; + int c; + + /* helper for doing checks in each color depth */ + #define FLOODER(bits, size) \ + { \ + /* check start pixel */ \ + if ((int)bmp_read##bits(addr+x*size) != src_color) \ + return x+1; \ + \ + /* work left from starting point */ \ + for (left=x-1; left>=bmp->cl; left--) { \ + if ((int)bmp_read##bits(addr+left*size) != src_color) \ + break; \ + } \ + \ + /* work right from starting point */ \ + for (right=x+1; rightcr; right++) { \ + if ((int)bmp_read##bits(addr+right*size) != src_color) \ + break; \ + } \ + } + + ASSERT(bmp); + + if (is_linear_bitmap(bmp)) { /* use direct access for linear bitmaps */ + addr = bmp_read_line(bmp, y); + bmp_select(bmp); + + switch (bitmap_color_depth(bmp)) { + + #ifdef ALLEGRO_COLOR8 + case 8: + FLOODER(8, 1); + break; + #endif + + #ifdef ALLEGRO_COLOR16 + case 15: + case 16: + FLOODER(16, sizeof(short)); + break; + #endif + + #ifdef ALLEGRO_COLOR24 + case 24: + FLOODER(24, 3); + break; + #endif + + #ifdef ALLEGRO_COLOR32 + case 32: + FLOODER(32, sizeof(int32_t)); + break; + #endif + } + + bmp_unwrite_line(bmp); + } + else { /* have to use getpixel() for mode-X */ + /* check start pixel */ + if (getpixel(bmp, x, y) != src_color) + return x+1; + + /* work left from starting point */ + for (left=x-1; left>=bmp->cl; left--) + if (getpixel(bmp, left, y) != src_color) + break; + + /* work right from starting point */ + for (right=x+1; rightcr; right++) + if (getpixel(bmp, right, y) != src_color) + break; + } + + left++; + right--; + + /* draw the line */ + bmp->vtable->hfill(bmp, left, y, right, dest_color); + + /* store it in the list of flooded segments */ + c = y; + p = FLOOD_LINE(c); + + if (p->flags) { + while (p->next) { + c = p->next; + p = FLOOD_LINE(c); + } + + p->next = c = flood_count++; + _grow_scratch_mem(sizeof(FLOODED_LINE) * flood_count); + p = FLOOD_LINE(c); + } + + p->flags = FLOOD_IN_USE; + p->lpos = left; + p->rpos = right; + p->y = y; + p->next = 0; + + if (y > bmp->ct) + p->flags |= FLOOD_TODO_ABOVE; + + if (y+1 < bmp->cb) + p->flags |= FLOOD_TODO_BELOW; + + return right+2; +} + + + +/* check_flood_line: + * Checks a line segment, using the scratch buffer is to store a list of + * segments which have already been drawn in order to minimise the required + * number of tests. + */ +static int check_flood_line(BITMAP *bmp, int y, int left, int right, int src_color, int dest_color) +{ + int c; + FLOODED_LINE *p; + int ret = FALSE; + + while (left <= right) { + c = y; + + for (;;) { + p = FLOOD_LINE(c); + + if ((left >= p->lpos) && (left <= p->rpos)) { + left = p->rpos+2; + break; + } + + c = p->next; + + if (!c) { + left = flooder(bmp, left, y, src_color, dest_color); + ret = TRUE; + break; + } + } + } + + return ret; +} + + + +/* floodfill: + * Fills an enclosed area (starting at point x, y) with the specified color. + */ +void _soft_floodfill(BITMAP *bmp, int x, int y, int color) +{ + int src_color; + int c, done; + FLOODED_LINE *p; + ASSERT(bmp); + + /* make sure we have a valid starting point */ + if ((x < bmp->cl) || (x >= bmp->cr) || (y < bmp->ct) || (y >= bmp->cb)) + return; + + acquire_bitmap(bmp); + + /* what color to replace? */ + src_color = getpixel(bmp, x, y); + if (src_color == color) { + release_bitmap(bmp); + return; + } + + /* set up the list of flooded segments */ + _grow_scratch_mem(sizeof(FLOODED_LINE) * bmp->cb); + flood_count = bmp->cb; + p = _scratch_mem; + for (c=0; cflags & FLOOD_TODO_BELOW) { + p->flags &= ~FLOOD_TODO_BELOW; + if (check_flood_line(bmp, p->y+1, p->lpos, p->rpos, src_color, color)) { + done = FALSE; + p = FLOOD_LINE(c); + } + } + + /* check above the segment? */ + if (p->flags & FLOOD_TODO_ABOVE) { + p->flags &= ~FLOOD_TODO_ABOVE; + if (check_flood_line(bmp, p->y-1, p->lpos, p->rpos, src_color, color)) { + done = FALSE; + /* special case shortcut for going backwards */ + if ((c < bmp->cb) && (c > 0)) + c -= 2; + } + } + } + + } while (!done); + + release_bitmap(bmp); +} + diff --git a/libsrc/allegro/src/gfx.c b/libsrc/allegro/src/gfx.c new file mode 100644 index 00000000000..1bd6f0a80fc --- /dev/null +++ b/libsrc/allegro/src/gfx.c @@ -0,0 +1,719 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Graphics routines: palette fading, circles, etc. + * + * By Shawn Hargreaves. + * + * Optimised line drawer by Michael Bukin. + * + * Bresenham arc routine by Romano Signorelli. + * + * Cohen-Sutherland line clipping by Jon Rafkind. + * + * See readme.txt for copyright information. + */ + + +#include +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* drawing_mode: + * Sets the drawing mode. This only affects routines like putpixel, + * lines, rectangles, triangles, etc, not the blitting or sprite + * drawing functions. + */ +void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor) +{ + _drawing_mode = mode; + _drawing_pattern = pattern; + _drawing_x_anchor = x_anchor; + _drawing_y_anchor = y_anchor; + + if (pattern) { + _drawing_x_mask = 1; + while (_drawing_x_mask < (unsigned)pattern->w) + _drawing_x_mask <<= 1; /* find power of two greater than w */ + + if (_drawing_x_mask > (unsigned)pattern->w) { + ASSERT(FALSE); + _drawing_x_mask >>= 1; /* round down if required */ + } + + _drawing_x_mask--; /* convert to AND mask */ + + _drawing_y_mask = 1; + while (_drawing_y_mask < (unsigned)pattern->h) + _drawing_y_mask <<= 1; /* find power of two greater than h */ + + if (_drawing_y_mask > (unsigned)pattern->h) { + ASSERT(FALSE); + _drawing_y_mask >>= 1; /* round down if required */ + } + + _drawing_y_mask--; /* convert to AND mask */ + } + else + _drawing_x_mask = _drawing_y_mask = 0; +} + + + +/* set_blender_mode: + * Specifies a custom set of blender functions for interpolating between + * truecolor pixels. The 24 bit blender is shared between the 24 and 32 bit + * modes. Pass a NULL table for unused color depths (you must not draw + * translucent graphics in modes without a handler, though!). Your blender + * will be passed two 32 bit colors in the appropriate format (5.5.5, 5.6.5, + * or 8.8.8), and an alpha value, should return the result of combining them. + * In translucent drawing modes, the two colors are taken from the source + * and destination images and the alpha is specified by this function. In + * lit modes, the alpha is specified when you call the drawing routine, and + * the interpolation is between the source color and the RGB values you pass + * to this function. + */ +void set_blender_mode(BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, int r, int g, int b, int a) +{ + _blender_func15 = b15; + _blender_func16 = b16; + _blender_func24 = b24; + _blender_func32 = b24; + + _blender_func15x = _blender_black; + _blender_func16x = _blender_black; + _blender_func24x = _blender_black; + + _blender_col_15 = makecol15(r, g, b); + _blender_col_16 = makecol16(r, g, b); + _blender_col_24 = makecol24(r, g, b); + _blender_col_32 = makecol32(r, g, b); + + _blender_alpha = a; +} + + + +/* set_blender_mode_ex + * Specifies a custom set of blender functions for interpolating between + * truecolor pixels, providing a more complete set of routines, which + * differentiate between 24 and 32 bit modes, and have special routines + * for blending 32 bit RGBA pixels onto a destination of any format. + */ +void set_blender_mode_ex(BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, BLENDER_FUNC b32, BLENDER_FUNC b15x, BLENDER_FUNC b16x, BLENDER_FUNC b24x, int r, int g, int b, int a) +{ + _blender_func15 = b15; + _blender_func16 = b16; + _blender_func24 = b24; + _blender_func32 = b32; + + _blender_func15x = b15x; + _blender_func16x = b16x; + _blender_func24x = b24x; + + _blender_col_15 = makecol15(r, g, b); + _blender_col_16 = makecol16(r, g, b); + _blender_col_24 = makecol24(r, g, b); + _blender_col_32 = makecol32(r, g, b); + + _blender_alpha = a; +} + + + +/* xor_mode: + * Shortcut function for toggling XOR mode on and off. + */ +void xor_mode(int on) +{ + drawing_mode(on ? DRAW_MODE_XOR : DRAW_MODE_SOLID, NULL, 0, 0); +} + + + +/* solid_mode: + * Shortcut function for selecting solid drawing mode. + */ +void solid_mode(void) +{ + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + + +/* clear_bitmap: + * Clears the bitmap to color 0. + */ +void clear_bitmap(BITMAP *bitmap) +{ + clear_to_color(bitmap, 0); +} + + + +/* _bitmap_has_alpha: + * Checks whether this bitmap has an alpha channel. + */ +int _bitmap_has_alpha(BITMAP *bmp) +{ + int x, y, c; + + if (bitmap_color_depth(bmp) != 32) + return FALSE; + + for (y = 0; y < bmp->h; y++) { + for (x = 0; x < bmp->w; x++) { + c = getpixel(bmp, x, y); + if (geta32(c)) + return TRUE; + } + } + + return FALSE; +} + + + +/* set_color: + * Sets a single palette entry. + */ +void set_color(int index, AL_CONST RGB *p) +{ + ASSERT(index >= 0 && index < PAL_SIZE); + set_palette_range((struct RGB *)p-index, index, index, FALSE); +} + + + +/* set_palette: + * Sets the entire color palette. + */ +void set_palette(AL_CONST PALETTE p) +{ + set_palette_range(p, 0, PAL_SIZE-1, TRUE); +} + + + +/* set_palette_range: + * Sets a part of the color palette. + */ +void set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) +{ + int c; + + ASSERT(from >= 0 && from < PAL_SIZE); + ASSERT(to >= 0 && to < PAL_SIZE) + + for (c=from; c<=to; c++) { + _current_palette[c] = p[c]; + + if (_color_depth != 8) + palette_color[c] = makecol(_rgb_scale_6[p[c].r], _rgb_scale_6[p[c].g], _rgb_scale_6[p[c].b]); + } + + _current_palette_changed = 0xFFFFFFFF & ~(1<<(_color_depth-1)); +} + + + +/* previous palette, so the image loaders can restore it when they are done */ +int _got_prev_current_palette = FALSE; +PALETTE _prev_current_palette; +static int prev_palette_color[PAL_SIZE]; + + + +/* select_palette: + * Sets the aspects of the palette tables that are used for converting + * between different image formats, without altering the display settings. + * The previous settings are copied onto a one-deep stack, from where they + * can be restored by calling unselect_palette(). + */ +void select_palette(AL_CONST PALETTE p) +{ + int c; + + for (c=0; ctruecolor. + */ +static int *palette_expansion_table(int bpp) +{ + int *table; + int c; + + switch (bpp) { + case 15: table = _palette_color15; break; + case 16: table = _palette_color16; break; + case 24: table = _palette_color24; break; + case 32: table = _palette_color32; break; + default: ASSERT(FALSE); return NULL; + } + + if (_current_palette_changed & (1<<(bpp-1))) { + for (c=0; c>5)&7) * 63/7; + pal[c].g = ((c>>2)&7) * 63/7; + pal[c].b = (c&3) * 63/3; + } + + pal[0].r = 63; + pal[0].g = 0; + pal[0].b = 63; + + pal[254].r = pal[254].g = pal[254].b = 0; +} + + + +/* get_color: + * Retrieves a single color from the palette. + */ +void get_color(int index, RGB *p) +{ + ASSERT(index >= 0 && index < PAL_SIZE); + ASSERT(p); + get_palette_range(p-index, index, index); +} + + + +/* get_palette: + * Retrieves the entire color palette. + */ +void get_palette(PALETTE p) +{ + get_palette_range(p, 0, PAL_SIZE-1); +} + + + +/* get_palette_range: + * Retrieves a part of the color palette. + */ +void get_palette_range(PALETTE p, int from, int to) +{ + int c; + + ASSERT(from >= 0 && from < PAL_SIZE); + ASSERT(to >= 0 && to < PAL_SIZE); + + for (c=from; c<=to; c++) + p[c] = _current_palette[c]; +} + + + +/* fade_interpolate: + * Calculates a palette part way between source and dest, returning it + * in output. The pos indicates how far between the two extremes it should + * be: 0 = return source, 64 = return dest, 32 = return exactly half way. + * Only affects colors between from and to (inclusive). + */ +void fade_interpolate(AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to) +{ + int c; + + ASSERT(pos >= 0 && pos <= 64); + ASSERT(from >= 0 && from < PAL_SIZE); + ASSERT(to >= 0 && to < PAL_SIZE); + + for (c=from; c<=to; c++) { + output[c].r = ((int)source[c].r * (63-pos) + (int)dest[c].r * pos) / 64; + output[c].g = ((int)source[c].g * (63-pos) + (int)dest[c].g * pos) / 64; + output[c].b = ((int)source[c].b * (63-pos) + (int)dest[c].b * pos) / 64; + } +} + + + +/* rect: + * Draws an outline rectangle. + */ +void _soft_rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + int t; + + if (x2 < x1) { + t = x1; + x1 = x2; + x2 = t; + } + + if (y2 < y1) { + t = y1; + y1 = y2; + y2 = t; + } + + acquire_bitmap(bmp); + + hline(bmp, x1, y1, x2, color); + + if (y2 > y1) + hline(bmp, x1, y2, x2, color); + + if (y2-1 >= y1+1) { + vline(bmp, x1, y1+1, y2-1, color); + + if (x2 > x1) + vline(bmp, x2, y1+1, y2-1, color); + } + + release_bitmap(bmp); +} + + + +/* _normal_rectfill: + * Draws a solid filled rectangle, using hfill() to do the work. + */ +void _normal_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + int t; + + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + if (bmp->clip) { + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + + if (x1 < bmp->cl) + x1 = bmp->cl; + + if (x2 >= bmp->cr) + x2 = bmp->cr-1; + + if (x2 < x1) + return; + + if (y1 < bmp->ct) + y1 = bmp->ct; + + if (y2 >= bmp->cb) + y2 = bmp->cb-1; + + if (y2 < y1) + return; + + bmp->clip = FALSE; + t = TRUE; + } + else + t = FALSE; + + acquire_bitmap(bmp); + + while (y1 <= y2) { + bmp->vtable->hfill(bmp, x1, y1, x2, color); + y1++; + }; + + release_bitmap(bmp); + + bmp->clip = t; +} + + + +/* do_line: + * Calculates all the points along a line between x1, y1 and x2, y2, + * calling the supplied function for each one. This will be passed a + * copy of the bmp parameter, the x and y position, and a copy of the + * d parameter (so do_line() can be used with putpixel()). + */ +void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, void (*proc)(BITMAP *, int, int, int)) +{ + int dx = x2-x1; + int dy = y2-y1; + int i1, i2; + int x, y; + int dd; + + /* worker macro */ + #define DO_LINE(pri_sign, pri_c, pri_cond, sec_sign, sec_c, sec_cond) \ + { \ + if (d##pri_c == 0) { \ + proc(bmp, x1, y1, d); \ + return; \ + } \ + \ + i1 = 2 * d##sec_c; \ + dd = i1 - (sec_sign (pri_sign d##pri_c)); \ + i2 = dd - (sec_sign (pri_sign d##pri_c)); \ + \ + x = x1; \ + y = y1; \ + \ + while (pri_c pri_cond pri_c##2) { \ + proc(bmp, x, y, d); \ + \ + if (dd sec_cond 0) { \ + sec_c = sec_c sec_sign 1; \ + dd += i2; \ + } \ + else \ + dd += i1; \ + \ + pri_c = pri_c pri_sign 1; \ + } \ + } + + if (dx >= 0) { + if (dy >= 0) { + if (dx >= dy) { + /* (x1 <= x2) && (y1 <= y2) && (dx >= dy) */ + DO_LINE(+, x, <=, +, y, >=); + } + else { + /* (x1 <= x2) && (y1 <= y2) && (dx < dy) */ + DO_LINE(+, y, <=, +, x, >=); + } + } + else { + if (dx >= -dy) { + /* (x1 <= x2) && (y1 > y2) && (dx >= dy) */ + DO_LINE(+, x, <=, -, y, <=); + } + else { + /* (x1 <= x2) && (y1 > y2) && (dx < dy) */ + DO_LINE(-, y, >=, +, x, >=); + } + } + } + else { + if (dy >= 0) { + if (-dx >= dy) { + /* (x1 > x2) && (y1 <= y2) && (dx >= dy) */ + DO_LINE(-, x, >=, +, y, >=); + } + else { + /* (x1 > x2) && (y1 <= y2) && (dx < dy) */ + DO_LINE(+, y, <=, -, x, <=); + } + } + else { + if (-dx >= -dy) { + /* (x1 > x2) && (y1 > y2) && (dx >= dy) */ + DO_LINE(-, x, >=, -, y, <=); + } + else { + /* (x1 > x2) && (y1 > y2) && (dx < dy) */ + DO_LINE(-, y, >=, -, x, <=); + } + } + } + + #undef DO_LINE +} + + + +/* _normal_line: + * Draws a line from x1, y1 to x2, y2, using putpixel() to do the work. + */ +void _normal_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + int sx, sy, dx, dy, t; + + if (x1 == x2) { + vline(bmp, x1, y1, y2, color); + return; + } + + if (y1 == y2) { + hline(bmp, x1, y1, x2, color); + return; + } + + /* use a bounding box to check if the line needs clipping */ + if (bmp->clip) { + sx = x1; + sy = y1; + dx = x2; + dy = y2; + + if (sx > dx) { + t = sx; + sx = dx; + dx = t; + } + + if (sy > dy) { + t = sy; + sy = dy; + dy = t; + } + + if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) + return; + + if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) + bmp->clip = FALSE; + + t = TRUE; + } + else + t= FALSE; + + acquire_bitmap(bmp); + + do_line(bmp, x1, y1, x2, y2, color, bmp->vtable->putpixel); + + release_bitmap(bmp); + + bmp->clip = t; +} + + +/* circlefill: + * Draws a filled circle. + */ +void _soft_circlefill(BITMAP *bmp, int x, int y, int radius, int color) +{ + int cx = 0; + int cy = radius; + int df = 1 - radius; + int d_e = 3; + int d_se = -2 * radius + 5; + int clip, sx, sy, dx, dy; + ASSERT(bmp); + + if (bmp->clip) { + sx = x-radius-1; + sy = y-radius-1; + dx = x+radius+1; + dy = y+radius+1; + + if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) + return; + + if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) + bmp->clip = FALSE; + + clip = TRUE; + } + else + clip = FALSE; + + acquire_bitmap(bmp); + + do { + bmp->vtable->hfill(bmp, x-cy, y-cx, x+cy, color); + + if (cx) + bmp->vtable->hfill(bmp, x-cy, y+cx, x+cy, color); + + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } + else { + if (cx != cy) { + bmp->vtable->hfill(bmp, x-cx, y-cy, x+cx, color); + + if (cy) + bmp->vtable->hfill(bmp, x-cx, y+cy, x+cx, color); + } + + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + + cx++; + + } while (cx <= cy); + + release_bitmap(bmp); + + bmp->clip = clip; +} diff --git a/libsrc/allegro/src/graphics.c b/libsrc/allegro/src/graphics.c new file mode 100644 index 00000000000..fec8c40f31e --- /dev/null +++ b/libsrc/allegro/src/graphics.c @@ -0,0 +1,539 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Graphics mode set and bitmap creation routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + +extern void blit_end(void); /* for LOCK_FUNCTION; defined in blit.c */ + + + +#define PREFIX_I "al-gfx INFO: " +#define PREFIX_W "al-gfx WARNING: " +#define PREFIX_E "al-gfx ERROR: " + + + +int _sub_bitmap_id_count = 1; /* hash value for sub-bitmaps */ + +RGB_MAP *rgb_map = NULL; /* RGB -> palette entry conversion */ + +COLOR_MAP *color_map = NULL; /* translucency/lighting table */ + +int _color_depth = 8; /* how many bits per pixel? */ + +int _color_conv = COLORCONV_TOTAL; /* which formats to auto convert? */ + +static int color_conv_set = FALSE; /* has the user set conversion mode? */ + +int _palette_color8[256]; /* palette -> pixel mapping */ +int _palette_color15[256]; +int _palette_color16[256]; +int _palette_color24[256]; +int _palette_color32[256]; + +int *palette_color = _palette_color8; + +BLENDER_FUNC _blender_func15 = NULL; /* truecolor pixel blender routines */ +BLENDER_FUNC _blender_func16 = NULL; +BLENDER_FUNC _blender_func24 = NULL; +BLENDER_FUNC _blender_func32 = NULL; + +BLENDER_FUNC _blender_func15x = NULL; +BLENDER_FUNC _blender_func16x = NULL; +BLENDER_FUNC _blender_func24x = NULL; + +int _blender_col_15 = 0; /* for truecolor lit sprites */ +int _blender_col_16 = 0; +int _blender_col_24 = 0; +int _blender_col_32 = 0; + +int _blender_alpha = 0; /* for truecolor translucent drawing */ + +int _rgb_r_shift_15 = DEFAULT_RGB_R_SHIFT_15; /* truecolor pixel format */ +int _rgb_g_shift_15 = DEFAULT_RGB_G_SHIFT_15; +int _rgb_b_shift_15 = DEFAULT_RGB_B_SHIFT_15; +int _rgb_r_shift_16 = DEFAULT_RGB_R_SHIFT_16; +int _rgb_g_shift_16 = DEFAULT_RGB_G_SHIFT_16; +int _rgb_b_shift_16 = DEFAULT_RGB_B_SHIFT_16; +int _rgb_r_shift_24 = DEFAULT_RGB_R_SHIFT_24; +int _rgb_g_shift_24 = DEFAULT_RGB_G_SHIFT_24; +int _rgb_b_shift_24 = DEFAULT_RGB_B_SHIFT_24; +int _rgb_r_shift_32 = DEFAULT_RGB_R_SHIFT_32; +int _rgb_g_shift_32 = DEFAULT_RGB_G_SHIFT_32; +int _rgb_b_shift_32 = DEFAULT_RGB_B_SHIFT_32; +int _rgb_a_shift_32 = DEFAULT_RGB_A_SHIFT_32; + + +/* lookup table for scaling 5 bit colors up to 8 bits */ +int _rgb_scale_5[32] = +{ + 0, 8, 16, 24, 33, 41, 49, 57, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 198, 206, 214, 222, 231, 239, 247, 255 +}; + + +/* lookup table for scaling 6 bit colors up to 8 bits */ +int _rgb_scale_6[64] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + 65, 69, 73, 77, 81, 85, 89, 93, + 97, 101, 105, 109, 113, 117, 121, 125, + 130, 134, 138, 142, 146, 150, 154, 158, + 162, 166, 170, 174, 178, 182, 186, 190, + 195, 199, 203, 207, 211, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 255 +}; + + +#define BMP_MAX_SIZE 46340 /* sqrt(INT_MAX) */ + +/* the product of these must fit in an int */ +static int failed_bitmap_w = BMP_MAX_SIZE; +static int failed_bitmap_h = BMP_MAX_SIZE; + + + +static int _set_gfx_mode(int card, int w, int h, int v_w, int v_h, int allow_config); +static int _set_gfx_mode_safe(int card, int w, int h, int v_w, int v_h); + + + +/* lock_bitmap: + * Locks all the memory used by a bitmap structure. + */ +void lock_bitmap(BITMAP *bmp) +{ + LOCK_DATA(bmp, sizeof(BITMAP) + sizeof(char *) * bmp->h); + + if (bmp->dat) { + LOCK_DATA(bmp->dat, bmp->w * bmp->h * BYTES_PER_PIXEL(bitmap_color_depth(bmp))); + } +} + + + +/* set_color_depth: + * Sets the pixel size (in bits) which will be used by subsequent calls to + * set_gfx_mode() and create_bitmap(). Valid depths are 8, 15, 16, 24 and 32. + */ +void set_color_depth(int depth) +{ + _color_depth = depth; + + switch (depth) { + case 8: palette_color = _palette_color8; break; + case 15: palette_color = _palette_color15; break; + case 16: palette_color = _palette_color16; break; + case 24: palette_color = _palette_color24; break; + case 32: palette_color = _palette_color32; break; + default: ASSERT(FALSE); + } +} + + + +/* get_color_depth: + * Returns the current color depth. + */ +int get_color_depth(void) +{ + return _color_depth; +} + + + +/* set_color_conversion: + * Sets a bit mask specifying which types of color format conversions are + * valid when loading data from disk. + */ +void set_color_conversion(int mode) +{ + _color_conv = mode; + + color_conv_set = TRUE; +} + + + +/* get_color_conversion: + * Returns the bitmask specifying which types of color format + * conversion are valid when loading data from disk. + */ +int get_color_conversion(void) +{ + return _color_conv; +} + + + +/* _color_load_depth: + * Works out which color depth an image should be loaded as, given the + * current conversion mode. + */ +int _color_load_depth(int depth, int hasalpha) +{ + typedef struct CONVERSION_FLAGS + { + int flag; + int in_depth; + int out_depth; + int hasalpha; + } CONVERSION_FLAGS; + + static CONVERSION_FLAGS conversion_flags[] = + { + { COLORCONV_8_TO_15, 8, 15, FALSE }, + { COLORCONV_8_TO_16, 8, 16, FALSE }, + { COLORCONV_8_TO_24, 8, 24, FALSE }, + { COLORCONV_8_TO_32, 8, 32, FALSE }, + { COLORCONV_15_TO_8, 15, 8, FALSE }, + { COLORCONV_15_TO_16, 15, 16, FALSE }, + { COLORCONV_15_TO_24, 15, 24, FALSE }, + { COLORCONV_15_TO_32, 15, 32, FALSE }, + { COLORCONV_16_TO_8, 16, 8, FALSE }, + { COLORCONV_16_TO_15, 16, 15, FALSE }, + { COLORCONV_16_TO_24, 16, 24, FALSE }, + { COLORCONV_16_TO_32, 16, 32, FALSE }, + { COLORCONV_24_TO_8, 24, 8, FALSE }, + { COLORCONV_24_TO_15, 24, 15, FALSE }, + { COLORCONV_24_TO_16, 24, 16, FALSE }, + { COLORCONV_24_TO_32, 24, 32, FALSE }, + { COLORCONV_32_TO_8, 32, 8, FALSE }, + { COLORCONV_32_TO_15, 32, 15, FALSE }, + { COLORCONV_32_TO_16, 32, 16, FALSE }, + { COLORCONV_32_TO_24, 32, 24, FALSE }, + { COLORCONV_32A_TO_8, 32, 8 , TRUE }, + { COLORCONV_32A_TO_15, 32, 15, TRUE }, + { COLORCONV_32A_TO_16, 32, 16, TRUE }, + { COLORCONV_32A_TO_24, 32, 24, TRUE } + }; + + int i; + + ASSERT(color_conv_set); + + if (depth == _color_depth) + return depth; + + for (i=0; i < (int)(sizeof(conversion_flags)/sizeof(CONVERSION_FLAGS)); i++) { + if ((conversion_flags[i].in_depth == depth) && + (conversion_flags[i].out_depth == _color_depth) && + ((conversion_flags[i].hasalpha != 0) == (hasalpha != 0))) { + if (_color_conv & conversion_flags[i].flag) + return _color_depth; + else + return depth; + } + } + + ASSERT(FALSE); + return 0; +} + + + +/* _get_vtable: + * Returns a pointer to the linear vtable for the specified color depth. + */ +GFX_VTABLE *_get_vtable(int color_depth) +{ + GFX_VTABLE *vt; + int i; + + for (i=0; _vtable_list[i].vtable; i++) { + if (_vtable_list[i].color_depth == color_depth) { + LOCK_DATA(_vtable_list[i].vtable, sizeof(GFX_VTABLE)); + LOCK_CODE(_vtable_list[i].vtable->draw_sprite, (long)_vtable_list[i].vtable->draw_sprite_end - (long)_vtable_list[i].vtable->draw_sprite); + LOCK_CODE(_vtable_list[i].vtable->blit_from_memory, (long)_vtable_list[i].vtable->blit_end - (long)_vtable_list[i].vtable->blit_from_memory); + return _vtable_list[i].vtable; + } + } + + return NULL; +} + + + +/* create_bitmap_ex + * Creates a new memory bitmap in the specified color_depth + */ +BITMAP *create_bitmap_ex(int color_depth, int width, int height) +{ + GFX_VTABLE *vtable; + BITMAP *bitmap; + int nr_pointers; + int padding; + int i; + + ASSERT(width >= 0); + ASSERT(height > 0); + + vtable = _get_vtable(color_depth); + if (!vtable) + return NULL; + + /* We need at least two pointers when drawing, otherwise we get crashes with + * Electric Fence. We think some of the assembly code assumes a second line + * pointer is always available. + */ + nr_pointers = MAX(2, height); + bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers)); + if (!bitmap) + return NULL; + + /* This avoids a crash for assembler code accessing the last pixel, as it + * read 4 bytes instead of 3. + */ + padding = (color_depth == 24) ? 1 : 0; + + bitmap->dat = _AL_MALLOC_ATOMIC(width * height * BYTES_PER_PIXEL(color_depth) + padding); + if (!bitmap->dat) { + _AL_FREE(bitmap); + return NULL; + } + + bitmap->w = bitmap->cr = width; + bitmap->h = bitmap->cb = height; + bitmap->clip = TRUE; + bitmap->cl = bitmap->ct = 0; + bitmap->vtable = vtable; + bitmap->write_bank = bitmap->read_bank = _stub_bank_switch; + bitmap->id = 0; + bitmap->extra = NULL; + bitmap->x_ofs = 0; + bitmap->y_ofs = 0; + bitmap->seg = _default_ds(); + + if (height > 0) { + bitmap->line[0] = bitmap->dat; + for (i=1; iline[i] = bitmap->line[i-1] + width * BYTES_PER_PIXEL(color_depth); + } + + return bitmap; +} + + + +/* create_bitmap: + * Creates a new memory bitmap. + */ +BITMAP *create_bitmap(int width, int height) +{ + ASSERT(width >= 0); + ASSERT(height > 0); + return create_bitmap_ex(_color_depth, width, height); +} + + + +/* create_sub_bitmap: + * Creates a sub bitmap, ie. a bitmap sharing drawing memory with a + * pre-existing bitmap, but possibly with different clipping settings. + * Usually will be smaller, and positioned at some arbitrary point. + * + * Mark Wodrich is the owner of the brain responsible this hugely useful + * and beautiful function. + */ +BITMAP *create_sub_bitmap(BITMAP *parent, int x, int y, int width, int height) +{ + BITMAP *bitmap; + int nr_pointers; + int i; + + ASSERT(parent); + ASSERT((x >= 0) && (y >= 0) && (x < parent->w) && (y < parent->h)); + ASSERT((width > 0) && (height > 0)); + + if (x+width > parent->w) + width = parent->w-x; + + if (y+height > parent->h) + height = parent->h-y; + + if (parent->vtable->create_sub_bitmap) + return parent->vtable->create_sub_bitmap(parent, x, y, width, height); + + /* get memory for structure and line pointers */ + /* (see create_bitmap for the reason we need at least two) */ + nr_pointers = MAX(2, height); + bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers)); + if (!bitmap) + return NULL; + + acquire_bitmap(parent); + + bitmap->w = bitmap->cr = width; + bitmap->h = bitmap->cb = height; + bitmap->clip = TRUE; + bitmap->cl = bitmap->ct = 0; + bitmap->vtable = parent->vtable; + bitmap->write_bank = parent->write_bank; + bitmap->read_bank = parent->read_bank; + bitmap->dat = NULL; + bitmap->extra = NULL; + bitmap->x_ofs = x + parent->x_ofs; + bitmap->y_ofs = y + parent->y_ofs; + bitmap->seg = parent->seg; + + /* All bitmaps are created with zero ID's. When a sub-bitmap is created, + * a unique ID is needed to identify the relationship when blitting from + * one to the other. This is obtained from the global variable + * _sub_bitmap_id_count, which provides a sequence of integers (yes I + * know it will wrap eventually, but not for a long time :-) If the + * parent already has an ID the sub-bitmap adopts it, otherwise a new + * ID is given to both the parent and the child. + */ + if (!(parent->id & BMP_ID_MASK)) { + parent->id |= _sub_bitmap_id_count; + _sub_bitmap_id_count = (_sub_bitmap_id_count+1) & BMP_ID_MASK; + } + + bitmap->id = parent->id | BMP_ID_SUB; + bitmap->id &= ~BMP_ID_LOCKED; + + if (is_planar_bitmap(bitmap)) + x /= 4; + + x *= BYTES_PER_PIXEL(bitmap_color_depth(bitmap)); + + /* setup line pointers: each line points to a line in the parent bitmap */ + for (i=0; iline[i] = parent->line[y+i] + x; + + if (bitmap->vtable->set_clip) + bitmap->vtable->set_clip(bitmap); + + if (parent->vtable->created_sub_bitmap) + parent->vtable->created_sub_bitmap(bitmap, parent); + + release_bitmap(parent); + + return bitmap; +} + + + +/* destroy_bitmap: + * Destroys a memory bitmap. + */ +void destroy_bitmap(BITMAP *bitmap) +{ + if (bitmap) { + /* normal memory or sub-bitmap destruction */ + + if (bitmap->dat) + _AL_FREE(bitmap->dat); + + _AL_FREE(bitmap); + } +} + + + +/* set_clip_rect: + * Sets the two opposite corners of the clipping rectangle to be used when + * drawing to the bitmap. Nothing will be drawn to positions outside of this + * rectangle. When a new bitmap is created the clipping rectangle will be + * set to the full area of the bitmap. + */ +void set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2) +{ + ASSERT(bitmap); + + /* internal clipping is inclusive-exclusive */ + x2++; + y2++; + + bitmap->cl = CLAMP(0, x1, bitmap->w-1); + bitmap->ct = CLAMP(0, y1, bitmap->h-1); + bitmap->cr = CLAMP(0, x2, bitmap->w); + bitmap->cb = CLAMP(0, y2, bitmap->h); + + if (bitmap->vtable->set_clip) + bitmap->vtable->set_clip(bitmap); +} + + + +/* add_clip_rect: + * Makes the new clipping rectangle the intersection between the given + * rectangle and the current one. + */ +void add_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2) +{ + int cx1, cy1, cx2, cy2; + + ASSERT(bitmap); + + get_clip_rect(bitmap, &cx1, &cy1, &cx2, &cy2); + + x1 = MAX(x1, cx1); + y1 = MAX(y1, cy1); + x2 = MIN(x2, cx2); + y2 = MIN(y2, cy2); + + set_clip_rect(bitmap, x1, y1, x2, y2); +} + + + +/* set_clip: + * Sets the two opposite corners of the clipping rectangle to be used when + * drawing to the bitmap. Nothing will be drawn to positions outside of this + * rectangle. When a new bitmap is created the clipping rectangle will be + * set to the full area of the bitmap. If x1, y1, x2 and y2 are all zero + * clipping will be turned off, which will slightly speed up drawing + * operations but will allow memory to be corrupted if you attempt to draw + * off the edge of the bitmap. + */ +void set_clip(BITMAP *bitmap, int x1, int y1, int x2, int y2) +{ + int t; + + ASSERT(bitmap); + + if ((!x1) && (!y1) && (!x2) && (!y2)) { + set_clip_rect(bitmap, 0, 0, bitmap->w-1, bitmap->h-1); + set_clip_state(bitmap, FALSE); + return; + } + + if (x2 < x1) { + t = x1; + x1 = x2; + x2 = t; + } + + if (y2 < y1) { + t = y1; + y1 = y2; + y2 = t; + } + + set_clip_rect(bitmap, x1, y1, x2, y2); + set_clip_state(bitmap, TRUE); +} + + diff --git a/libsrc/allegro/src/inline.c b/libsrc/allegro/src/inline.c new file mode 100644 index 00000000000..4dcb31a052e --- /dev/null +++ b/libsrc/allegro/src/inline.c @@ -0,0 +1,28 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Copies of the inline functions in allegro.h, in case anyone needs + * to take the address of them, or is compiling without optimisation. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#define AL_INLINE(type, name, args, code) type name args code + +#include "allegro.h" +#include "allegro/internal/aintern.h" + +#ifdef ALLEGRO_INTERNAL_HEADER + #include ALLEGRO_INTERNAL_HEADER +#endif + diff --git a/libsrc/allegro/src/libc.c b/libsrc/allegro/src/libc.c new file mode 100644 index 00000000000..389c8cc4ea2 --- /dev/null +++ b/libsrc/allegro/src/libc.c @@ -0,0 +1,176 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Emulation for libc routines that may be missing on some platforms. + * + * By Michael Bukin. + * + * Henrik Stokseth added _al_sane_realloc() and _al_sane_strncpy() functions. + * + * _al_srand() and _al_rand() functions based on code by Paul Pridham. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" +#include + + +static int _al_rand_seed = 0; + + + +#ifdef ALLEGRO_NO_STRLWR + +/* _alemu_strlwr: + * Convert all upper case characters in string to lower case. + */ +char *_alemu_strlwr(char *string) +{ + char *p; + ASSERT(string); + + for (p=string; *p; p++) + *p = utolower(*p); + + return string; +} + +#endif + + + +#ifdef ALLEGRO_NO_STRUPR + +/* _alemu_strupr: + * Convert all lower case characters in string to upper case. + */ +char *_alemu_strupr(char *string) +{ + char *p; + ASSERT(string); + + for (p=string; *p; p++) + *p = utoupper(*p); + + return string; +} + +#endif + + + +#ifdef ALLEGRO_NO_STRICMP + +/* _alemu_stricmp: + * Case-insensitive comparison of strings. + */ +int _alemu_stricmp(AL_CONST char *s1, AL_CONST char *s2) +{ + int c1, c2; + ASSERT(s1); + ASSERT(s2); + + do { + c1 = utolower(*(s1++)); + c2 = utolower(*(s2++)); + } while ((c1) && (c1 == c2)); + + return c1 - c2; +} + +#endif + + + +#ifdef ALLEGRO_NO_MEMCMP + +/* _alemu_memcmp: + * Comparison of two memory blocks. + */ +int _alemu_memcmp(AL_CONST void *s1, AL_CONST void *s2, size_t num) +{ + size_t i; + ASSERT(s1); + ASSERT(s2); + ASSERT(num >= 0); + + for (i=0; i> 16) & _AL_RAND_MAX); +} diff --git a/libsrc/allegro/src/math.c b/libsrc/allegro/src/math.c new file mode 100644 index 00000000000..3e88e4701fb --- /dev/null +++ b/libsrc/allegro/src/math.c @@ -0,0 +1,367 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point math routines and lookup tables. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include + +#include "allegro.h" + + + +fixed _cos_tbl[512] = +{ + /* precalculated fixed point (16.16) cosines for a full circle (0-255) */ + + 65536L, 65531L, 65516L, 65492L, 65457L, 65413L, 65358L, 65294L, + 65220L, 65137L, 65043L, 64940L, 64827L, 64704L, 64571L, 64429L, + 64277L, 64115L, 63944L, 63763L, 63572L, 63372L, 63162L, 62943L, + 62714L, 62476L, 62228L, 61971L, 61705L, 61429L, 61145L, 60851L, + 60547L, 60235L, 59914L, 59583L, 59244L, 58896L, 58538L, 58172L, + 57798L, 57414L, 57022L, 56621L, 56212L, 55794L, 55368L, 54934L, + 54491L, 54040L, 53581L, 53114L, 52639L, 52156L, 51665L, 51166L, + 50660L, 50146L, 49624L, 49095L, 48559L, 48015L, 47464L, 46906L, + 46341L, 45769L, 45190L, 44604L, 44011L, 43412L, 42806L, 42194L, + 41576L, 40951L, 40320L, 39683L, 39040L, 38391L, 37736L, 37076L, + 36410L, 35738L, 35062L, 34380L, 33692L, 33000L, 32303L, 31600L, + 30893L, 30182L, 29466L, 28745L, 28020L, 27291L, 26558L, 25821L, + 25080L, 24335L, 23586L, 22834L, 22078L, 21320L, 20557L, 19792L, + 19024L, 18253L, 17479L, 16703L, 15924L, 15143L, 14359L, 13573L, + 12785L, 11996L, 11204L, 10411L, 9616L, 8820L, 8022L, 7224L, + 6424L, 5623L, 4821L, 4019L, 3216L, 2412L, 1608L, 804L, + 0L, -804L, -1608L, -2412L, -3216L, -4019L, -4821L, -5623L, + -6424L, -7224L, -8022L, -8820L, -9616L, -10411L, -11204L, -11996L, + -12785L, -13573L, -14359L, -15143L, -15924L, -16703L, -17479L, -18253L, + -19024L, -19792L, -20557L, -21320L, -22078L, -22834L, -23586L, -24335L, + -25080L, -25821L, -26558L, -27291L, -28020L, -28745L, -29466L, -30182L, + -30893L, -31600L, -32303L, -33000L, -33692L, -34380L, -35062L, -35738L, + -36410L, -37076L, -37736L, -38391L, -39040L, -39683L, -40320L, -40951L, + -41576L, -42194L, -42806L, -43412L, -44011L, -44604L, -45190L, -45769L, + -46341L, -46906L, -47464L, -48015L, -48559L, -49095L, -49624L, -50146L, + -50660L, -51166L, -51665L, -52156L, -52639L, -53114L, -53581L, -54040L, + -54491L, -54934L, -55368L, -55794L, -56212L, -56621L, -57022L, -57414L, + -57798L, -58172L, -58538L, -58896L, -59244L, -59583L, -59914L, -60235L, + -60547L, -60851L, -61145L, -61429L, -61705L, -61971L, -62228L, -62476L, + -62714L, -62943L, -63162L, -63372L, -63572L, -63763L, -63944L, -64115L, + -64277L, -64429L, -64571L, -64704L, -64827L, -64940L, -65043L, -65137L, + -65220L, -65294L, -65358L, -65413L, -65457L, -65492L, -65516L, -65531L, + -65536L, -65531L, -65516L, -65492L, -65457L, -65413L, -65358L, -65294L, + -65220L, -65137L, -65043L, -64940L, -64827L, -64704L, -64571L, -64429L, + -64277L, -64115L, -63944L, -63763L, -63572L, -63372L, -63162L, -62943L, + -62714L, -62476L, -62228L, -61971L, -61705L, -61429L, -61145L, -60851L, + -60547L, -60235L, -59914L, -59583L, -59244L, -58896L, -58538L, -58172L, + -57798L, -57414L, -57022L, -56621L, -56212L, -55794L, -55368L, -54934L, + -54491L, -54040L, -53581L, -53114L, -52639L, -52156L, -51665L, -51166L, + -50660L, -50146L, -49624L, -49095L, -48559L, -48015L, -47464L, -46906L, + -46341L, -45769L, -45190L, -44604L, -44011L, -43412L, -42806L, -42194L, + -41576L, -40951L, -40320L, -39683L, -39040L, -38391L, -37736L, -37076L, + -36410L, -35738L, -35062L, -34380L, -33692L, -33000L, -32303L, -31600L, + -30893L, -30182L, -29466L, -28745L, -28020L, -27291L, -26558L, -25821L, + -25080L, -24335L, -23586L, -22834L, -22078L, -21320L, -20557L, -19792L, + -19024L, -18253L, -17479L, -16703L, -15924L, -15143L, -14359L, -13573L, + -12785L, -11996L, -11204L, -10411L, -9616L, -8820L, -8022L, -7224L, + -6424L, -5623L, -4821L, -4019L, -3216L, -2412L, -1608L, -804L, + 0L, 804L, 1608L, 2412L, 3216L, 4019L, 4821L, 5623L, + 6424L, 7224L, 8022L, 8820L, 9616L, 10411L, 11204L, 11996L, + 12785L, 13573L, 14359L, 15143L, 15924L, 16703L, 17479L, 18253L, + 19024L, 19792L, 20557L, 21320L, 22078L, 22834L, 23586L, 24335L, + 25080L, 25821L, 26558L, 27291L, 28020L, 28745L, 29466L, 30182L, + 30893L, 31600L, 32303L, 33000L, 33692L, 34380L, 35062L, 35738L, + 36410L, 37076L, 37736L, 38391L, 39040L, 39683L, 40320L, 40951L, + 41576L, 42194L, 42806L, 43412L, 44011L, 44604L, 45190L, 45769L, + 46341L, 46906L, 47464L, 48015L, 48559L, 49095L, 49624L, 50146L, + 50660L, 51166L, 51665L, 52156L, 52639L, 53114L, 53581L, 54040L, + 54491L, 54934L, 55368L, 55794L, 56212L, 56621L, 57022L, 57414L, + 57798L, 58172L, 58538L, 58896L, 59244L, 59583L, 59914L, 60235L, + 60547L, 60851L, 61145L, 61429L, 61705L, 61971L, 62228L, 62476L, + 62714L, 62943L, 63162L, 63372L, 63572L, 63763L, 63944L, 64115L, + 64277L, 64429L, 64571L, 64704L, 64827L, 64940L, 65043L, 65137L, + 65220L, 65294L, 65358L, 65413L, 65457L, 65492L, 65516L, 65531L +}; + + + +fixed _tan_tbl[256] = +{ + /* precalculated fixed point (16.16) tangents for a half circle (0-127) */ + + 0L, 804L, 1609L, 2414L, 3220L, 4026L, 4834L, 5644L, + 6455L, 7268L, 8083L, 8901L, 9721L, 10545L, 11372L, 12202L, + 13036L, 13874L, 14717L, 15564L, 16416L, 17273L, 18136L, 19005L, + 19880L, 20762L, 21650L, 22546L, 23449L, 24360L, 25280L, 26208L, + 27146L, 28093L, 29050L, 30018L, 30996L, 31986L, 32988L, 34002L, + 35030L, 36071L, 37126L, 38196L, 39281L, 40382L, 41500L, 42636L, + 43790L, 44963L, 46156L, 47369L, 48605L, 49863L, 51145L, 52451L, + 53784L, 55144L, 56532L, 57950L, 59398L, 60880L, 62395L, 63947L, + 65536L, 67165L, 68835L, 70548L, 72308L, 74116L, 75974L, 77887L, + 79856L, 81885L, 83977L, 86135L, 88365L, 90670L, 93054L, 95523L, + 98082L, 100736L, 103493L, 106358L, 109340L, 112447L, 115687L, 119071L, + 122609L, 126314L, 130198L, 134276L, 138564L, 143081L, 147847L, 152884L, + 158218L, 163878L, 169896L, 176309L, 183161L, 190499L, 198380L, 206870L, + 216043L, 225990L, 236817L, 248648L, 261634L, 275959L, 291845L, 309568L, + 329472L, 351993L, 377693L, 407305L, 441808L, 482534L, 531352L, 590958L, + 665398L, 761030L, 888450L, 1066730L,1334016L,1779314L,2669641L,5340086L, + -2147483647L,-5340086L,-2669641L,-1779314L,-1334016L,-1066730L,-888450L,-761030L, + -665398L,-590958L,-531352L,-482534L,-441808L,-407305L,-377693L,-351993L, + -329472L,-309568L,-291845L,-275959L,-261634L,-248648L,-236817L,-225990L, + -216043L,-206870L,-198380L,-190499L,-183161L,-176309L,-169896L,-163878L, + -158218L,-152884L,-147847L,-143081L,-138564L,-134276L,-130198L,-126314L, + -122609L,-119071L,-115687L,-112447L,-109340L,-106358L,-103493L,-100736L, + -98082L, -95523L, -93054L, -90670L, -88365L, -86135L, -83977L, -81885L, + -79856L, -77887L, -75974L, -74116L, -72308L, -70548L, -68835L, -67165L, + -65536L, -63947L, -62395L, -60880L, -59398L, -57950L, -56532L, -55144L, + -53784L, -52451L, -51145L, -49863L, -48605L, -47369L, -46156L, -44963L, + -43790L, -42636L, -41500L, -40382L, -39281L, -38196L, -37126L, -36071L, + -35030L, -34002L, -32988L, -31986L, -30996L, -30018L, -29050L, -28093L, + -27146L, -26208L, -25280L, -24360L, -23449L, -22546L, -21650L, -20762L, + -19880L, -19005L, -18136L, -17273L, -16416L, -15564L, -14717L, -13874L, + -13036L, -12202L, -11372L, -10545L, -9721L, -8901L, -8083L, -7268L, + -6455L, -5644L, -4834L, -4026L, -3220L, -2414L, -1609L, -804L +}; + + + +fixed _acos_tbl[513] = +{ + /* precalculated fixed point (16.16) inverse cosines (-1 to 1) */ + + 0x800000L, 0x7C65C7L, 0x7AE75AL, 0x79C19EL, 0x78C9BEL, 0x77EF25L, 0x772953L, 0x76733AL, + 0x75C991L, 0x752A10L, 0x74930CL, 0x740345L, 0x7379C1L, 0x72F5BAL, 0x72768FL, 0x71FBBCL, + 0x7184D3L, 0x711174L, 0x70A152L, 0x703426L, 0x6FC9B5L, 0x6F61C9L, 0x6EFC36L, 0x6E98D1L, + 0x6E3777L, 0x6DD805L, 0x6D7A5EL, 0x6D1E68L, 0x6CC40BL, 0x6C6B2FL, 0x6C13C1L, 0x6BBDAFL, + 0x6B68E6L, 0x6B1558L, 0x6AC2F5L, 0x6A71B1L, 0x6A217EL, 0x69D251L, 0x698420L, 0x6936DFL, + 0x68EA85L, 0x689F0AL, 0x685465L, 0x680A8DL, 0x67C17DL, 0x67792CL, 0x673194L, 0x66EAAFL, + 0x66A476L, 0x665EE5L, 0x6619F5L, 0x65D5A2L, 0x6591E7L, 0x654EBFL, 0x650C26L, 0x64CA18L, + 0x648890L, 0x64478CL, 0x640706L, 0x63C6FCL, 0x63876BL, 0x63484FL, 0x6309A5L, 0x62CB6AL, + 0x628D9CL, 0x625037L, 0x621339L, 0x61D69FL, 0x619A68L, 0x615E90L, 0x612316L, 0x60E7F7L, + 0x60AD31L, 0x6072C3L, 0x6038A9L, 0x5FFEE3L, 0x5FC56EL, 0x5F8C49L, 0x5F5372L, 0x5F1AE7L, + 0x5EE2A7L, 0x5EAAB0L, 0x5E7301L, 0x5E3B98L, 0x5E0473L, 0x5DCD92L, 0x5D96F3L, 0x5D6095L, + 0x5D2A76L, 0x5CF496L, 0x5CBEF2L, 0x5C898BL, 0x5C545EL, 0x5C1F6BL, 0x5BEAB0L, 0x5BB62DL, + 0x5B81E1L, 0x5B4DCAL, 0x5B19E7L, 0x5AE638L, 0x5AB2BCL, 0x5A7F72L, 0x5A4C59L, 0x5A1970L, + 0x59E6B6L, 0x59B42AL, 0x5981CCL, 0x594F9BL, 0x591D96L, 0x58EBBDL, 0x58BA0EL, 0x588889L, + 0x58572DL, 0x5825FAL, 0x57F4EEL, 0x57C40AL, 0x57934DL, 0x5762B5L, 0x573243L, 0x5701F5L, + 0x56D1CCL, 0x56A1C6L, 0x5671E4L, 0x564224L, 0x561285L, 0x55E309L, 0x55B3ADL, 0x558471L, + 0x555555L, 0x552659L, 0x54F77BL, 0x54C8BCL, 0x549A1BL, 0x546B98L, 0x543D31L, 0x540EE7L, + 0x53E0B9L, 0x53B2A7L, 0x5384B0L, 0x5356D4L, 0x532912L, 0x52FB6BL, 0x52CDDDL, 0x52A068L, + 0x52730CL, 0x5245C9L, 0x52189EL, 0x51EB8BL, 0x51BE8FL, 0x5191AAL, 0x5164DCL, 0x513825L, + 0x510B83L, 0x50DEF7L, 0x50B280L, 0x50861FL, 0x5059D2L, 0x502D99L, 0x500175L, 0x4FD564L, + 0x4FA967L, 0x4F7D7DL, 0x4F51A6L, 0x4F25E2L, 0x4EFA30L, 0x4ECE90L, 0x4EA301L, 0x4E7784L, + 0x4E4C19L, 0x4E20BEL, 0x4DF574L, 0x4DCA3AL, 0x4D9F10L, 0x4D73F6L, 0x4D48ECL, 0x4D1DF1L, + 0x4CF305L, 0x4CC829L, 0x4C9D5AL, 0x4C729AL, 0x4C47E9L, 0x4C1D45L, 0x4BF2AEL, 0x4BC826L, + 0x4B9DAAL, 0x4B733BL, 0x4B48D9L, 0x4B1E84L, 0x4AF43BL, 0x4AC9FEL, 0x4A9FCDL, 0x4A75A7L, + 0x4A4B8DL, 0x4A217EL, 0x49F77AL, 0x49CD81L, 0x49A393L, 0x4979AFL, 0x494FD5L, 0x492605L, + 0x48FC3FL, 0x48D282L, 0x48A8CFL, 0x487F25L, 0x485584L, 0x482BECL, 0x48025DL, 0x47D8D6L, + 0x47AF57L, 0x4785E0L, 0x475C72L, 0x47330AL, 0x4709ABL, 0x46E052L, 0x46B701L, 0x468DB7L, + 0x466474L, 0x463B37L, 0x461201L, 0x45E8D0L, 0x45BFA6L, 0x459682L, 0x456D64L, 0x45444BL, + 0x451B37L, 0x44F229L, 0x44C920L, 0x44A01CL, 0x44771CL, 0x444E21L, 0x44252AL, 0x43FC38L, + 0x43D349L, 0x43AA5FL, 0x438178L, 0x435894L, 0x432FB4L, 0x4306D8L, 0x42DDFEL, 0x42B527L, + 0x428C53L, 0x426381L, 0x423AB2L, 0x4211E5L, 0x41E91AL, 0x41C051L, 0x41978AL, 0x416EC5L, + 0x414601L, 0x411D3EL, 0x40F47CL, 0x40CBBBL, 0x40A2FBL, 0x407A3CL, 0x40517DL, 0x4028BEL, + 0x400000L, 0x3FD742L, 0x3FAE83L, 0x3F85C4L, 0x3F5D05L, 0x3F3445L, 0x3F0B84L, 0x3EE2C2L, + 0x3EB9FFL, 0x3E913BL, 0x3E6876L, 0x3E3FAFL, 0x3E16E6L, 0x3DEE1BL, 0x3DC54EL, 0x3D9C7FL, + 0x3D73ADL, 0x3D4AD9L, 0x3D2202L, 0x3CF928L, 0x3CD04CL, 0x3CA76CL, 0x3C7E88L, 0x3C55A1L, + 0x3C2CB7L, 0x3C03C8L, 0x3BDAD6L, 0x3BB1DFL, 0x3B88E4L, 0x3B5FE4L, 0x3B36E0L, 0x3B0DD7L, + 0x3AE4C9L, 0x3ABBB5L, 0x3A929CL, 0x3A697EL, 0x3A405AL, 0x3A1730L, 0x39EDFFL, 0x39C4C9L, + 0x399B8CL, 0x397249L, 0x3948FFL, 0x391FAEL, 0x38F655L, 0x38CCF6L, 0x38A38EL, 0x387A20L, + 0x3850A9L, 0x38272AL, 0x37FDA3L, 0x37D414L, 0x37AA7CL, 0x3780DBL, 0x375731L, 0x372D7EL, + 0x3703C1L, 0x36D9FBL, 0x36B02BL, 0x368651L, 0x365C6DL, 0x36327FL, 0x360886L, 0x35DE82L, + 0x35B473L, 0x358A59L, 0x356033L, 0x353602L, 0x350BC5L, 0x34E17CL, 0x34B727L, 0x348CC5L, + 0x346256L, 0x3437DAL, 0x340D52L, 0x33E2BBL, 0x33B817L, 0x338D66L, 0x3362A6L, 0x3337D7L, + 0x330CFBL, 0x32E20FL, 0x32B714L, 0x328C0AL, 0x3260F0L, 0x3235C6L, 0x320A8CL, 0x31DF42L, + 0x31B3E7L, 0x31887CL, 0x315CFFL, 0x313170L, 0x3105D0L, 0x30DA1EL, 0x30AE5AL, 0x308283L, + 0x305699L, 0x302A9CL, 0x2FFE8BL, 0x2FD267L, 0x2FA62EL, 0x2F79E1L, 0x2F4D80L, 0x2F2109L, + 0x2EF47DL, 0x2EC7DBL, 0x2E9B24L, 0x2E6E56L, 0x2E4171L, 0x2E1475L, 0x2DE762L, 0x2DBA37L, + 0x2D8CF4L, 0x2D5F98L, 0x2D3223L, 0x2D0495L, 0x2CD6EEL, 0x2CA92CL, 0x2C7B50L, 0x2C4D59L, + 0x2C1F47L, 0x2BF119L, 0x2BC2CFL, 0x2B9468L, 0x2B65E5L, 0x2B3744L, 0x2B0885L, 0x2AD9A7L, + 0x2AAAABL, 0x2A7B8FL, 0x2A4C53L, 0x2A1CF7L, 0x29ED7BL, 0x29BDDCL, 0x298E1CL, 0x295E3AL, + 0x292E34L, 0x28FE0BL, 0x28CDBDL, 0x289D4BL, 0x286CB3L, 0x283BF6L, 0x280B12L, 0x27DA06L, + 0x27A8D3L, 0x277777L, 0x2745F2L, 0x271443L, 0x26E26AL, 0x26B065L, 0x267E34L, 0x264BD6L, + 0x26194AL, 0x25E690L, 0x25B3A7L, 0x25808EL, 0x254D44L, 0x2519C8L, 0x24E619L, 0x24B236L, + 0x247E1FL, 0x2449D3L, 0x241550L, 0x23E095L, 0x23ABA2L, 0x237675L, 0x23410EL, 0x230B6AL, + 0x22D58AL, 0x229F6BL, 0x22690DL, 0x22326EL, 0x21FB8DL, 0x21C468L, 0x218CFFL, 0x215550L, + 0x211D59L, 0x20E519L, 0x20AC8EL, 0x2073B7L, 0x203A92L, 0x20011DL, 0x1FC757L, 0x1F8D3DL, + 0x1F52CFL, 0x1F1809L, 0x1EDCEAL, 0x1EA170L, 0x1E6598L, 0x1E2961L, 0x1DECC7L, 0x1DAFC9L, + 0x1D7264L, 0x1D3496L, 0x1CF65BL, 0x1CB7B1L, 0x1C7895L, 0x1C3904L, 0x1BF8FAL, 0x1BB874L, + 0x1B7770L, 0x1B35E8L, 0x1AF3DAL, 0x1AB141L, 0x1A6E19L, 0x1A2A5EL, 0x19E60BL, 0x19A11BL, + 0x195B8AL, 0x191551L, 0x18CE6CL, 0x1886D4L, 0x183E83L, 0x17F573L, 0x17AB9BL, 0x1760F6L, + 0x17157BL, 0x16C921L, 0x167BE0L, 0x162DAFL, 0x15DE82L, 0x158E4FL, 0x153D0BL, 0x14EAA8L, + 0x14971AL, 0x144251L, 0x13EC3FL, 0x1394D1L, 0x133BF5L, 0x12E198L, 0x1285A2L, 0x1227FBL, + 0x11C889L, 0x11672FL, 0x1103CAL, 0x109E37L, 0x10364BL, 0xFCBDAL, 0xF5EAEL, 0xEEE8CL, + 0xE7B2DL, 0xE0444L, 0xD8971L, 0xD0A46L, 0xC863FL, 0xBFCBBL, 0xB6CF4L, 0xAD5F0L, + 0xA366FL, 0x98CC6L, 0x8D6ADL, 0x810DBL, 0x73642L, 0x63E62L, 0x518A6L, 0x39A39L, + 0x0L +}; + + + +/* fixatan: + * Fixed point inverse tangent. Does a binary search on the tan table. + */ +fixed fixatan(fixed x) +{ + int a, b, c; /* for binary search */ + fixed d; /* difference value for search */ + + if (x >= 0) { /* search the first part of tan table */ + a = 0; + b = 127; + } + else { /* search the second half instead */ + a = 128; + b = 255; + } + + do { + c = (a + b) >> 1; + d = x - _tan_tbl[c]; + + if (d > 0) + a = c + 1; + else + if (d < 0) + b = c - 1; + + } while ((a <= b) && (d)); + + if (x >= 0) + return ((long)c) << 15; + + return (-0x00800000L + (((long)c) << 15)); +} + + + +/* fixatan2: + * Like the libc atan2, but for fixed point numbers. + */ +fixed fixatan2(fixed y, fixed x) +{ + fixed r; + + if (x==0) { + if (y==0) { + *allegro_errno = EDOM; + return 0L; + } + else + return ((y < 0) ? -0x00400000L : 0x00400000L); + } + + *allegro_errno = 0; + r = fixdiv(y, x); + + if (*allegro_errno) { + *allegro_errno = 0; + return ((y < 0) ? -0x00400000L : 0x00400000L); + } + + r = fixatan(r); + + if (x >= 0) + return r; + + if (y >= 0) + return 0x00800000L + r; + + return r - 0x00800000L; +} + + + +/* fixtorad_r, radtofix_r: + * Ratios for converting between radians and fixed point angles. + */ +AL_CONST fixed fixtorad_r = (fixed)1608; /* 2pi/256 */ +AL_CONST fixed radtofix_r = (fixed)2670177; /* 256/2pi */ + + + +#if (defined ALLEGRO_I386) && (!defined ALLEGRO_NO_ASM) + + + +unsigned short _sqrt_table[256] = +{ + /* this table is used by the fixsqrt() and fixhypot() routines in imisc.s */ + + 0x2D4, 0x103F, 0x16CD, 0x1BDB, 0x201F, 0x23E3, 0x274B, 0x2A6D, + 0x2D57, 0x3015, 0x32AC, 0x3524, 0x377F, 0x39C2, 0x3BEE, 0x3E08, + 0x400F, 0x4207, 0x43F0, 0x45CC, 0x479C, 0x4960, 0x4B19, 0x4CC9, + 0x4E6F, 0x500C, 0x51A2, 0x532F, 0x54B6, 0x5635, 0x57AE, 0x5921, + 0x5A8D, 0x5BF4, 0x5D56, 0x5EB3, 0x600A, 0x615D, 0x62AB, 0x63F5, + 0x653B, 0x667D, 0x67BA, 0x68F5, 0x6A2B, 0x6B5E, 0x6C8D, 0x6DBA, + 0x6EE3, 0x7009, 0x712C, 0x724C, 0x7369, 0x7484, 0x759C, 0x76B1, + 0x77C4, 0x78D4, 0x79E2, 0x7AEE, 0x7BF7, 0x7CFE, 0x7E04, 0x7F07, + 0x8007, 0x8106, 0x8203, 0x82FF, 0x83F8, 0x84EF, 0x85E5, 0x86D9, + 0x87CB, 0x88BB, 0x89AA, 0x8A97, 0x8B83, 0x8C6D, 0x8D56, 0x8E3D, + 0x8F22, 0x9007, 0x90E9, 0x91CB, 0x92AB, 0x938A, 0x9467, 0x9543, + 0x961E, 0x96F8, 0x97D0, 0x98A8, 0x997E, 0x9A53, 0x9B26, 0x9BF9, + 0x9CCA, 0x9D9B, 0x9E6A, 0x9F39, 0xA006, 0xA0D2, 0xA19D, 0xA268, + 0xA331, 0xA3F9, 0xA4C1, 0xA587, 0xA64D, 0xA711, 0xA7D5, 0xA898, + 0xA95A, 0xAA1B, 0xAADB, 0xAB9A, 0xAC59, 0xAD16, 0xADD3, 0xAE8F, + 0xAF4B, 0xB005, 0xB0BF, 0xB178, 0xB230, 0xB2E8, 0xB39F, 0xB455, + 0xB50A, 0xB5BF, 0xB673, 0xB726, 0xB7D9, 0xB88A, 0xB93C, 0xB9EC, + 0xBA9C, 0xBB4B, 0xBBFA, 0xBCA8, 0xBD55, 0xBE02, 0xBEAE, 0xBF5A, + 0xC005, 0xC0AF, 0xC159, 0xC202, 0xC2AB, 0xC353, 0xC3FA, 0xC4A1, + 0xC548, 0xC5ED, 0xC693, 0xC737, 0xC7DC, 0xC87F, 0xC923, 0xC9C5, + 0xCA67, 0xCB09, 0xCBAA, 0xCC4B, 0xCCEB, 0xCD8B, 0xCE2A, 0xCEC8, + 0xCF67, 0xD004, 0xD0A2, 0xD13F, 0xD1DB, 0xD277, 0xD312, 0xD3AD, + 0xD448, 0xD4E2, 0xD57C, 0xD615, 0xD6AE, 0xD746, 0xD7DE, 0xD876, + 0xD90D, 0xD9A4, 0xDA3A, 0xDAD0, 0xDB66, 0xDBFB, 0xDC90, 0xDD24, + 0xDDB8, 0xDE4C, 0xDEDF, 0xDF72, 0xE004, 0xE096, 0xE128, 0xE1B9, + 0xE24A, 0xE2DB, 0xE36B, 0xE3FB, 0xE48B, 0xE51A, 0xE5A9, 0xE637, + 0xE6C5, 0xE753, 0xE7E1, 0xE86E, 0xE8FB, 0xE987, 0xEA13, 0xEA9F, + 0xEB2B, 0xEBB6, 0xEC41, 0xECCB, 0xED55, 0xEDDF, 0xEE69, 0xEEF2, + 0xEF7B, 0xF004, 0xF08C, 0xF114, 0xF19C, 0xF223, 0xF2AB, 0xF332, + 0xF3B8, 0xF43E, 0xF4C4, 0xF54A, 0xF5D0, 0xF655, 0xF6DA, 0xF75E, + 0xF7E3, 0xF867, 0xF8EA, 0xF96E, 0xF9F1, 0xFA74, 0xFAF7, 0xFB79, + 0xFBFB, 0xFC7D, 0xFCFF, 0xFD80, 0xFE02, 0xFE82, 0xFF03, 0xFF83 +}; + + + +#else /* not i386, so use straight C versions */ + + + +/* fixsqrt: + * Fixed point square root routine for non-i386. + */ +fixed fixsqrt(fixed x) +{ + if (x > 0) + return ftofix(sqrt(fixtof(x))); + + if (x < 0) + *allegro_errno = EDOM; + + return 0; +} + + + +/* fixhypot: + * Fixed point sqrt (x*x+y*y) for non-i386. + */ +fixed fixhypot(fixed x, fixed y) +{ + return ftofix(hypot(fixtof(x), fixtof(y))); +} + + + +#endif /* i386 vs. portable C implementations */ + diff --git a/libsrc/allegro/src/pcx.c b/libsrc/allegro/src/pcx.c new file mode 100644 index 00000000000..387ffe99bf9 --- /dev/null +++ b/libsrc/allegro/src/pcx.c @@ -0,0 +1,346 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * PCX reader. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* load_pcx: + * Loads a 256 color PCX file, returning a bitmap structure and storing + * the palette data in the specified palette (this should be an array of + * at least 256 RGB structures). + */ +BITMAP *load_pcx(AL_CONST char *filename, RGB *pal) +{ + PACKFILE *f; + BITMAP *bmp; + ASSERT(filename); + + f = pack_fopen(filename, F_READ); + if (!f) + return NULL; + + bmp = load_pcx_pf(f, pal); + + pack_fclose(f); + + return bmp; +} + + + +/* load_pcx_pf: + * Like load_pcx, but starts loading from the current place in the PACKFILE + * specified. If successful the offset into the file will be left just after + * the image data. If unsuccessful the offset into the file is unspecified, + * i.e. you must either reset the offset to some known place or close the + * packfile. The packfile is not closed by this function. + */ +BITMAP *load_pcx_pf(PACKFILE *f, RGB *pal) +{ + BITMAP *b; + PALETTE tmppal; + int want_palette = TRUE; + int c; + int width, height; + int bpp, bytes_per_line; + int xx, po; + int x, y; + char ch; + int dest_depth; + ASSERT(f); + + /* we really need a palette */ + if (!pal) { + want_palette = FALSE; + pal = tmppal; + } + + pack_getc(f); /* skip manufacturer ID */ + pack_getc(f); /* skip version flag */ + pack_getc(f); /* skip encoding flag */ + + if (pack_getc(f) != 8) { /* we like 8 bit color planes */ + return NULL; + } + + width = -(pack_igetw(f)); /* xmin */ + height = -(pack_igetw(f)); /* ymin */ + width += pack_igetw(f) + 1; /* xmax */ + height += pack_igetw(f) + 1; /* ymax */ + + pack_igetl(f); /* skip DPI values */ + + for (c=0; c<16; c++) { /* read the 16 color palette */ + pal[c].r = pack_getc(f) / 4; + pal[c].g = pack_getc(f) / 4; + pal[c].b = pack_getc(f) / 4; + } + + pack_getc(f); + + bpp = pack_getc(f) * 8; /* how many color planes? */ + if ((bpp != 8) && (bpp != 24)) { + return NULL; + } + + dest_depth = _color_load_depth(bpp, FALSE); + bytes_per_line = pack_igetw(f); + + for (c=0; c<60; c++) /* skip some more junk */ + pack_getc(f); + + b = create_bitmap_ex(bpp, width, height); + if (!b) { + return NULL; + } + + *allegro_errno = 0; + + for (y=0; yw) + b->line[y][x] = ch; + x++; + } + } + else { + while (c--) { + if (xx < b->w) + b->line[y][xx*3+po] = ch; + x++; + if (x == bytes_per_line) { + xx = 0; +#ifdef ALLEGRO_LITTLE_ENDIAN + po = _rgb_g_shift_24/8; +#elif defined ALLEGRO_BIG_ENDIAN + po = 2 - _rgb_g_shift_24/8; +#elif !defined SCAN_DEPEND + #error endianess not defined +#endif + } + else if (x == bytes_per_line*2) { + xx = 0; +#ifdef ALLEGRO_LITTLE_ENDIAN + po = _rgb_b_shift_24/8; +#elif defined ALLEGRO_BIG_ENDIAN + po = 2 - _rgb_b_shift_24/8; +#elif !defined SCAN_DEPEND + #error endianess not defined +#endif + } + else + xx++; + } + } + } + } + + if (bpp == 8) { /* look for a 256 color palette */ + while ((c = pack_getc(f)) != EOF) { + if (c == 12) { + for (c=0; c<256; c++) { + pal[c].r = pack_getc(f) / 4; + pal[c].g = pack_getc(f) / 4; + pal[c].b = pack_getc(f) / 4; + } + break; + } + } + } + + if (*allegro_errno) { + destroy_bitmap(b); + return NULL; + } + + if (dest_depth != bpp) { + /* restore original palette except if it comes from the bitmap */ + if ((bpp != 8) && (!want_palette)) + pal = NULL; + + b = _fixup_loaded_bitmap(b, pal, dest_depth); + } + + /* construct a fake palette if 8-bit mode is not involved */ + if ((bpp != 8) && (dest_depth != 8) && want_palette) + generate_332_palette(pal); + + return b; +} + + + +/* save_pcx: + * Writes a bitmap into a PCX file, using the specified palette (this + * should be an array of at least 256 RGB structures). + */ +int save_pcx(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) +{ + PACKFILE *f; + int ret; + ASSERT(filename); + + f = pack_fopen(filename, F_WRITE); + if (!f) + return -1; + + ret = save_pcx_pf(f, bmp, pal); + + pack_fclose(f); + + return ret; +} + + + +/* save_pcx_pf: + * Like save_pcx but writes into the PACKFILE given instead of a new file. + * The packfile is not closed after writing is completed. On success the + * offset into the file is left after the TGA file just written. On failure + * the offset is left at the end of whatever incomplete data was written. + */ +int save_pcx_pf(PACKFILE *f, BITMAP *bmp, AL_CONST RGB *pal) +{ + PALETTE tmppal; + int c; + int x, y; + int runcount; + int depth, planes; + char runchar; + char ch; + ASSERT(f); + ASSERT(bmp); + + if (!pal) { + get_palette(tmppal); + pal = tmppal; + } + + depth = bitmap_color_depth(bmp); + if (depth == 8) + planes = 1; + else + planes = 3; + + *allegro_errno = 0; + + pack_putc(10, f); /* manufacturer */ + pack_putc(5, f); /* version */ + pack_putc(1, f); /* run length encoding */ + pack_putc(8, f); /* 8 bits per pixel */ + pack_iputw(0, f); /* xmin */ + pack_iputw(0, f); /* ymin */ + pack_iputw(bmp->w-1, f); /* xmax */ + pack_iputw(bmp->h-1, f); /* ymax */ + pack_iputw(320, f); /* HDpi */ + pack_iputw(200, f); /* VDpi */ + + for (c=0; c<16; c++) { + pack_putc(_rgb_scale_6[pal[c].r], f); + pack_putc(_rgb_scale_6[pal[c].g], f); + pack_putc(_rgb_scale_6[pal[c].b], f); + } + + pack_putc(0, f); /* reserved */ + pack_putc(planes, f); /* one or three color planes */ + pack_iputw(bmp->w, f); /* number of bytes per scanline */ + pack_iputw(1, f); /* color palette */ + pack_iputw(bmp->w, f); /* hscreen size */ + pack_iputw(bmp->h, f); /* vscreen size */ + for (c=0; c<54; c++) /* filler */ + pack_putc(0, f); + + for (y=0; yh; y++) { /* for each scanline... */ + runcount = 0; + runchar = 0; + for (x=0; xw*planes; x++) { /* for each pixel... */ + if (depth == 8) { + ch = getpixel(bmp, x, y); + } + else { + if (xw) { + c = getpixel(bmp, x, y); + ch = getr_depth(depth, c); + } + else if (xw*2) { + c = getpixel(bmp, x-bmp->w, y); + ch = getg_depth(depth, c); + } + else { + c = getpixel(bmp, x-bmp->w*2, y); + ch = getb_depth(depth, c); + } + } + if (runcount==0) { + runcount = 1; + runchar = ch; + } + else { + if ((ch != runchar) || (runcount >= 0x3f)) { + if ((runcount > 1) || ((runchar & 0xC0) == 0xC0)) + pack_putc(0xC0 | runcount, f); + pack_putc(runchar,f); + runcount = 1; + runchar = ch; + } + else + runcount++; + } + } + if ((runcount > 1) || ((runchar & 0xC0) == 0xC0)) + pack_putc(0xC0 | runcount, f); + pack_putc(runchar,f); + } + + if (depth == 8) { /* 256 color palette */ + pack_putc(12, f); + + for (c=0; c<256; c++) { + pack_putc(_rgb_scale_6[pal[c].r], f); + pack_putc(_rgb_scale_6[pal[c].g], f); + pack_putc(_rgb_scale_6[pal[c].b], f); + } + } + + if (*allegro_errno) + return -1; + else + return 0; +} + diff --git a/libsrc/allegro/src/polygon.c b/libsrc/allegro/src/polygon.c new file mode 100644 index 00000000000..3808f5f7def --- /dev/null +++ b/libsrc/allegro/src/polygon.c @@ -0,0 +1,274 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * The 2d polygon rasteriser. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* fill_edge_structure: + * Polygon helper function: initialises an edge structure for the 2d + * rasteriser. + */ +static void fill_edge_structure(POLYGON_EDGE *edge, AL_CONST int *i1, AL_CONST int *i2) +{ + if (i2[1] < i1[1]) { + AL_CONST int *it; + + it = i1; + i1 = i2; + i2 = it; + } + + edge->top = i1[1]; + edge->bottom = i2[1]; + edge->x = (i1[0] << POLYGON_FIX_SHIFT) + (1 << (POLYGON_FIX_SHIFT-1)); + if (i2[1] != i1[1]) { + edge->dx = ((i2[0] - i1[0]) << POLYGON_FIX_SHIFT) / (i2[1] - i1[1]); + } + else { + edge->dx = ((i2[0] - i1[0]) << POLYGON_FIX_SHIFT) << 1; + } + edge->w = MAX(ABS(edge->dx)-1, 0); + edge->prev = NULL; + edge->next = NULL; + if (edge->dx < 0) + edge->x += edge->dx/2 ; +} + + + +/* _add_edge: + * Adds an edge structure to a linked list, returning the new head pointer. + */ +POLYGON_EDGE *_add_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x) +{ + POLYGON_EDGE *pos = list; + POLYGON_EDGE *prev = NULL; + + if (sort_by_x) { + while ((pos) && (pos->x < edge->x)) { + prev = pos; + pos = pos->next; + } + } + else { + while ((pos) && (pos->top < edge->top)) { + prev = pos; + pos = pos->next; + } + } + + edge->next = pos; + edge->prev = prev; + + if (pos) + pos->prev = edge; + + if (prev) { + prev->next = edge; + return list; + } + else + return edge; +} + + + +/* _remove_edge: + * Removes an edge structure from a list, returning the new head pointer. + */ +POLYGON_EDGE *_remove_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge) +{ + if (edge->next) + edge->next->prev = edge->prev; + + if (edge->prev) { + edge->prev->next = edge->next; + return list; + } + else + return edge->next; +} + + + +/* polygon: + * Draws a filled polygon with an arbitrary number of corners. Pass the + * number of vertices, then an array containing a series of x, y points + * (a total of vertices*2 values). + */ +void _soft_polygon(BITMAP *bmp, int vertices, AL_CONST int *points, int color) +{ + int c; + int top = INT_MAX; + int bottom = INT_MIN; + AL_CONST int *i1, *i2; + POLYGON_EDGE *edge, *next_edge; + POLYGON_EDGE *active_edges = NULL; + POLYGON_EDGE *inactive_edges = NULL; + ASSERT(bmp); + + /* allocate some space and fill the edge table */ + _grow_scratch_mem(sizeof(POLYGON_EDGE) * vertices); + + edge = (POLYGON_EDGE *)_scratch_mem; + i1 = points; + i2 = points + (vertices-1) * 2; + + for (c=0; cbottom >= edge->top) { + + if (edge->top < top) + top = edge->top; + + if (edge->bottom > bottom) + bottom = edge->bottom; + + inactive_edges = _add_edge(inactive_edges, edge, FALSE); + edge++; + } + + i2 = i1; + i1 += 2; + } + + if (bottom >= bmp->cb) + bottom = bmp->cb-1; + + acquire_bitmap(bmp); + + /* for each scanline in the polygon... */ + for (c=top; c<=bottom; c++) { + int hid = 0; + int b1 = 0; + int e1 = 0; + int up = 0; + int draw = 0; + int e; + + /* check for newly active edges */ + edge = inactive_edges; + while ((edge) && (edge->top == c)) { + next_edge = edge->next; + inactive_edges = _remove_edge(inactive_edges, edge); + active_edges = _add_edge(active_edges, edge, TRUE); + edge = next_edge; + } + + /* draw horizontal line segments */ + edge = active_edges; + while (edge) { + e = edge->w; + if (edge->bottom != c) { + up = 1 - up; + } + else { + e = edge->w >> 1; + } + + if (edge->top == c) { + e = edge->w >> 1; + } + + if ((draw < 1) && (up >= 1)) { + b1 = (edge->x + e) >> POLYGON_FIX_SHIFT; + } + else if (draw >= 1) { + /* filling the polygon */ + e1 = edge->x >> POLYGON_FIX_SHIFT; + hid = MAX(hid, b1 + 1); + + if (hid <= e1-1) { + bmp->vtable->hfill(bmp, hid, c, e1-1, color); + } + + b1 = (edge->x + e) >> POLYGON_FIX_SHIFT; + } + + /* drawing the edge */ + hid = MAX(hid, edge->x >> POLYGON_FIX_SHIFT); + if (hid <= ((edge->x + e) >> POLYGON_FIX_SHIFT)) { + bmp->vtable->hfill(bmp, hid, c, (edge->x + e) >> POLYGON_FIX_SHIFT, color); + hid = 1 + ((edge->x + e) >> POLYGON_FIX_SHIFT); + } + + edge = edge->next; + draw = up; + } + + /* update edges, sorting and removing dead ones */ + edge = active_edges; + while (edge) { + next_edge = edge->next; + if (c >= edge->bottom) { + active_edges = _remove_edge(active_edges, edge); + } + else { + edge->x += edge->dx; + if ((edge->top == c) && (edge->dx > 0)) { + edge->x -= edge->dx/2; + } + if ((edge->bottom == c+1) && (edge->dx < 0)) { + edge->x -= edge->dx/2; + } + while ((edge->prev) && (edge->x < edge->prev->x)) { + if (edge->next) + edge->next->prev = edge->prev; + edge->prev->next = edge->next; + edge->next = edge->prev; + edge->prev = edge->prev->prev; + edge->next->prev = edge; + if (edge->prev) + edge->prev->next = edge; + else + active_edges = edge; + } + } + edge = next_edge; + } + } + + release_bitmap(bmp); +} + + + +/* triangle: + * Draws a filled triangle between the three points. + */ +void _soft_triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) +{ + ASSERT(bmp); + + { + /* portable version for other platforms */ + int point[6]; + + point[0] = x1; point[1] = y1; + point[2] = x2; point[3] = y2; + point[4] = x3; point[5] = y3; + + polygon(bmp, 3, point, color); + } +} + diff --git a/libsrc/allegro/src/quantize.c b/libsrc/allegro/src/quantize.c new file mode 100644 index 00000000000..ea7458c0bb8 --- /dev/null +++ b/libsrc/allegro/src/quantize.c @@ -0,0 +1,522 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Optimised palette generation routines. + * + * By Michal Mertl. + * + * Portability improvements and bugfixes by Michael Bukin. + * + * See readme.txt for copyright information. + * + * The algorithm used here is my own, because the ones I found + * on the net seemed too complex for me :-) First I just count the + * number of pixels of the same color (the number of different colors + * is for 24/32bpp significantly reduced by using only 4(5) bits per + * RGB). Than I sort the list with the most used colors first. Most + * of the palette is just copy of this list and the rest (very + * important in fact) is generated by comparing colors one by one + * with each other inserting to the palette the most different ones. + * + * The vast majority of the time spent in the routine is in initial + * counting (looking up items in hashtable), so the smaller the number + * of colors the faster the result. For example on my computer (P100) + * with 800/600 32bpp image and 4 bits per RGB it takes about 590ms + * and with 5 bits per RGB about 5100ms. + */ + + +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#define DEFAULT_PREC 4 +#define DEFAULT_FRACTION 5 +#define DEFAULT_MAXSWAPS 16 +#define DEFAULT_MINDIFF 9 + + +/* the number of lists, prime number */ +#define HASHTABLESIZE 1031 + + +typedef struct NODE { + struct NODE *next; + int color, count; +} NODE; + + +typedef struct { + int color, key; +} ITEM; + + +static int distinct; +static NODE *hash_table; + + + +static void delete_list(NODE *list) +{ + NODE *node, *next; + + for (node = list; node != NULL; node = next) { + next = node->next; + _AL_FREE (node); + } +} + + + +static void insert_node(int color) +{ + NODE *p; + + p = &hash_table[color % HASHTABLESIZE]; + + for (;;) { + if (p->color == color) { + /* this node (e.g. the color was already filled) */ + p->count++; + return; + } + if (p->next) + p = p->next; + else + break; + } + + /* new color */ + if (p->count) { + p->next = _AL_MALLOC(sizeof(NODE)); + p = p->next; + } + if (p != NULL) { + p->color = color; + p->count = 1; + p->next = NULL; + distinct++; + } +} + + + +/* helper function for builtin qsort function */ +static int qsort_helper_ITEM(AL_CONST void *e1, AL_CONST void *e2) +{ + return ((ITEM *)e2)->key - ((ITEM *)e1)->key; +} + + + +/* compare two color values */ +static INLINE int compare_cols(int col1, int col2) +{ + int b = ((col1 >> 16) & 0xFF) - ((col2 >> 16) & 0xFF); + int g = ((col1 >> 8) & 0xFF) - ((col2 >> 8) & 0xFF); + int r = ((col1 & 0xFF) - (col2 & 0xFF)); + return (((r < 0) ? -r : r) + ((g < 0) ? -g : g) + ((b < 0) ? -b : b)); +} + + + +/* Searches the array from 'item'th field comparing any pair of items. + * Fills 'key' field of all items >= 'item'th with the difference + * value (the smallest difference between the checked color and all + * already used). Than only the last added item has to be compared with + * all other not yet added colors, what is performed afterwards. + */ +static void optimize_colors(ITEM *array, int item, int palsize, int length, int mindiff) +{ + int i, j, best, curbest, bestpos, t; + + /* iterate through the array comparing any item behind 'item' */ + for (i=item; i best) { + best = array[j].key; + bestpos = j; + } + } + } + } +} + + + +/* searches the array of length for the color */ +static INLINE int no_such_color(ITEM *array, int length, int color, int mask) +{ + int i; + + for (i=0; ir = (color & 0xFF); + rgb->g = (color >> 8) & 0xFF; + rgb->b = (color >> 16) & 0xFF; +} + + + +/* generate_optimized_palette_ex: + * Calculates a suitable palette for color reducing the specified truecolor + * image. If the rsvdcols parameter is not NULL, it contains an array of + * 256 flags. If rsvdcols[n] > 0 the palette entry is assumed to be already + * set so I count with it. If rsvdcols[n] < 0 I mustn't assume anything about + * the entry. If rsvdcols[n] == 0 the entry is free for me to change. + * + * Variable fraction controls, how big part of the palette should be + * filled with 'different colors', maxswaps gives upper boundary for + * number of swaps and mindiff chooses when to stop replacing values + */ +static int generate_optimized_palette_ex(BITMAP *image, PALETTE pal, AL_CONST signed char *rsvdcols, int bitsperrgb, int fraction, int maxswaps, int mindiff) +{ + int i, j, x, y, imgdepth, numcols, palsize, rsvdcnt=0, rsvduse=0; + unsigned int prec_mask, prec_mask2, bitmask15, bitmask16, bitmask24; + signed char tmprsvd[256]; + int rshift, gshift, bshift; + ITEM *colors; + + switch (bitsperrgb) { + + case 4: + prec_mask = 0x3C3C3C; + prec_mask2 = 0; + bitmask15 = 0x7BDE; /* 0111 1011 1101 1110 */ + bitmask16 = 0xF79E; /* 1111 0111 1001 1110 */ + bitmask24 = 0xF0F0F0; + break; + + case 5: + prec_mask = 0x3E3E3E; + prec_mask2 = 0x3C3C3C; + bitmask15 = 0x7FFF; /* 0111 1111 1111 1111 */ + bitmask16 = 0xFFDF; /* 1111 1111 1101 1111 */ + bitmask24 = 0xF8F8F8; + break; + + default: + return -1; + } + + distinct = 0; + + imgdepth = bitmap_color_depth(image); + if (imgdepth == 8) + return 0; + + hash_table = _AL_MALLOC(HASHTABLESIZE * sizeof(NODE)); + if (hash_table == NULL) + return 0; + + for (i = 0; i < HASHTABLESIZE; i++) { + hash_table[i].next = NULL; + hash_table[i].color = -1; + hash_table[i].count = 0; + } + + /* count the number of colors we shouldn't modify */ + if (rsvdcols) { + for (i=0; i<256; i++) { + if (rsvdcols[i]) { + rsvdcnt++; + if (rsvdcols[i] > 0) + rsvduse++; + } + } + } + else { + pal[0].r = 63; + pal[0].g = 0; + pal[0].b = 63; + + tmprsvd[0] = 1; + rsvdcnt++; + rsvduse++; + + for (i=1; i<256; i++) + tmprsvd[i] = 0; + + rsvdcols = tmprsvd; + } + + /* fix palette */ + for (i = 0; i < 256; i++) { + pal[i].r &= 0x3F; + pal[i].g &= 0x3F; + pal[i].b &= 0x3F; + } + + /* fill the 'hash_table' with 4bit per RGB color values */ + bmp_select(image); + + switch (imgdepth) { + + case 32: + for (y=0; yh; y++) + for (x=0; xw; x++) + insert_node(bmp_read32((uintptr_t)image->line[y]+x*sizeof(int32_t)) & bitmask24); + break; + + case 24: + for (y=0; yh; y++) + for (x=0; xw; x++) + insert_node(bmp_read24((uintptr_t)image->line[y]+x*3) & bitmask24); + break; + + case 16: + for (y=0; yh; y++) + for (x=0; xw; x++) + insert_node(bmp_read16((uintptr_t)image->line[y]+x*sizeof(short)) & bitmask16); + break; + + case 15: + for (y=0; yh; y++) + for (x=0; xw; x++) + insert_node(bmp_read15((uintptr_t)image->line[y]+x*sizeof(short)) & bitmask15); + break; + + default: + return -1; + } + + /* convert the 'hash_table' to array 'colors' */ + colors = _AL_MALLOC((rsvduse + distinct) * sizeof(ITEM)); + if (colors == NULL) { + _AL_FREE(hash_table); + return 0; + } + + for (i = 0, j = rsvduse; icolor; + colors[j++].key = node->count; + node = node->next; + } while (node != NULL); + + if (hash_table[i].next) + delete_list(hash_table[i].next); + } + } + + _AL_FREE(hash_table); + + /* sort the list with biggest count first */ + qsort(colors + rsvduse, distinct, sizeof(ITEM), qsort_helper_ITEM); + + /* we don't want to deal anymore with colors that are seldomly(?) used */ + numcols = rsvduse + distinct; + palsize = 256 - rsvdcnt + rsvduse; + + /* change the format of the color information to some faster one + * (in fact to the 00BBBB?0 00GGGG?0 00RRRR?0). + */ + + switch (imgdepth) { + + case 32: + rshift = _rgb_r_shift_32 + 3; + gshift = _rgb_g_shift_32 + 3; + bshift = _rgb_b_shift_32 + 3; + break; + + case 24: + rshift = _rgb_r_shift_24 + 3; + gshift = _rgb_g_shift_24 + 3; + bshift = _rgb_b_shift_24 + 3; + break; + + case 16: + rshift = _rgb_r_shift_16; + gshift = _rgb_g_shift_16 + 1; + bshift = _rgb_b_shift_16; + break; + + case 15: + rshift = _rgb_r_shift_15; + gshift = _rgb_g_shift_15; + bshift = _rgb_b_shift_15; + break; + + default: + return -1; + } + + for (i = rsvduse; i < numcols; i++) { + int r = (colors[i].color >> rshift) & 0x1F; + int g = (colors[i].color >> gshift) & 0x1F; + int b = (colors[i].color >> bshift) & 0x1F; + colors[i].color = ((r << 1) | (g << 9) | (b << 17)); + } + + do { + int start, k; + + /* there may be only small number of numcols colors, so we don't need + * any optimization + */ + if (numcols <= palsize) + break; + + if (rsvduse > 0) { + /* copy 'rsvd' to the 'colors' */ + for (i = 0, j = 0; i < rsvduse; j++) + if (rsvdcols[j] > 0) + colors[i++].color = (pal[j].r | (pal[j].g << 8) | (pal[j].b << 16)); + + /* reduce 'colors' skipping colors contained in 'rsvd' palette */ + for (i = rsvduse, j = i; i < numcols; i++) + if (no_such_color(colors, rsvduse, colors[i].color, prec_mask)) + colors[j++].color = colors[i].color; + + /* now there are j colors in 'common' */ + numcols = j; + + /* now there might be enough free cells in palette */ + if (numcols <= palsize) + break; + } + + /* from 'start' will start swapping colors */ + start = palsize - palsize / fraction; + + /* it may be slow, so don't let replace too many colors */ + if (start < (palsize - maxswaps)) + start = palsize - maxswaps; + + /* swap not less than 10 colors */ + if (start > (palsize - 10)) + start = rsvduse; + + /* don't swap reserved colors */ + if (start < rsvduse) + start = rsvduse; + + if (bitsperrgb == 5) { + /* do second pass on the colors we'll possibly use to replace (lower + bits per pixel to 4) - this would effectively lower the maximum + number of different colors to some 4000 (from 32000) */ + for (i = start, k = i; i < numcols; i++) { + for (j = 0; j < k; j++) { + if ((colors[j].color & prec_mask2) == (colors[i].color & prec_mask2)) { + j = -1; + break; + } + } + /* add this color if there is not similar one */ + if (j != -1) + colors[k++].color = colors[i].color; + } + + /* now there are k colors in 'common' */ + numcols = k; + + /* now there might be enough free cells in palette */ + if (numcols <= palsize) + break; + } + + /* start finding the most different colors */ + optimize_colors(colors, start, palsize, numcols, mindiff); + + numcols = palsize; + } while (0); + + /* copy used colors to 'pal', skipping 'rsvd' */ + for (i = rsvduse, j = 0; i < numcols; j++) + if (!rsvdcols[j]) + copy_color(&pal[j], colors[i++].color); + + _AL_FREE(colors); + + return distinct; +} + + + +int generate_optimized_palette(BITMAP *image, PALETTE pal, AL_CONST signed char rsvdcols[PAL_SIZE]) +{ + ASSERT(image); + return generate_optimized_palette_ex(image, pal, rsvdcols, DEFAULT_PREC, DEFAULT_FRACTION, DEFAULT_MAXSWAPS, DEFAULT_MINDIFF); +} + diff --git a/libsrc/allegro/src/readbmp.c b/libsrc/allegro/src/readbmp.c new file mode 100644 index 00000000000..388a26c6c86 --- /dev/null +++ b/libsrc/allegro/src/readbmp.c @@ -0,0 +1,250 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Top level bitmap reading routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +typedef struct BITMAP_TYPE_INFO +{ + char *ext; + BITMAP *(*load)(AL_CONST char *filename, RGB *pal); + int (*save)(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal); + struct BITMAP_TYPE_INFO *next; +} BITMAP_TYPE_INFO; + +static BITMAP_TYPE_INFO *bitmap_type_list = NULL; + + + +/* register_bitmap_file_type: + * Informs Allegro of a new image file type, telling it how to load and + * save files of this format (either function may be NULL). + */ +void register_bitmap_file_type(AL_CONST char *ext, BITMAP *(*load)(AL_CONST char *filename, RGB *pal), int (*save)(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal)) +{ + char tmp[32], *aext; + BITMAP_TYPE_INFO *iter = bitmap_type_list; + + aext = uconvert_toascii(ext, tmp); + if (strlen(aext) == 0) return; + + if (!iter) + iter = bitmap_type_list = _AL_MALLOC(sizeof(struct BITMAP_TYPE_INFO)); + else { + for (iter = bitmap_type_list; iter->next; iter = iter->next); + iter = iter->next = _AL_MALLOC(sizeof(struct BITMAP_TYPE_INFO)); + } + + if (iter) { + iter->load = load; + iter->save = save; + iter->ext = _al_strdup(aext); + iter->next = NULL; + } +} + + + +/* load_bitmap: + * Loads a bitmap from disk. + */ +BITMAP *load_bitmap(AL_CONST char *filename, RGB *pal) +{ + char tmp[32], *aext; + BITMAP_TYPE_INFO *iter; + ASSERT(filename); + + aext = uconvert_toascii(get_extension(filename), tmp); + + for (iter = bitmap_type_list; iter; iter = iter->next) { + if (stricmp(iter->ext, aext) == 0) { + if (iter->load) + return iter->load(filename, pal); + return NULL; + } + } + + return NULL; +} + + + +/* save_bitmap: + * Writes a bitmap to disk. + */ +int save_bitmap(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) +{ + char tmp[32], *aext; + BITMAP_TYPE_INFO *iter; + ASSERT(filename); + ASSERT(bmp); + + aext = uconvert_toascii(get_extension(filename), tmp); + + for (iter = bitmap_type_list; iter; iter = iter->next) { + if (stricmp(iter->ext, aext) == 0) { + if (iter->save) + return iter->save(filename, bmp, pal); + return 1; + } + } + + return 1; +} + + + +/* _fixup_loaded_bitmap: + * Helper function for adjusting the color depth of a loaded image. + * Converts the bitmap BMP to the color depth BPP. If BMP is a 8-bit + * bitmap, PAL must be the palette attached to the bitmap. If BPP is + * equal to 8, the conversion is performed either by building a palette + * optimized for the bitmap if PAL is not NULL (in which case PAL gets + * filled in with this palette) or by using the current palette if PAL + * is NULL. In any other cases, PAL is unused. + */ +BITMAP *_fixup_loaded_bitmap(BITMAP *bmp, PALETTE pal, int bpp) +{ + BITMAP *b2; + ASSERT(bmp); + + b2 = create_bitmap_ex(bpp, bmp->w, bmp->h); + if (!b2) { + destroy_bitmap(bmp); + return NULL; + } + + if (bpp == 8) { + RGB_MAP *old_map = rgb_map; + + if (pal) + generate_optimized_palette(bmp, pal, NULL); + else + pal = _current_palette; + + rgb_map = _AL_MALLOC(sizeof(RGB_MAP)); + if (rgb_map != NULL) + create_rgb_table(rgb_map, pal, NULL); + + blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h); + + if (rgb_map != NULL) + _AL_FREE(rgb_map); + rgb_map = old_map; + } + else if (bitmap_color_depth(bmp) == 8) { + select_palette(pal); + blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h); + unselect_palette(); + } + else { + blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h); + } + + destroy_bitmap(bmp); + + return b2; +} + + + +/* register_bitmap_file_type_exit: + * Free list of registered bitmap file types. + */ +static void register_bitmap_file_type_exit(void) +{ + BITMAP_TYPE_INFO *iter = bitmap_type_list, *next; + + while (iter) { + next = iter->next; + _AL_FREE(iter->ext); + _AL_FREE(iter); + iter = next; + } + + bitmap_type_list = NULL; + + /* If we are using a destructor, then we only want to prune the list + * down to valid modules. So we clean up as usual, but then reinstall + * the internal modules. + */ + #ifdef ALLEGRO_USE_CONSTRUCTOR + _register_bitmap_file_type_init(); + #endif + + _remove_exit_func(register_bitmap_file_type_exit); +} + + + +/* _register_bitmap_file_type_init: + * Register built-in bitmap file types. + */ +void _register_bitmap_file_type_init(void) +{ + char buf[32]; + + _add_exit_func(register_bitmap_file_type_exit, + "register_bitmap_file_type_exit"); + + register_bitmap_file_type(uconvert_ascii("bmp", buf), load_bmp, save_bmp); + register_bitmap_file_type(uconvert_ascii("pcx", buf), load_pcx, save_pcx); +} + + + +#ifdef ALLEGRO_USE_CONSTRUCTOR + CONSTRUCTOR_FUNCTION(static void bitmap_filetype_constructor(void)); + DESTRUCTOR_FUNCTION(static void bitmap_filetype_destructor(void)); + + /* bitmap_filetype_constructor: + * Register bitmap filetype functions if this object file is linked + * in. This isn't called if the load_bitmap() and save_bitmap() + * functions aren't used in a program, thus saving a little space + * in statically linked programs. + */ + static void bitmap_filetype_constructor(void) + { + _register_bitmap_file_type_init(); + } + + /* bitmap_filetype_destructor: + * Since we only want to destroy the whole list when we *actually* + * quit, not just when allegro_exit() is called, we need to use a + * destructor to accomplish this. + */ + static void bitmap_filetype_destructor(void) + { + BITMAP_TYPE_INFO *iter = bitmap_type_list, *next; + + while (iter) { + next = iter->next; + _AL_FREE(iter->ext); + _AL_FREE(iter); + iter = next; + } + + bitmap_type_list = NULL; + + _remove_exit_func(register_bitmap_file_type_exit); + } +#endif diff --git a/libsrc/allegro/src/rotate.c b/libsrc/allegro/src/rotate.c new file mode 100644 index 00000000000..b17148bbcf9 --- /dev/null +++ b/libsrc/allegro/src/rotate.c @@ -0,0 +1,896 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Sprite rotation routines. + * + * By Shawn Hargreaves. + * + * Flipping routines by Andrew Geers. + * + * Optimized by Sven Sandberg. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" +#include + + + +/* + * Scanline drawers. + */ + +#define SCANLINE_DRAWER_GENERIC(name, INIT, PUTPIXEL) \ + static void draw_scanline_##name(BITMAP *bmp, BITMAP *spr, \ + fixed l_bmp_x, int bmp_y_i, \ + fixed r_bmp_x, \ + fixed l_spr_x, fixed l_spr_y, \ + fixed spr_dx, fixed spr_dy) \ + { \ + int c; \ + int mask_color; \ + \ + INIT; \ + mask_color = bmp->vtable->mask_color; \ + r_bmp_x >>= 16; \ + l_bmp_x >>= 16; \ + for (; l_bmp_x <= r_bmp_x; l_bmp_x++) { \ + c = getpixel(spr, l_spr_x>>16, l_spr_y>>16); \ + if (c != mask_color) \ + PUTPIXEL; \ + l_spr_x += spr_dx; \ + l_spr_y += spr_dy; \ + } \ + } + +SCANLINE_DRAWER_GENERIC(generic_convert + , + int bmp_depth; + int spr_depth; + bmp_depth = bitmap_color_depth(bmp); + spr_depth = bitmap_color_depth(spr); + , + putpixel(bmp, l_bmp_x, bmp_y_i, + makecol_depth(bmp_depth, + getr_depth(spr_depth, c), + getg_depth(spr_depth, c), + getb_depth(spr_depth, c)))) + +SCANLINE_DRAWER_GENERIC(generic + , + ; /* nop */ + , + putpixel(bmp, l_bmp_x, bmp_y_i, c)) + + + +#define SCANLINE_DRAWER(bits_pp, GETPIXEL) \ + static void draw_scanline_##bits_pp(BITMAP *bmp, BITMAP *spr, \ + fixed l_bmp_x, int bmp_y_i, \ + fixed r_bmp_x, \ + fixed l_spr_x, fixed l_spr_y, \ + fixed spr_dx, fixed spr_dy) \ + { \ + int c; \ + uintptr_t addr, end_addr; \ + unsigned char **spr_line = spr->line; \ + \ + r_bmp_x >>= 16; \ + l_bmp_x >>= 16; \ + bmp_select(bmp); \ + addr = bmp_write_line(bmp, bmp_y_i); \ + end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ + addr += l_bmp_x * ((bits_pp + 7) / 8); \ + for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ + GETPIXEL; \ + if (c != MASK_COLOR_##bits_pp) \ + bmp_write##bits_pp(addr, c); \ + l_spr_x += spr_dx; \ + l_spr_y += spr_dy; \ + } \ + } + + + +#ifdef ALLEGRO_COLOR8 + SCANLINE_DRAWER(8, c = spr_line[l_spr_y>>16][l_spr_x>>16]); +#endif + +#ifdef ALLEGRO_COLOR16 + SCANLINE_DRAWER(15, c = ((unsigned short *)spr_line[l_spr_y>>16]) + [l_spr_x>>16]) + SCANLINE_DRAWER(16, c = ((unsigned short *)spr_line[l_spr_y>>16]) + [l_spr_x>>16]) +#endif + +#ifdef ALLEGRO_COLOR24 + #ifdef ALLEGRO_LITTLE_ENDIAN + SCANLINE_DRAWER(24, + { + unsigned char *p = spr_line[l_spr_y>>16] + + (l_spr_x>>16) * 3; + c = p[0]; + c |= (int)p[1] << 8; + c |= (int)p[2] << 16; + }) + #else + SCANLINE_DRAWER(24, + { + unsigned char *p = spr_line[l_spr_y>>16] + + (l_spr_x>>16) * 3; + c = (int)p[0] << 16; + c |= (int)p[1] << 8; + c |= p[2]; + }) + #endif +#endif + +#ifdef ALLEGRO_COLOR32 + SCANLINE_DRAWER(32, + c = ((uint32_t *)spr_line[l_spr_y>>16]) + [l_spr_x>>16]) +#endif + +#ifdef ALLEGRO_GFX_HAS_VGA + static void draw_scanline_modex( + BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y_i, fixed r_bmp_x, + fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy) + { + int c; + uintptr_t start_addr, addr, end_addr; + unsigned char **spr_line = spr->line; + int plane; + fixed spr_x, spr_y; + + r_bmp_x >>= 16; + l_bmp_x >>= 16; + start_addr = (uintptr_t)bmp->line[bmp_y_i]; + spr_dx <<= 2; + spr_dy <<= 2; + for (plane = 0; plane < 4; plane++) { + addr = start_addr + ((l_bmp_x + plane) >> 2); + end_addr = addr + ((r_bmp_x - l_bmp_x - plane) >> 2); + outportw(0x3C4, (0x100 << ((l_bmp_x + plane) & 3)) | 2); + spr_x = l_spr_x; + spr_y = l_spr_y; + for (; addr < end_addr; addr++) { + c = spr_line[spr_y >> 16][spr_x >> 16]; + if (c != MASK_COLOR_8) + _farnspokeb(addr, c); + spr_x += spr_dx; + spr_y += spr_dy; + } + l_spr_x += spr_dx >> 2; + l_spr_y += spr_dy >> 2; + } + } +#endif + + + +/* _parallelogram_map: + * Worker routine for drawing rotated and/or scaled and/or flipped sprites: + * It actually maps the sprite to any parallelogram-shaped area of the + * bitmap. The top left corner is mapped to (xs[0], ys[0]), the top right to + * (xs[1], ys[1]), the bottom right to x (xs[2], ys[2]), and the bottom left + * to (xs[3], ys[3]). The corners are assumed to form a perfect + * parallelogram, i.e. xs[0]+xs[2] = xs[1]+xs[3]. The corners are given in + * fixed point format, so xs[] and ys[] are coordinates of the outer corners + * of corner pixels in clockwise order beginning with top left. + * All coordinates begin with 0 in top left corner of pixel (0, 0). So a + * rotation by 0 degrees of a sprite to the top left of a bitmap can be + * specified with coordinates (0, 0) for the top left pixel in source + * bitmap. With the default scanline drawer, a pixel in the destination + * bitmap is drawn if and only if its center is covered by any pixel in the + * sprite. The color of this covering sprite pixel is used to draw. + * If sub_pixel_accuracy=FALSE, then the scanline drawer will be called with + * *_bmp_x being a fixed point representation of the integers representing + * the x coordinate of the first and last point in bmp whose centre is + * covered by the sprite. If sub_pixel_accuracy=TRUE, then the scanline + * drawer will be called with the exact fixed point position of the first + * and last point in which the horizontal line passing through the centre is + * at least partly covered by the sprite. This is useful for doing + * anti-aliased blending. + */ +void _parallelogram_map(BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], + void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, + fixed l_bmp_x, int bmp_y, + fixed r_bmp_x, + fixed l_spr_x, fixed l_spr_y, + fixed spr_dx, fixed spr_dy), + int sub_pixel_accuracy) +{ + /* Index in xs[] and ys[] to topmost point. */ + int top_index; + /* Rightmost point has index (top_index+right_index) int xs[] and ys[]. */ + int right_index; + /* Loop variables. */ + int index, i; + /* Coordinates in bmp ordered as top-right-bottom-left. */ + fixed corner_bmp_x[4], corner_bmp_y[4]; + /* Coordinates in spr ordered as top-right-bottom-left. */ + fixed corner_spr_x[4], corner_spr_y[4]; + /* y coordinate of bottom point, left point and right point. */ + int clip_bottom_i, l_bmp_y_bottom_i, r_bmp_y_bottom_i; + /* Left and right clipping. */ + fixed clip_left, clip_right; + /* Temporary variable. */ + fixed extra_scanline_fraction; + + /* + * Variables used in the loop + */ + /* Coordinates of sprite and bmp points in beginning of scanline. */ + fixed l_spr_x, l_spr_y, l_bmp_x, l_bmp_dx; + /* Increment of left sprite point as we move a scanline down. */ + fixed l_spr_dx, l_spr_dy; + /* Coordinates of sprite and bmp points in end of scanline. */ + fixed r_bmp_x, r_bmp_dx; + #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE + fixed r_spr_x, r_spr_y; + /* Increment of right sprite point as we move a scanline down. */ + fixed r_spr_dx, r_spr_dy; + #endif + /* Increment of sprite point as we move right inside a scanline. */ + fixed spr_dx, spr_dy; + /* Positions of beginning of scanline after rounding to integer coordinate + in bmp. */ + fixed l_spr_x_rounded, l_spr_y_rounded, l_bmp_x_rounded; + fixed r_bmp_x_rounded; + /* Current scanline. */ + int bmp_y_i; + /* Right edge of scanline. */ + int right_edge_test; + + /* Get index of topmost point. */ + top_index = 0; + if (ys[1] < ys[0]) + top_index = 1; + if (ys[2] < ys[top_index]) + top_index = 2; + if (ys[3] < ys[top_index]) + top_index = 3; + + /* Get direction of points: clockwise or anti-clockwise. */ + right_index = (double)(xs[(top_index+1) & 3] - xs[top_index]) * + (double)(ys[(top_index-1) & 3] - ys[top_index]) > + (double)(xs[(top_index-1) & 3] - xs[top_index]) * + (double)(ys[(top_index+1) & 3] - ys[top_index]) ? 1 : -1; + //FIXME: why does fixmul overflow below? + /*if (fixmul(xs[(top_index+1) & 3] - xs[top_index], + ys[(top_index-1) & 3] - ys[top_index]) > + fixmul(xs[(top_index-1) & 3] - xs[top_index], + ys[(top_index+1) & 3] - ys[top_index])) + right_index = 1; + else + right_index = -1;*/ + + /* + * Get coordinates of the corners. + */ + + /* corner_*[0] is top, [1] is right, [2] is bottom, [3] is left. */ + index = top_index; + for (i = 0; i < 4; i++) { + corner_bmp_x[i] = xs[index]; + corner_bmp_y[i] = ys[index]; + if (index < 2) + corner_spr_y[i] = 0; + else + /* Need `- 1' since otherwise it would be outside sprite. */ + corner_spr_y[i] = (spr->h << 16) - 1; + if ((index == 0) || (index == 3)) + corner_spr_x[i] = 0; + else + corner_spr_x[i] = (spr->w << 16) - 1; + index = (index + right_index) & 3; + } + + /* + * Get scanline starts, ends and deltas, and clipping coordinates. + */ + #define top_bmp_y corner_bmp_y[0] + #define right_bmp_y corner_bmp_y[1] + #define bottom_bmp_y corner_bmp_y[2] + #define left_bmp_y corner_bmp_y[3] + #define top_bmp_x corner_bmp_x[0] + #define right_bmp_x corner_bmp_x[1] + #define bottom_bmp_x corner_bmp_x[2] + #define left_bmp_x corner_bmp_x[3] + #define top_spr_y corner_spr_y[0] + #define right_spr_y corner_spr_y[1] + #define bottom_spr_y corner_spr_y[2] + #define left_spr_y corner_spr_y[3] + #define top_spr_x corner_spr_x[0] + #define right_spr_x corner_spr_x[1] + #define bottom_spr_x corner_spr_x[2] + #define left_spr_x corner_spr_x[3] + + /* Calculate left and right clipping. */ + if (bmp->clip) { + clip_left = bmp->cl << 16; + clip_right = (bmp->cr << 16) - 1; + } + else { + ASSERT(left_bmp_x >= 0 && top_bmp_x >= 0 && bottom_bmp_x >= 0 + && right_bmp_x < (bmp->w << 16) + && top_bmp_x < (bmp->w << 16) + && bottom_bmp_x < (bmp->w << 16)); + clip_left = 0; + clip_right = (bmp->w << 16) - 1; + } + + /* Quit if we're totally outside. */ + if ((left_bmp_x > clip_right) && + (top_bmp_x > clip_right) && + (bottom_bmp_x > clip_right)) + return; + if ((right_bmp_x < clip_left) && + (top_bmp_x < clip_left) && + (bottom_bmp_x < clip_left)) + return; + + /* Bottom clipping. */ + if (sub_pixel_accuracy) + clip_bottom_i = (bottom_bmp_y + 0xffff) >> 16; + else + clip_bottom_i = (bottom_bmp_y + 0x8000) >> 16; + if (bmp->clip) { + if (clip_bottom_i > bmp->cb) + clip_bottom_i = bmp->cb; + } + else { + ASSERT(clip_bottom_i <= bmp->h); + } + + /* Calculate y coordinate of first scanline. */ + if (sub_pixel_accuracy) + bmp_y_i = top_bmp_y >> 16; + else + bmp_y_i = (top_bmp_y + 0x8000) >> 16; + if (bmp->clip) { + if (bmp_y_i < bmp->ct) + bmp_y_i = bmp->ct; + } + else { + ASSERT(bmp_y_i >= 0); + } + + /* Sprite is above or below bottom clipping area. */ + if (bmp_y_i >= clip_bottom_i) + return; + + /* Vertical gap between top corner and centre of topmost scanline. */ + extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - top_bmp_y; + /* Calculate x coordinate of beginning of scanline in bmp. */ + l_bmp_dx = fixdiv(left_bmp_x - top_bmp_x, + left_bmp_y - top_bmp_y); + l_bmp_x = top_bmp_x + fixmul(extra_scanline_fraction, l_bmp_dx); + /* Calculate x coordinate of beginning of scanline in spr. */ + /* note: all these are rounded down which is probably a Good Thing (tm) */ + l_spr_dx = fixdiv(left_spr_x - top_spr_x, + left_bmp_y - top_bmp_y); + l_spr_x = top_spr_x + fixmul(extra_scanline_fraction, l_spr_dx); + /* Calculate y coordinate of beginning of scanline in spr. */ + l_spr_dy = fixdiv(left_spr_y - top_spr_y, + left_bmp_y - top_bmp_y); + l_spr_y = top_spr_y + fixmul(extra_scanline_fraction, l_spr_dy); + + /* Calculate left loop bound. */ + l_bmp_y_bottom_i = (left_bmp_y + 0x8000) >> 16; + if (l_bmp_y_bottom_i > clip_bottom_i) + l_bmp_y_bottom_i = clip_bottom_i; + + /* Calculate x coordinate of end of scanline in bmp. */ + r_bmp_dx = fixdiv(right_bmp_x - top_bmp_x, + right_bmp_y - top_bmp_y); + r_bmp_x = top_bmp_x + fixmul(extra_scanline_fraction, r_bmp_dx); + #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE + /* Calculate x coordinate of end of scanline in spr. */ + r_spr_dx = fixdiv(right_spr_x - top_spr_x, + right_bmp_y - top_bmp_y); + r_spr_x = top_spr_x + fixmul(extra_scanline_fraction, r_spr_dx); + /* Calculate y coordinate of end of scanline in spr. */ + r_spr_dy = fixdiv(right_spr_y - top_spr_y, + right_bmp_y - top_bmp_y); + r_spr_y = top_spr_y + fixmul(extra_scanline_fraction, r_spr_dy); + #endif + + /* Calculate right loop bound. */ + r_bmp_y_bottom_i = (right_bmp_y + 0x8000) >> 16; + + /* Get dx and dy, the offsets to add to the source coordinates as we move + one pixel rightwards along a scanline. This formula can be derived by + considering the 2x2 matrix that transforms the sprite to the + parallelogram. + We'd better use double to get this as exact as possible, since any + errors will be accumulated along the scanline. + */ + spr_dx = (fixed)((ys[3] - ys[0]) * 65536.0 * (65536.0 * spr->w) / + ((xs[1] - xs[0]) * (double)(ys[3] - ys[0]) - + (xs[3] - xs[0]) * (double)(ys[1] - ys[0]))); + spr_dy = (fixed)((ys[1] - ys[0]) * 65536.0 * (65536.0 * spr->h) / + ((xs[3] - xs[0]) * (double)(ys[1] - ys[0]) - + (xs[1] - xs[0]) * (double)(ys[3] - ys[0]))); + + /* + * Loop through scanlines. + */ + + while (1) { + /* Has beginning of scanline passed a corner? */ + if (bmp_y_i >= l_bmp_y_bottom_i) { + /* Are we done? */ + if (bmp_y_i >= clip_bottom_i) + break; + + /* Vertical gap between left corner and centre of scanline. */ + extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - left_bmp_y; + /* Update x coordinate of beginning of scanline in bmp. */ + l_bmp_dx = fixdiv(bottom_bmp_x - left_bmp_x, + bottom_bmp_y - left_bmp_y); + l_bmp_x = left_bmp_x + fixmul(extra_scanline_fraction, l_bmp_dx); + /* Update x coordinate of beginning of scanline in spr. */ + l_spr_dx = fixdiv(bottom_spr_x - left_spr_x, + bottom_bmp_y - left_bmp_y); + l_spr_x = left_spr_x + fixmul(extra_scanline_fraction, l_spr_dx); + /* Update y coordinate of beginning of scanline in spr. */ + l_spr_dy = fixdiv(bottom_spr_y - left_spr_y, + bottom_bmp_y - left_bmp_y); + l_spr_y = left_spr_y + fixmul(extra_scanline_fraction, l_spr_dy); + + /* Update loop bound. */ + if (sub_pixel_accuracy) + l_bmp_y_bottom_i = (bottom_bmp_y + 0xffff) >> 16; + else + l_bmp_y_bottom_i = (bottom_bmp_y + 0x8000) >> 16; + if (l_bmp_y_bottom_i > clip_bottom_i) + l_bmp_y_bottom_i = clip_bottom_i; + } + + /* Has end of scanline passed a corner? */ + if (bmp_y_i >= r_bmp_y_bottom_i) { + /* Vertical gap between right corner and centre of scanline. */ + extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - right_bmp_y; + /* Update x coordinate of end of scanline in bmp. */ + r_bmp_dx = fixdiv(bottom_bmp_x - right_bmp_x, + bottom_bmp_y - right_bmp_y); + r_bmp_x = right_bmp_x + fixmul(extra_scanline_fraction, r_bmp_dx); + #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE + /* Update x coordinate of beginning of scanline in spr. */ + r_spr_dx = fixdiv(bottom_spr_x - right_spr_x, + bottom_bmp_y - right_bmp_y); + r_spr_x = right_spr_x + fixmul(extra_scanline_fraction, r_spr_dx); + /* Update y coordinate of beginning of scanline in spr. */ + r_spr_dy = fixdiv(bottom_spr_y - right_spr_y, + bottom_bmp_y - right_bmp_y); + r_spr_y = right_spr_y + fixmul(extra_scanline_fraction, r_spr_dy); + #endif + + /* Update loop bound: We aren't supposed to use this any more, so + just set it to some big enough value. */ + r_bmp_y_bottom_i = clip_bottom_i; + } + + /* Make left bmp coordinate be an integer and clip it. */ + if (sub_pixel_accuracy) + l_bmp_x_rounded = l_bmp_x; + else + l_bmp_x_rounded = (l_bmp_x + 0x8000) & ~0xffff; + if (l_bmp_x_rounded < clip_left) + l_bmp_x_rounded = clip_left; + + /* ... and move starting point in sprite accordingly. */ + if (sub_pixel_accuracy) { + l_spr_x_rounded = l_spr_x + + fixmul((l_bmp_x_rounded - l_bmp_x), spr_dx); + l_spr_y_rounded = l_spr_y + + fixmul((l_bmp_x_rounded - l_bmp_x), spr_dy); + } + else { + l_spr_x_rounded = l_spr_x + + fixmul(l_bmp_x_rounded + 0x7fff - l_bmp_x, spr_dx); + l_spr_y_rounded = l_spr_y + + fixmul(l_bmp_x_rounded + 0x7fff - l_bmp_x, spr_dy); + } + + /* Make right bmp coordinate be an integer and clip it. */ + if (sub_pixel_accuracy) + r_bmp_x_rounded = r_bmp_x; + else + r_bmp_x_rounded = (r_bmp_x - 0x8000) & ~0xffff; + if (r_bmp_x_rounded > clip_right) + r_bmp_x_rounded = clip_right; + + /* Draw! */ + if (l_bmp_x_rounded <= r_bmp_x_rounded) { + if (!sub_pixel_accuracy) { + /* The bodies of these ifs are only reached extremely seldom, + it's an ugly hack to avoid reading outside the sprite when + the rounding errors are accumulated the wrong way. It would + be nicer if we could ensure that this never happens by making + all multiplications and divisions be rounded up or down at + the correct places. + I did try another approach: recalculate the edges of the + scanline from scratch each scanline rather than incrementally. + Drawing a sprite with that routine took about 25% longer time + though. + */ + if ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->w) { + if (((l_spr_x_rounded < 0) && (spr_dx <= 0)) || + ((l_spr_x_rounded > 0) && (spr_dx >= 0))) { + /* This can happen. */ + goto skip_draw; + } + else { + /* I don't think this can happen, but I can't prove it. */ + do { + l_spr_x_rounded += spr_dx; + l_bmp_x_rounded += 65536; + if (l_bmp_x_rounded > r_bmp_x_rounded) + goto skip_draw; + } while ((unsigned)(l_spr_x_rounded >> 16) >= + (unsigned)spr->w); + + } + } + right_edge_test = l_spr_x_rounded + + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * + spr_dx; + if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->w) { + if (((right_edge_test < 0) && (spr_dx <= 0)) || + ((right_edge_test > 0) && (spr_dx >= 0))) { + /* This can happen. */ + do { + r_bmp_x_rounded -= 65536; + right_edge_test -= spr_dx; + if (l_bmp_x_rounded > r_bmp_x_rounded) + goto skip_draw; + } while ((unsigned)(right_edge_test >> 16) >= + (unsigned)spr->w); + } + else { + /* I don't think this can happen, but I can't prove it. */ + goto skip_draw; + } + } + if ((unsigned)(l_spr_y_rounded >> 16) >= (unsigned)spr->h) { + if (((l_spr_y_rounded < 0) && (spr_dy <= 0)) || + ((l_spr_y_rounded > 0) && (spr_dy >= 0))) { + /* This can happen. */ + goto skip_draw; + } + else { + /* I don't think this can happen, but I can't prove it. */ + do { + l_spr_y_rounded += spr_dy; + l_bmp_x_rounded += 65536; + if (l_bmp_x_rounded > r_bmp_x_rounded) + goto skip_draw; + } while (((unsigned)l_spr_y_rounded >> 16) >= + (unsigned)spr->h); + } + } + right_edge_test = l_spr_y_rounded + + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * + spr_dy; + if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->h) { + if (((right_edge_test < 0) && (spr_dy <= 0)) || + ((right_edge_test > 0) && (spr_dy >= 0))) { + /* This can happen. */ + do { + r_bmp_x_rounded -= 65536; + right_edge_test -= spr_dy; + if (l_bmp_x_rounded > r_bmp_x_rounded) + goto skip_draw; + } while ((unsigned)(right_edge_test >> 16) >= + (unsigned)spr->h); + } + else { + /* I don't think this can happen, but I can't prove it. */ + goto skip_draw; + } + } + } + draw_scanline(bmp, spr, + l_bmp_x_rounded, bmp_y_i, r_bmp_x_rounded, + l_spr_x_rounded, l_spr_y_rounded, + spr_dx, spr_dy); + + } + /* I'm not going to apoligize for this label and its gotos: to get + rid of it would just make the code look worse. */ + skip_draw: + + /* Jump to next scanline. */ + bmp_y_i++; + /* Update beginning of scanline. */ + l_bmp_x += l_bmp_dx; + l_spr_x += l_spr_dx; + l_spr_y += l_spr_dy; + /* Update end of scanline. */ + r_bmp_x += r_bmp_dx; + #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE + r_spr_x += r_spr_dx; + r_spr_y += r_spr_dy; + #endif + } + + bmp_unwrite_line(bmp); +} + + + +/* _parallelogram_map_standard: + * Helper function for calling _parallelogram_map() with the appropriate + * scanline drawer. I didn't want to include this in the + * _parallelogram_map() function since then you can bypass it and define + * your own scanline drawer, eg. for anti-aliased rotations. + */ +void _parallelogram_map_standard(BITMAP *bmp, BITMAP *sprite, + fixed xs[4], fixed ys[4]) +{ + int old_drawing_mode; + if (bitmap_color_depth(bmp) != bitmap_color_depth(sprite)) { + /* These scanline drawers use putpixel() so we must set solid mode. */ + old_drawing_mode = _drawing_mode; + drawing_mode(DRAW_MODE_SOLID, _drawing_pattern, + _drawing_x_anchor, _drawing_y_anchor); + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_generic_convert, FALSE); + drawing_mode(old_drawing_mode, _drawing_pattern, + _drawing_x_anchor, _drawing_y_anchor); + } + else if (!is_memory_bitmap(sprite)) { + old_drawing_mode = _drawing_mode; + drawing_mode(DRAW_MODE_SOLID, _drawing_pattern, + _drawing_x_anchor, _drawing_y_anchor); + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_generic, FALSE); + drawing_mode(old_drawing_mode, _drawing_pattern, + _drawing_x_anchor, _drawing_y_anchor); + } + else if (is_linear_bitmap(bmp)) { + switch (bitmap_color_depth(bmp)) { + #ifdef ALLEGRO_COLOR8 + case 8: + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_8, FALSE); + break; + #endif + + #ifdef ALLEGRO_COLOR16 + case 15: + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_15, FALSE); + break; + + case 16: + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_16, FALSE); + break; + #endif + + #ifdef ALLEGRO_COLOR24 + case 24: + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_24, FALSE); + break; + #endif + + #ifdef ALLEGRO_COLOR32 + case 32: + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_32, FALSE); + break; + #endif + + default: + /* NOTREACHED */ + ASSERT(0); + } + } + #ifdef ALLEGRO_GFX_HAS_VGA + else { + _parallelogram_map(bmp, sprite, xs, ys, + draw_scanline_modex, FALSE); + } + #endif +} + + + +/* _rotate_scale_flip_coordinates: + * Calculates the coordinates for the rotated, scaled and flipped sprite, + * and passes them on to the given function. + */ +void _rotate_scale_flip_coordinates(fixed w, fixed h, + fixed x, fixed y, fixed cx, fixed cy, + fixed angle, + fixed scale_x, fixed scale_y, + int h_flip, int v_flip, + fixed xs[4], fixed ys[4]) +{ + fixed fix_cos, fix_sin; + int tl = 0, tr = 1, bl = 3, br = 2; + int tmp; + double cos_angle, sin_angle; + fixed xofs, yofs; + + /* Setting angle to the range -180...180 degrees makes sin & cos + more numerically stable. (Yes, this does have an effect for big + angles!) Note that using "real" sin() and cos() gives much better + precision than fixsin() and fixcos(). */ + angle = angle & 0xffffff; + if (angle >= 0x800000) + angle -= 0x1000000; + + _AL_SINCOS(angle * (AL_PI / (double)0x800000), sin_angle, cos_angle); + + if (cos_angle >= 0) + fix_cos = (int)(cos_angle * 0x10000 + 0.5); + else + fix_cos = (int)(cos_angle * 0x10000 - 0.5); + if (sin_angle >= 0) + fix_sin = (int)(sin_angle * 0x10000 + 0.5); + else + fix_sin = (int)(sin_angle * 0x10000 - 0.5); + + /* Decide what order to take corners in. */ + if (v_flip) { + tl = 3; + tr = 2; + bl = 0; + br = 1; + } + else { + tl = 0; + tr = 1; + bl = 3; + br = 2; + } + if (h_flip) { + tmp = tl; + tl = tr; + tr = tmp; + tmp = bl; + bl = br; + br = tmp; + } + + /* Calculate new coordinates of all corners. */ + w = fixmul(w, scale_x); + h = fixmul(h, scale_y); + cx = fixmul(cx, scale_x); + cy = fixmul(cy, scale_y); + + xofs = x - fixmul(cx, fix_cos) + fixmul(cy, fix_sin); + + yofs = y - fixmul(cx, fix_sin) - fixmul(cy, fix_cos); + + xs[tl] = xofs; + ys[tl] = yofs; + xs[tr] = xofs + fixmul(w, fix_cos); + ys[tr] = yofs + fixmul(w, fix_sin); + xs[bl] = xofs - fixmul(h, fix_sin); + ys[bl] = yofs + fixmul(h, fix_cos); + + xs[br] = xs[tr] + xs[bl] - xs[tl]; + ys[br] = ys[tr] + ys[bl] - ys[tl]; +} + + + +/* _pivot_scaled_sprite_flip: + * The most generic routine to which you specify the position with angles, + * scales, etc. + */ +void _pivot_scaled_sprite_flip(BITMAP *bmp, BITMAP *sprite, + fixed x, fixed y, fixed cx, fixed cy, + fixed angle, fixed scale, int v_flip) +{ + fixed xs[4], ys[4]; + + _rotate_scale_flip_coordinates(sprite->w << 16, sprite->h << 16, + x, y, cx, cy, angle, scale, scale, + FALSE, v_flip, xs, ys); + + _parallelogram_map_standard(bmp, sprite, xs, ys); +} + + + +/* + * rotate_*() + */ + + + +/* _rotate_scaled_sprite_flip: (template) + * Rotates and scales a sprite, optionally flipping it about either axis. + * Coordinates are given in fixed point format. + */ +#if 0 +static void _rotate_scaled_sprite_flip(BITMAP *bmp, BITMAP *sprite, + fixed x, fixed y, + fixed angle, fixed scale, int v_flip) +{ + _pivot_scaled_sprite_flip(bmp, sprite, + x + (sprite->w * scale) / 2, + y + (sprite->h * scale) / 2, + sprite->w << 15, sprite->h << 15, + angle, scale, v_flip); +} +#endif + + + +/* rotate_sprite: (inlined) + * Draws a sprite image onto a bitmap at the specified position, rotating + * it by the specified angle. The angle is a fixed point 16.16 number in + * the same format used by the fixed point trig routines, with 256 equal + * to a full circle, 64 a right angle, etc. This function can draw between + * any two bitmaps. + */ + + + +/* rotate_sprite_v_flip: (inlined) + * Similar to rotate_sprite(), except flips the sprite vertically first. + */ + + + +/* rotate_scaled_sprite: (inlined) + * Draws a sprite image onto a bitmap at the specified position, rotating + * it by the specified angle. The angle is a fixed point 16.16 number in + * the same format used by the fixed point trig routines, with 256 equal + * to a full circle, 64 a right angle, etc. This function can draw between + * any two bitmaps. + */ + + + +/* rotate_scaled_sprite_v_flip: (inlined) + * Similar to rotate_scaled_sprite(), except flips the sprite vertically first. + */ + + + +/* + * pivot_*() + */ + + + +/* pivot_sprite: (inlined) + * Rotates a sprite around the specified pivot centre point. + */ + + + +/* pivot_sprite_v_flip: (inlined) + * Similar to pivot_sprite(), except flips the sprite vertically first. + */ + + + +/* pivot_scaled_sprite: (inlined) + * Rotates and scales a sprite around the specified pivot centre point. + */ + + + +/* pivot_scaled_sprite_v_flip: (inlined) + * Similar to pivot_scaled_sprite(), except flips the sprite vertically first. + */ diff --git a/libsrc/allegro/src/unicode.c b/libsrc/allegro/src/unicode.c new file mode 100644 index 00000000000..cd34afd71fd --- /dev/null +++ b/libsrc/allegro/src/unicode.c @@ -0,0 +1,3166 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * String handling functions (UTF-8, Unicode, ASCII, etc). + * + * By Shawn Hargreaves. + * + * Case conversion functions improved by Ole Laursen. + * + * ustrrchr() and usprintf() improvements by Sven Sandberg. + * + * Peter Cech added some non-ASCII characters to uissspace(). + * + * size-aware (aka 'z') functions added by Eric Botcazou. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +/* this is a valid encoding in any of the supported formats */ +char empty_string[] = EMPTY_STRING; + + + +/* ascii_getc: + * Reads a character from an ASCII string. + */ +static int ascii_getc(AL_CONST char *s) +{ + return *((unsigned char *)s); +} + + + +/* ascii_getx: + * Reads a character from an ASCII string, advancing the pointer position. + */ +static int ascii_getx(char **s) +{ + return *((unsigned char *)((*s)++)); +} + + + +/* ascii_setc: + * Sets a character in an ASCII string. + */ +static int ascii_setc(char *s, int c) +{ + *s = c; + return 1; +} + + + +/* ascii_width: + * Returns the width of an ASCII character. + */ +static int ascii_width(AL_CONST char *s) +{ + return 1; +} + + + +/* ascii_cwidth: + * Returns the width of an ASCII character. + */ +static int ascii_cwidth(int c) +{ + return 1; +} + + + +/* ascii_isok: + * Checks whether this character can be encoded in 8-bit ASCII format. + */ +static int ascii_isok(int c) +{ + return ((c >= 0) && (c <= 255)); +} + + + +/* lookup table for implementing 8-bit codepage modes */ +static unsigned short _codepage_table[] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, +}; + + + +/* this default table reduces Latin-1 and Extended-A characters to 7 bits */ +static unsigned short _codepage_extras[] = +{ + 0xA1, '!', 0xA2, 'c', 0xA3, '#', 0xB5, 'u', 0xBF, '?', 0xC0, 'A', + 0xC1, 'A', 0xC2, 'A', 0xC3, 'A', 0xC4, 'A', 0xC5, 'A', 0xC6, 'A', + 0xC7, 'C', 0xC8, 'E', 0xC9, 'E', 0xCA, 'E', 0xCB, 'E', 0xCC, 'I', + 0xCD, 'I', 0xCE, 'I', 0xCF, 'I', 0xD0, 'D', 0xD1, 'N', 0xD2, 'O', + 0xD3, 'O', 0xD4, 'O', 0xD5, 'O', 0xD6, 'O', 0xD7, 'X', 0xD8, '0', + 0xD9, 'U', 0xDA, 'U', 0xDB, 'U', 0xDC, 'U', 0xDD, 'Y', 0xDE, 'P', + 0xDF, 'S', 0xE0, 'a', 0xE1, 'a', 0xE2, 'a', 0xE3, 'a', 0xE4, 'a', + 0xE5, 'a', 0xE6, 'a', 0xE7, 'c', 0xE8, 'e', 0xE9, 'e', 0xEA, 'e', + 0xEB, 'e', 0xEC, 'i', 0xED, 'i', 0xEE, 'i', 0xEF, 'i', 0xF0, 'o', + 0xF1, 'n', 0xF2, 'o', 0xF3, 'o', 0xF4, 'o', 0xF5, 'o', 0xF6, 'o', + 0xF8, 'o', 0xF9, 'u', 0xFA, 'u', 0xFB, 'u', 0xFC, 'u', 0xFD, 'y', + 0xFE, 'p', 0xFF, 'y', + + 0x100, 'A', 0x101, 'a', 0x102, 'A', 0x103, 'a', 0x104, 'A', + 0x105, 'a', 0x106, 'C', 0x107, 'c', 0x108, 'C', 0x109, 'c', + 0x10a, 'C', 0x10b, 'c', 0x10c, 'C', 0x10d, 'c', 0x10e, 'D', + 0x10f, 'd', 0x110, 'D', 0x111, 'd', 0x112, 'E', 0x113, 'e', + 0x114, 'E', 0x115, 'e', 0x116, 'E', 0x117, 'e', 0x118, 'E', + 0x119, 'e', 0x11a, 'E', 0x11b, 'e', 0x11c, 'G', 0x11d, 'g', + 0x11e, 'G', 0x11f, 'g', 0x120, 'G', 0x121, 'g', 0x122, 'G', + 0x123, 'g', 0x124, 'H', 0x125, 'h', 0x126, 'H', 0x127, 'h', + 0x128, 'I', 0x129, 'i', 0x12a, 'I', 0x12b, 'i', 0x12c, 'I', + 0x12d, 'i', 0x12e, 'I', 0x12f, 'i', 0x130, 'I', 0x131, 'i', + 0x134, 'J', 0x135, 'j', 0x136, 'K', 0x137, 'k', 0x138, 'K', + 0x139, 'L', 0x13a, 'l', 0x13b, 'L', 0x13c, 'l', 0x13d, 'L', + 0x13e, 'l', 0x13f, 'L', 0x140, 'l', 0x141, 'L', 0x142, 'l', + 0x143, 'N', 0x144, 'n', 0x145, 'N', 0x146, 'n', 0x147, 'N', + 0x148, 'n', 0x149, 'n', 0x14a, 'N', 0x14b, 'n', 0x14c, 'O', + 0x14d, 'o', 0x14e, 'O', 0x14f, 'o', 0x150, 'O', 0x151, 'o', + 0x154, 'R', 0x155, 'r', 0x156, 'R', 0x157, 'r', 0x158, 'R', + 0x159, 'r', 0x15a, 'S', 0x15b, 's', 0x15c, 'S', 0x15d, 's', + 0x15e, 'S', 0x15f, 's', 0x160, 'S', 0x161, 's', 0x162, 'T', + 0x163, 't', 0x164, 'T', 0x165, 't', 0x166, 'T', 0x167, 't', + 0x168, 'U', 0x169, 'u', 0x16a, 'U', 0x16b, 'u', 0x16c, 'U', + 0x16d, 'u', 0x16e, 'U', 0x16f, 'u', 0x170, 'U', 0x171, 'u', + 0x172, 'U', 0x173, 'u', 0x174, 'W', 0x175, 'w', 0x176, 'Y', + 0x177, 'y', 0x178, 'y', 0x179, 'Z', 0x17a, 'z', 0x17b, 'Z', + 0x17c, 'z', 0x17d, 'Z', 0x17e, 'z', 0 +}; + + + +/* access via pointers so they can be changed by the user */ +static AL_CONST unsigned short *codepage_table = _codepage_table; +static AL_CONST unsigned short *codepage_extras = _codepage_extras; + + + +/* ascii_cp_getc: + * Reads a character from an ASCII codepage string. + */ +static int ascii_cp_getc(AL_CONST char *s) +{ + return codepage_table[*((unsigned char *)s)]; +} + + + +/* ascii_cp_getx: + * Reads from an ASCII codepage string, advancing pointer position. + */ +static int ascii_cp_getx(char **s) +{ + return codepage_table[*((unsigned char *)((*s)++))]; +} + + + +/* ascii_cp_setc: + * Sets a character in an ASCII codepage string. + */ +static int ascii_cp_setc(char *s, int c) +{ + int i; + + for (i=0; i<256; i++) { + if (codepage_table[i] == c) { + *s = i; + return 1; + } + } + + if (codepage_extras) { + for (i=0; codepage_extras[i]; i+=2) { + if (codepage_extras[i] == c) { + *s = codepage_extras[i+1]; + return 1; + } + } + } + + *s = '^'; + return 1; +} + + + +/* ascii_cp_isok: + * Checks whether this character can be encoded in ASCII codepage format. + */ +static int ascii_cp_isok(int c) +{ + int i; + + for (i=0; i<256; i++) { + if (codepage_table[i] == c) + return TRUE; + } + + if (codepage_extras) { + for (i=0; codepage_extras[i]; i+=2) { + if (codepage_extras[i] == c) + return TRUE; + } + } + + return FALSE; +} + + + +/* unicode_getc: + * Reads a character from a Unicode string. + */ +static int unicode_getc(AL_CONST char *s) +{ + return *((unsigned short *)s); +} + + + +/* unicode_getx: + * Reads a character from a Unicode string, advancing the pointer position. + */ +static int unicode_getx(char **s) +{ + int c = *((unsigned short *)(*s)); + (*s) += sizeof(unsigned short); + return c; +} + + + +/* unicode_setc: + * Sets a character in a Unicode string. + */ +static int unicode_setc(char *s, int c) +{ + *((unsigned short *)s) = c; + return sizeof(unsigned short); +} + + + +/* unicode_width: + * Returns the width of a Unicode character. + */ +static int unicode_width(AL_CONST char *s) +{ + return sizeof(unsigned short); +} + + + +/* unicode_cwidth: + * Returns the width of a Unicode character. + */ +static int unicode_cwidth(int c) +{ + return sizeof(unsigned short); +} + + + +/* unicode_isok: + * Checks whether this character can be encoded in 16-bit Unicode format. + */ +static int unicode_isok(int c) +{ + return ((c >= 0) && (c <= 65535)); +} + + + +/* utf8_getc: + * Reads a character from a UTF-8 string. + */ +static int utf8_getc(AL_CONST char *s) +{ + int c = *((unsigned char *)(s++)); + int n, t; + + if (c & 0x80) { + n = 1; + while (c & (0x80>>n)) + n++; + + c &= (1<<(8-n))-1; + + while (--n > 0) { + t = *((unsigned char *)(s++)); + + if ((!(t&0x80)) || (t&0x40)) + return '^'; + + c = (c<<6) | (t&0x3F); + } + } + + return c; +} + + + +/* utf8_getx: + * Reads a character from a UTF-8 string, advancing the pointer position. + */ +static int utf8_getx(char **s) +{ + int c = *((unsigned char *)((*s)++)); + int n, t; + + if (c & 0x80) { + n = 1; + while (c & (0x80>>n)) + n++; + + c &= (1<<(8-n))-1; + + while (--n > 0) { + t = *((unsigned char *)((*s)++)); + + if ((!(t&0x80)) || (t&0x40)) { + (*s)--; + return '^'; + } + + c = (c<<6) | (t&0x3F); + } + } + + return c; +} + + + +/* utf8_setc: + * Sets a character in a UTF-8 string. + */ +static int utf8_setc(char *s, int c) +{ + int size, bits, b, i; + + if (c < 128) { + *s = c; + return 1; + } + + bits = 7; + while (c >= (1<>b; + + for (i=0; i>i); + + for (i=1; i>b)&0x3F); + } + + return size; +} + + + +/* utf8_width: + * Returns the width of a UTF-8 character. + */ +static int utf8_width(AL_CONST char *s) +{ + int c = *((unsigned char *)s); + int n = 1; + + if (c & 0x80) { + while (c & (0x80>>n)) + n++; + } + + return n; +} + + + +/* utf8_cwidth: + * Returns the width of a UTF-8 character. + */ +static int utf8_cwidth(int c) +{ + int size, bits, b; + + if (c < 128) + return 1; + + bits = 7; + while (c >= (1<id; + ugetc = info->u_getc; + ugetx = (int (*)(char **)) info->u_getx; + ugetxc = (int (*)(AL_CONST char **)) info->u_getx; + usetc = info->u_setc; + uwidth = info->u_width; + ucwidth = info->u_cwidth; + uisok = info->u_isok; + } +} + + + +/* get_uformat: + * Returns the current text encoding format. + */ +int get_uformat(void) +{ + return utype; +} + + + +/* register_uformat: + * Allows the user to hook in custom routines for supporting a new string + * encoding format. + */ +void register_uformat(int type, int (*ugetc)(AL_CONST char *s), int (*ugetx)(char **s), int (*usetc)(char *s, int c), int (*uwidth)(AL_CONST char *s), int (*ucwidth)(int c), int (*uisok)(int c), int uwidth_max) +{ + UTYPE_INFO *info = _find_utype(type); + + if (!info) + info = _find_utype(0); + + if (info) { + info->id = type; + info->u_getc = ugetc; + info->u_getx = ugetx; + info->u_setc = usetc; + info->u_width = uwidth; + info->u_cwidth = ucwidth; + info->u_isok = uisok; + info->u_width_max = uwidth_max; + } +} + + + +/* set_ucodepage: + * Sets lookup table data for the codepage conversion functions. + */ +void set_ucodepage(AL_CONST unsigned short *table, AL_CONST unsigned short *extras) +{ + ASSERT(table); + codepage_table = table; + codepage_extras = extras; +} + + + +/* need_uconvert: + * Decides whether a conversion is required to make this string be in the + * new type. No conversion will be needed if both types are the same, or + * when going from ASCII <-> UTF8 where the data is 7-bit clean. + */ +int need_uconvert(AL_CONST char *s, int type, int newtype) +{ + int c; + ASSERT(s); + + if (type == U_CURRENT) + type = utype; + + if (newtype == U_CURRENT) + newtype = utype; + + if (type == newtype) + return FALSE; + + if (((type == U_ASCII) || (type == U_UTF8)) && ((newtype == U_ASCII) || (newtype == U_UTF8))) { + do { + c = *((unsigned char *)(s++)); + if (!c) + return FALSE; + } while (c <= 127); + } + + return TRUE; +} + + + +/* uconvert_size: + * Returns the number of bytes this string will occupy when converted to + * the specified type. + */ +int uconvert_size(AL_CONST char *s, int type, int newtype) +{ + UTYPE_INFO *info, *outfo; + int size = 0; + int c; + ASSERT(s); + + info = _find_utype(type); + if (!info) + return 0; + + outfo = _find_utype(newtype); + if (!outfo) + return 0; + + size = 0; + + while ((c = info->u_getx((char **)&s)) != 0) + size += outfo->u_cwidth(c); + + return size + outfo->u_cwidth(0); +} + + + +/* do_uconvert: + * Converts a string from one format to another. + */ +void do_uconvert(AL_CONST char *s, int type, char *buf, int newtype, int size) +{ + UTYPE_INFO *info, *outfo; + int pos = 0; + int c; + ASSERT(s); + ASSERT(buf); + ASSERT(size > 0); + + info = _find_utype(type); + if (!info) + return; + + outfo = _find_utype(newtype); + if (!outfo) + return; + + size -= outfo->u_cwidth(0); + ASSERT(size >= 0); + + while ((c = info->u_getx((char**)&s)) != 0) { + if (!outfo->u_isok(c)) + c = '^'; + + size -= outfo->u_cwidth(c); + if (size < 0) + break; + + pos += outfo->u_setc(buf+pos, c); + } + + outfo->u_setc(buf+pos, 0); +} + + + +/* uconvert: + * Higher level version of do_uconvert(). This routine is intelligent + * enough to just return a copy of the input string if no conversion + * is required, and to use an internal static buffer if no user buffer + * is provided. + */ +char *uconvert(AL_CONST char *s, int type, char *buf, int newtype, int size) +{ + static char static_buf[1024]; + ASSERT(s); + ASSERT(size >= 0); + + if (!need_uconvert(s, type, newtype)) + return (char *)s; + + if (!buf) { + buf = static_buf; + size = sizeof(static_buf); + } + + do_uconvert(s, type, buf, newtype, size); + return buf; +} + + + +/* uoffset: + * Returns the offset in bytes from the start of the string to the + * character at the specified index. If the index is negative, counts + * backward from the end of the string (-1 returns an offset to the + * last character). + */ +int uoffset(AL_CONST char *s, int index) +{ + AL_CONST char *orig = s; + AL_CONST char *last; + ASSERT(s); + + if (index < 0) + index += ustrlen(s); + + while (index-- > 0) { + last = s; + if (!ugetxc(&s)) { + s = last; + break; + } + } + + return (long)s - (long)orig; +} + + + +/* ugetat: + * Returns the character from the specified index within the string. + */ +int ugetat(AL_CONST char *s, int index) +{ + ASSERT(s); + return ugetc(s + uoffset(s, index)); +} + + + +/* usetat: + * Modifies the character at the specified index within the string, + * handling adjustments for variable width data. Returns how far the + * rest of the string was moved. + */ +int usetat(char *s, int index, int c) +{ + int oldw, neww; + ASSERT(s); + + s += uoffset(s, index); + + oldw = uwidth(s); + neww = ucwidth(c); + + if (oldw != neww) + memmove(s+neww, s+oldw, ustrsizez(s+oldw)); + + usetc(s, c); + + return neww-oldw; +} + + + +/* uinsert: + * Inserts a character at the specified index within a string, sliding + * following data along to make room. Returns how far the data was moved. + */ +int uinsert(char *s, int index, int c) +{ + int w = ucwidth(c); + ASSERT(s); + + s += uoffset(s, index); + memmove(s+w, s, ustrsizez(s)); + usetc(s, c); + + return w; +} + + + +/* uremove: + * Removes the character at the specified index within the string, sliding + * following data back to make room. Returns how far the data was moved. + */ +int uremove(char *s, int index) +{ + int w; + ASSERT(s); + + s += uoffset(s, index); + w = uwidth(s); + memmove(s, s+w, ustrsizez(s+w)); + + return -w; +} + + + +/* uwidth_max: + * Returns the largest possible size of a character in the specified + * encoding format, in bytes. + */ +int uwidth_max(int type) +{ + UTYPE_INFO *info; + + info = _find_utype(type); + if (!info) + return 0; + + return info->u_width_max; +} + + + +/* utolower: + * Unicode-aware version of the ANSI tolower() function. + */ +int utolower(int c) +{ + if ((c >= 65 && c <= 90) || + (c >= 192 && c <= 214) || + (c >= 216 && c <= 222) || + (c >= 913 && c <= 929) || + (c >= 931 && c <= 939) || + (c >= 1040 && c <= 1071)) + return c + 32; + if ((c >= 393 && c <= 394)) + return c + 205; + if ((c >= 433 && c <= 434)) + return c + 217; + if ((c >= 904 && c <= 906)) + return c + 37; + if ((c >= 910 && c <= 911)) + return c + 63; + if ((c >= 1025 && c <= 1036) || + (c >= 1038 && c <= 1039)) + return c + 80; + if ((c >= 1329 && c <= 1366) || + (c >= 4256 && c <= 4293)) + return c + 48; + if ((c >= 7944 && c <= 7951) || + (c >= 7960 && c <= 7965) || + (c >= 7976 && c <= 7983) || + (c >= 7992 && c <= 7999) || + (c >= 8008 && c <= 8013) || + (c >= 8040 && c <= 8047) || + (c >= 8072 && c <= 8079) || + (c >= 8088 && c <= 8095) || + (c >= 8104 && c <= 8111) || + (c >= 8120 && c <= 8121) || + (c >= 8152 && c <= 8153) || + (c >= 8168 && c <= 8169)) + return c + -8; + if ((c >= 8122 && c <= 8123)) + return c + -74; + if ((c >= 8136 && c <= 8139)) + return c + -86; + if ((c >= 8154 && c <= 8155)) + return c + -100; + if ((c >= 8170 && c <= 8171)) + return c + -112; + if ((c >= 8184 && c <= 8185)) + return c + -128; + if ((c >= 8186 && c <= 8187)) + return c + -126; + if ((c >= 8544 && c <= 8559)) + return c + 16; + if ((c >= 9398 && c <= 9423)) + return c + 26; + + switch (c) { + case 256: + case 258: + case 260: + case 262: + case 264: + case 266: + case 268: + case 270: + case 272: + case 274: + case 276: + case 278: + case 280: + case 282: + case 284: + case 286: + case 288: + case 290: + case 292: + case 294: + case 296: + case 298: + case 300: + case 302: + case 306: + case 308: + case 310: + case 313: + case 315: + case 317: + case 319: + case 321: + case 323: + case 325: + case 327: + case 330: + case 332: + case 334: + case 336: + case 338: + case 340: + case 342: + case 344: + case 346: + case 348: + case 350: + case 352: + case 354: + case 356: + case 358: + case 360: + case 362: + case 364: + case 366: + case 368: + case 370: + case 372: + case 374: + case 377: + case 379: + case 381: + case 386: + case 388: + case 391: + case 395: + case 401: + case 408: + case 416: + case 418: + case 420: + case 423: + case 428: + case 431: + case 435: + case 437: + case 440: + case 444: + case 453: + case 456: + case 459: + case 461: + case 463: + case 465: + case 467: + case 469: + case 471: + case 473: + case 475: + case 478: + case 480: + case 482: + case 484: + case 486: + case 488: + case 490: + case 492: + case 494: + case 498: + case 500: + case 506: + case 508: + case 510: + case 512: + case 514: + case 516: + case 518: + case 520: + case 522: + case 524: + case 526: + case 528: + case 530: + case 532: + case 534: + case 994: + case 996: + case 998: + case 1000: + case 1002: + case 1004: + case 1006: + case 1120: + case 1122: + case 1124: + case 1126: + case 1128: + case 1130: + case 1132: + case 1134: + case 1136: + case 1138: + case 1140: + case 1142: + case 1144: + case 1146: + case 1148: + case 1150: + case 1152: + case 1168: + case 1170: + case 1172: + case 1174: + case 1176: + case 1178: + case 1180: + case 1182: + case 1184: + case 1186: + case 1188: + case 1190: + case 1192: + case 1194: + case 1196: + case 1198: + case 1200: + case 1202: + case 1204: + case 1206: + case 1208: + case 1210: + case 1212: + case 1214: + case 1217: + case 1219: + case 1223: + case 1227: + case 1232: + case 1234: + case 1236: + case 1238: + case 1240: + case 1242: + case 1244: + case 1246: + case 1248: + case 1250: + case 1252: + case 1254: + case 1256: + case 1258: + case 1262: + case 1264: + case 1266: + case 1268: + case 1272: + case 7680: + case 7682: + case 7684: + case 7686: + case 7688: + case 7690: + case 7692: + case 7694: + case 7696: + case 7698: + case 7700: + case 7702: + case 7704: + case 7706: + case 7708: + case 7710: + case 7712: + case 7714: + case 7716: + case 7718: + case 7720: + case 7722: + case 7724: + case 7726: + case 7728: + case 7730: + case 7732: + case 7734: + case 7736: + case 7738: + case 7740: + case 7742: + case 7744: + case 7746: + case 7748: + case 7750: + case 7752: + case 7754: + case 7756: + case 7758: + case 7760: + case 7762: + case 7764: + case 7766: + case 7768: + case 7770: + case 7772: + case 7774: + case 7776: + case 7778: + case 7780: + case 7782: + case 7784: + case 7786: + case 7788: + case 7790: + case 7792: + case 7794: + case 7796: + case 7798: + case 7800: + case 7802: + case 7804: + case 7806: + case 7808: + case 7810: + case 7812: + case 7814: + case 7816: + case 7818: + case 7820: + case 7822: + case 7824: + case 7826: + case 7828: + case 7840: + case 7842: + case 7844: + case 7846: + case 7848: + case 7850: + case 7852: + case 7854: + case 7856: + case 7858: + case 7860: + case 7862: + case 7864: + case 7866: + case 7868: + case 7870: + case 7872: + case 7874: + case 7876: + case 7878: + case 7880: + case 7882: + case 7884: + case 7886: + case 7888: + case 7890: + case 7892: + case 7894: + case 7896: + case 7898: + case 7900: + case 7902: + case 7904: + case 7906: + case 7908: + case 7910: + case 7912: + case 7914: + case 7916: + case 7918: + case 7920: + case 7922: + case 7924: + case 7926: + case 7928: + return c + 1; + case 304: + return c + -199; + case 376: + return c + -121; + case 385: + return c + 210; + case 390: + return c + 206; + case 398: + return c + 79; + case 399: + return c + 202; + case 400: + return c + 203; + case 403: + return c + 205; + case 404: + return c + 207; + case 406: + case 412: + return c + 211; + case 407: + return c + 209; + case 413: + return c + 213; + case 415: + return c + 214; + case 422: + case 425: + case 430: + return c + 218; + case 439: + return c + 219; + case 452: + case 455: + case 458: + case 497: + return c + 2; + case 902: + return c + 38; + case 908: + return c + 64; + case 8025: + case 8027: + case 8029: + case 8031: + return c + -8; + case 8124: + case 8140: + case 8188: + return c + -9; + case 8172: + return c + -7; + default: + return c; + } +} + + + +/* utoupper: + * Unicode-aware version of the ANSI toupper() function. + */ +int utoupper(int c) +{ + if ((c >= 97 && c <= 122) || + (c >= 224 && c <= 246) || + (c >= 248 && c <= 254) || + (c >= 945 && c <= 961) || + (c >= 963 && c <= 971) || + (c >= 1072 && c <= 1103)) + return c + -32; + if ((c >= 598 && c <= 599)) + return c + -205; + if ((c >= 650 && c <= 651)) + return c + -217; + if ((c >= 941 && c <= 943)) + return c + -37; + if ((c >= 973 && c <= 974)) + return c + -63; + if ((c >= 1105 && c <= 1116) || + (c >= 1118 && c <= 1119)) + return c + -80; + if ((c >= 1377 && c <= 1414)) + return c + -48; + if ((c >= 7936 && c <= 7943) || + (c >= 7952 && c <= 7957) || + (c >= 7968 && c <= 7975) || + (c >= 7984 && c <= 7991) || + (c >= 8000 && c <= 8005) || + (c >= 8032 && c <= 8039) || + (c >= 8064 && c <= 8071) || + (c >= 8080 && c <= 8087) || + (c >= 8096 && c <= 8103) || + (c >= 8112 && c <= 8113) || + (c >= 8144 && c <= 8145) || + (c >= 8160 && c <= 8161)) + return c + 8; + if ((c >= 8048 && c <= 8049)) + return c + 74; + if ((c >= 8050 && c <= 8053)) + return c + 86; + if ((c >= 8054 && c <= 8055)) + return c + 100; + if ((c >= 8056 && c <= 8057)) + return c + 128; + if ((c >= 8058 && c <= 8059)) + return c + 112; + if ((c >= 8060 && c <= 8061)) + return c + 126; + if ((c >= 8560 && c <= 8575)) + return c + -16; + if ((c >= 9424 && c <= 9449)) + return c + -26; + + switch (c) { + case 255: + return c + 121; + case 257: + case 259: + case 261: + case 263: + case 265: + case 267: + case 269: + case 271: + case 273: + case 275: + case 277: + case 279: + case 281: + case 283: + case 285: + case 287: + case 289: + case 291: + case 293: + case 295: + case 297: + case 299: + case 301: + case 303: + case 307: + case 309: + case 311: + case 314: + case 316: + case 318: + case 320: + case 322: + case 324: + case 326: + case 328: + case 331: + case 333: + case 335: + case 337: + case 339: + case 341: + case 343: + case 345: + case 347: + case 349: + case 351: + case 353: + case 355: + case 357: + case 359: + case 361: + case 363: + case 365: + case 367: + case 369: + case 371: + case 373: + case 375: + case 378: + case 380: + case 382: + case 387: + case 389: + case 392: + case 396: + case 402: + case 409: + case 417: + case 419: + case 421: + case 424: + case 429: + case 432: + case 436: + case 438: + case 441: + case 445: + case 453: + case 456: + case 459: + case 462: + case 464: + case 466: + case 468: + case 470: + case 472: + case 474: + case 476: + case 479: + case 481: + case 483: + case 485: + case 487: + case 489: + case 491: + case 493: + case 495: + case 498: + case 501: + case 507: + case 509: + case 511: + case 513: + case 515: + case 517: + case 519: + case 521: + case 523: + case 525: + case 527: + case 529: + case 531: + case 533: + case 535: + case 995: + case 997: + case 999: + case 1001: + case 1003: + case 1005: + case 1007: + case 1121: + case 1123: + case 1125: + case 1127: + case 1129: + case 1131: + case 1133: + case 1135: + case 1137: + case 1139: + case 1141: + case 1143: + case 1145: + case 1147: + case 1149: + case 1151: + case 1153: + case 1169: + case 1171: + case 1173: + case 1175: + case 1177: + case 1179: + case 1181: + case 1183: + case 1185: + case 1187: + case 1189: + case 1191: + case 1193: + case 1195: + case 1197: + case 1199: + case 1201: + case 1203: + case 1205: + case 1207: + case 1209: + case 1211: + case 1213: + case 1215: + case 1218: + case 1220: + case 1224: + case 1228: + case 1233: + case 1235: + case 1237: + case 1239: + case 1241: + case 1243: + case 1245: + case 1247: + case 1249: + case 1251: + case 1253: + case 1255: + case 1257: + case 1259: + case 1263: + case 1265: + case 1267: + case 1269: + case 1273: + case 7681: + case 7683: + case 7685: + case 7687: + case 7689: + case 7691: + case 7693: + case 7695: + case 7697: + case 7699: + case 7701: + case 7703: + case 7705: + case 7707: + case 7709: + case 7711: + case 7713: + case 7715: + case 7717: + case 7719: + case 7721: + case 7723: + case 7725: + case 7727: + case 7729: + case 7731: + case 7733: + case 7735: + case 7737: + case 7739: + case 7741: + case 7743: + case 7745: + case 7747: + case 7749: + case 7751: + case 7753: + case 7755: + case 7757: + case 7759: + case 7761: + case 7763: + case 7765: + case 7767: + case 7769: + case 7771: + case 7773: + case 7775: + case 7777: + case 7779: + case 7781: + case 7783: + case 7785: + case 7787: + case 7789: + case 7791: + case 7793: + case 7795: + case 7797: + case 7799: + case 7801: + case 7803: + case 7805: + case 7807: + case 7809: + case 7811: + case 7813: + case 7815: + case 7817: + case 7819: + case 7821: + case 7823: + case 7825: + case 7827: + case 7829: + case 7841: + case 7843: + case 7845: + case 7847: + case 7849: + case 7851: + case 7853: + case 7855: + case 7857: + case 7859: + case 7861: + case 7863: + case 7865: + case 7867: + case 7869: + case 7871: + case 7873: + case 7875: + case 7877: + case 7879: + case 7881: + case 7883: + case 7885: + case 7887: + case 7889: + case 7891: + case 7893: + case 7895: + case 7897: + case 7899: + case 7901: + case 7903: + case 7905: + case 7907: + case 7909: + case 7911: + case 7913: + case 7915: + case 7917: + case 7919: + case 7921: + case 7923: + case 7925: + case 7927: + case 7929: + return c + -1; + case 305: + return c + -232; + case 383: + return c + -300; + case 454: + case 457: + case 460: + case 499: + return c + -2; + case 477: + case 1010: + return c + -79; + case 595: + return c + -210; + case 596: + return c + -206; + case 601: + return c + -202; + case 603: + return c + -203; + case 608: + return c + -205; + case 611: + return c + -207; + case 616: + return c + -209; + case 617: + case 623: + return c + -211; + case 626: + return c + -213; + case 629: + return c + -214; + case 640: + case 643: + case 648: + return c + -218; + case 658: + return c + -219; + case 837: + return c + 84; + case 940: + return c + -38; + case 962: + return c + -31; + case 972: + return c + -64; + case 976: + return c + -62; + case 977: + return c + -57; + case 981: + return c + -47; + case 982: + return c + -54; + case 1008: + return c + -86; + case 1009: + return c + -80; + case 7835: + return c + -59; + case 8017: + case 8019: + case 8021: + case 8023: + return c + 8; + case 8115: + case 8131: + case 8179: + return c + 9; + case 8126: + return c + -7205; + case 8165: + return c + 7; + default: + return c; + } +} + + + +/* uisspace: + * Unicode-aware version of the ANSI isspace() function. + */ +int uisspace(int c) +{ + return ((c == ' ') || (c == '\t') || (c == '\r') || + (c == '\n') || (c == '\f') || (c == '\v') || + (c == 0x1680) || ((c >= 0x2000) && (c <= 0x200A)) || + (c == 0x2028) || (c == 0x202f) || (c == 0x3000)); +} + + + +/* uisdigit: + * Unicode-aware version of the ANSI isdigit() function. + */ +int uisdigit(int c) +{ + return ((c >= '0') && (c <= '9')); +} + + + +/* ustrdup: + * Returns a newly allocated copy of the src string, which must later be + * freed by the caller. This function is for external use by Allegro + * clients only. Internal code should use _al_ustrdup(). + */ +char *_ustrdup(AL_CONST char *src, AL_METHOD(void *, malloc_func, (size_t))) +{ + char *s; + int size; + ASSERT(src); + ASSERT(malloc_func); + + size = ustrsizez(src); + + s = malloc_func(size); + if (s) + ustrzcpy(s, size, src); + else + *allegro_errno = ENOMEM; + + return s; +} + + + +/* _al_ustrdup: + * Returns a newly allocated copy of the src string, which must later be + * freed by the caller using _AL_FREE(). This function is for internal use + * by Allegro clients only. External code should use ustrdup(). + */ +char *_al_ustrdup(AL_CONST char *src) +{ + int size; + char *newstring; + ASSERT(src); + + size = ustrsizez(src); + newstring = _AL_MALLOC(size); + + if (newstring) + ustrzcpy(newstring, size, src); + + return newstring; +} + + + +/* ustrsize: + * Returns the size of the specified string in bytes, not including the + * trailing zero. + */ +int ustrsize(AL_CONST char *s) +{ + AL_CONST char *orig = s; + AL_CONST char *last; + ASSERT(s); + + do { + last = s; + } while (ugetxc(&s) != 0); + + return (long)last - (long)orig; +} + + + +/* ustrsizez: + * Returns the size of the specified string in bytes, including the + * trailing zero. + */ +int ustrsizez(AL_CONST char *s) +{ + AL_CONST char *orig = s; + ASSERT(s); + + do { + } while (ugetxc(&s) != 0); + + return (long)s - (long)orig; +} + + + +/* ustrzcpy: + * Enhanced Unicode-aware version of the ANSI strcpy() function + * that can handle the size (in bytes) of the destination string. + * The raw Unicode-aware version of ANSI strcpy() is defined as: + * #define ustrcpy(dest, src) ustrzcpy(dest, INT_MAX, src) + */ +char *ustrzcpy(char *dest, int size, AL_CONST char *src) +{ + int pos = 0; + int c; + ASSERT(dest); + ASSERT(src); + ASSERT(size > 0); + + size -= ucwidth(0); + ASSERT(size >= 0); + + while ((c = ugetxc(&src)) != 0) { + size -= ucwidth(c); + if (size < 0) + break; + + pos += usetc(dest+pos, c); + } + + usetc(dest+pos, 0); + + return dest; +} + + + +/* ustrzcat: + * Enhanced Unicode-aware version of the ANSI strcat() function + * that can handle the size (in bytes) of the destination string. + * The raw Unicode-aware version of ANSI strcat() is defined as: + * #define ustrcat(dest, src) ustrzcat(dest, INT_MAX, src) + */ +char *ustrzcat(char *dest, int size, AL_CONST char *src) +{ + int pos; + int c; + ASSERT(dest); + ASSERT(src); + ASSERT(size > 0); + + pos = ustrsize(dest); + size -= pos + ucwidth(0); + ASSERT(size >= 0); + + while ((c = ugetxc(&src)) != 0) { + size -= ucwidth(c); + if (size < 0) + break; + + pos += usetc(dest+pos, c); + } + + usetc(dest+pos, 0); + + return dest; +} + + + +/* ustrlen: + * Unicode-aware version of the ANSI strlen() function. + */ +int ustrlen(AL_CONST char *s) +{ + int c = 0; + ASSERT(s); + + while (ugetxc(&s)) + c++; + + return c; +} + + + +/* ustrcmp: + * Unicode-aware version of the ANSI strcmp() function. + */ +int ustrcmp(AL_CONST char *s1, AL_CONST char *s2) +{ + int c1, c2; + ASSERT(s1); + ASSERT(s2); + + for (;;) { + c1 = ugetxc(&s1); + c2 = ugetxc(&s2); + + if (c1 != c2) + return c1 - c2; + + if (!c1) + return 0; + } +} + + + +/* ustrzncpy: + * Enhanced Unicode-aware version of the ANSI strncpy() function + * that can handle the size (in bytes) of the destination string. + * The raw Unicode-aware version of ANSI strncpy() is defined as: + * #define ustrncpy(dest, src, n) ustrzncpy(dest, INT_MAX, src, n) + */ +char *ustrzncpy(char *dest, int size, AL_CONST char *src, int n) +{ + int pos = 0, len = 0; + int ansi_oddness = FALSE; + int c; + ASSERT(dest); + ASSERT(src); + ASSERT(size > 0); + ASSERT(n >= 0); + + /* detect raw ustrncpy() call */ + if (size == INT_MAX) + ansi_oddness = TRUE; + + size -= ucwidth(0); + ASSERT(size >= 0); + + /* copy at most n characters */ + while (((c = ugetxc(&src)) != 0) && (len < n)) { + size -= ucwidth(c); + if (size<0) + break; + + pos += usetc(dest+pos, c); + len++; + } + + /* pad with NULL characters */ + while (len < n) { + size -= ucwidth(0); + if (size < 0) + break; + + pos += usetc(dest+pos, 0); + len++; + } + + /* ANSI C doesn't append the terminating NULL character */ + if (!ansi_oddness) + usetc(dest+pos, 0); + + return dest; +} + + + +/* ustrzncat: + * Enhanced Unicode-aware version of the ANSI strncat() function + * that can handle the size (in bytes) of the destination string. + * The raw Unicode-aware version of ANSI strncat() is defined as: + * #define ustrncat(dest, src, n) ustrzncat(dest, INT_MAX, src, n) + */ +char *ustrzncat(char *dest, int size, AL_CONST char *src, int n) +{ + int pos, len = 0; + int c; + ASSERT(dest); + ASSERT(src); + ASSERT(size >= 0); + ASSERT(n >= 0); + + pos = ustrsize(dest); + size -= pos + ucwidth(0); + + while (((c = ugetxc(&src)) != 0) && (len < n)) { + size -= ucwidth(c); + if (size<0) + break; + + pos += usetc(dest+pos, c); + len++; + } + + usetc(dest+pos, 0); + + return dest; +} + + + +/* ustrncmp: + * Unicode-aware version of the ANSI strncmp() function. + */ +int ustrncmp(AL_CONST char *s1, AL_CONST char *s2, int n) +{ + int c1, c2; + ASSERT(s1); + ASSERT(s2); + + if (n <= 0) + return 0; + + for (;;) { + c1 = ugetxc(&s1); + c2 = ugetxc(&s2); + + if (c1 != c2) + return c1 - c2; + + if ((!c1) || (--n <= 0)) + return 0; + } +} + + + +/* ustricmp: + * Unicode-aware version of the DJGPP stricmp() function. + */ +int ustricmp(AL_CONST char *s1, AL_CONST char *s2) +{ + int c1, c2; + ASSERT(s1); + ASSERT(s2); + + for (;;) { + c1 = utolower(ugetxc(&s1)); + c2 = utolower(ugetxc(&s2)); + + if (c1 != c2) + return c1 - c2; + + if (!c1) + return 0; + } +} + + + +/* ustrnicmp: + * Unicode-aware version of the DJGPP strnicmp() function. + */ +int ustrnicmp(AL_CONST char *s1, AL_CONST char *s2, int n) +{ + int c1, c2; + ASSERT(s1); + ASSERT(s2); + + if (n <= 0) + return 0; + + for (;;) { + c1 = utolower(ugetxc(&s1)); + c2 = utolower(ugetxc(&s2)); + + if (c1 != c2) + return c1 - c2; + + if ((!c1) || (--n <= 0)) + return 0; + } +} + + + +/* ustrlwr: + * Unicode-aware version of the ANSI strlwr() function. + */ +char *ustrlwr(char *s) +{ + int pos = 0; + int c, lc; + ASSERT(s); + + while ((c = ugetc(s+pos)) != 0) { + lc = utolower(c); + + if (lc != c) + usetat(s+pos, 0, lc); + + pos += uwidth(s+pos); + } + + return s; +} + + + +/* ustrupr: + * Unicode-aware version of the ANSI strupr() function. + */ +char *ustrupr(char *s) +{ + int pos = 0; + int c, uc; + ASSERT(s); + + while ((c = ugetc(s+pos)) != 0) { + uc = utoupper(c); + + if (uc != c) + usetat(s+pos, 0, uc); + + pos += uwidth(s+pos); + } + + return s; +} + + + +/* ustrchr: + * Unicode-aware version of the ANSI strchr() function. + */ +char *ustrchr(AL_CONST char *s, int c) +{ + int d; + ASSERT(s); + + while ((d = ugetc(s)) != 0) { + if (c == d) + return (char *)s; + + s += uwidth(s); + } + + if (!c) + return (char *)s; + + return NULL; +} + + + +/* ustrrchr: + * Unicode-aware version of the ANSI strrchr() function. + */ +char *ustrrchr(AL_CONST char *s, int c) +{ + AL_CONST char *last_match = NULL; + int c1, pos = 0; + ASSERT(s); + + for (c1=ugetc(s); c1; c1=ugetc(s+pos)) { + if (c1 == c) + last_match = s + pos; + + pos += ucwidth(c1); + } + + return (char *)last_match; +} + + + +/* ustrstr: + * Unicode-aware version of the ANSI strstr() function. + */ +char *ustrstr(AL_CONST char *s1, AL_CONST char *s2) +{ + int len; + ASSERT(s1); + ASSERT(s2); + + len = ustrlen(s2); + while (ugetc(s1)) { + if (ustrncmp(s1, s2, len) == 0) + return (char *)s1; + + s1 += uwidth(s1); + } + + return NULL; +} + + + +/* ustrpbrk: + * Unicode-aware version of the ANSI strpbrk() function. + */ +char *ustrpbrk(AL_CONST char *s, AL_CONST char *set) +{ + AL_CONST char *setp; + int c, d; + ASSERT(s); + ASSERT(set); + + while ((c = ugetc(s)) != 0) { + setp = set; + + while ((d = ugetxc(&setp)) != 0) { + if (c == d) + return (char *)s; + } + + s += uwidth(s); + } + + return NULL; +} + + + +/* ustrtok: + * Unicode-aware version of the ANSI strtok() function. + */ +char *ustrtok(char *s, AL_CONST char *set) +{ + static char *last = NULL; + + return ustrtok_r(s, set, &last); +} + + + +/* ustrtok_r: + * Unicode-aware version of the strtok_r() function. + */ +char *ustrtok_r(char *s, AL_CONST char *set, char **last) +{ + char *prev_str, *tok; + AL_CONST char *setp; + int c, sc; + + ASSERT(last); + + if (!s) { + s = *last; + + if (!s) + return NULL; + } + + skip_leading_delimiters: + + prev_str = s; + c = ugetx(&s); + + setp = set; + + while ((sc = ugetxc(&setp)) != 0) { + if (c == sc) + goto skip_leading_delimiters; + } + + if (!c) { + *last = NULL; + return NULL; + } + + tok = prev_str; + + for (;;) { + prev_str = s; + c = ugetx(&s); + + setp = set; + + do { + sc = ugetxc(&setp); + if (sc == c) { + if (!c) { + *last = NULL; + return tok; + } + else { + s += usetat(prev_str, 0, 0); + *last = s; + return tok; + } + } + } while (sc); + } +} + + + +/* uatof: + * Unicode-aware version of the ANSI atof() function. No need to bother + * implementing this ourselves, since all floating point numbers are + * valid ASCII in any case. + */ +double uatof(AL_CONST char *s) +{ + char tmp[64]; + ASSERT(s); + return atof(uconvert_toascii(s, tmp)); +} + + + +/* ustrtol: + * Unicode-aware version of the ANSI strtol() function. Note the + * nicely bodged implementation :-) + */ +long ustrtol(AL_CONST char *s, char **endp, int base) +{ + char tmp[64]; + char *myendp; + long ret; + char *t; + ASSERT(s); + + t = uconvert_toascii(s, tmp); + + ret = strtol(t, &myendp, base); + + if (endp) + *endp = (char *)s + uoffset(s, (long)myendp - (long)t); + + return ret; +} + + + +/* ustrtod: + * Unicode-aware version of the ANSI strtod() function. Note the + * nicely bodged implementation :-) + */ +double ustrtod(AL_CONST char *s, char **endp) +{ + char tmp[64]; + char *myendp; + double ret; + char *t; + ASSERT(s); + + t = uconvert_toascii(s, tmp); + + ret = strtod(t, &myendp); + + if (endp) + *endp = (char *)s + uoffset(s, (long)myendp - (long)t); + + return ret; +} + + + +/* ustrerror: + * Fetch the error description from the OS and convert to Unicode. + */ +AL_CONST char *ustrerror(int err) +{ + AL_CONST char *s = strerror(err); + static char tmp[1024]; + return uconvert_ascii(s, tmp); +} + + + +/*******************************************************************/ +/*** Unicode-aware sprintf() functions ***/ +/*******************************************************************/ + + +/* information about the current format conversion mode */ +typedef struct SPRINT_INFO +{ + int flags; + int field_width; + int precision; + int num_special; +} SPRINT_INFO; + + + +#define SPRINT_FLAG_LEFT_JUSTIFY 1 +#define SPRINT_FLAG_FORCE_PLUS_SIGN 2 +#define SPRINT_FLAG_FORCE_SPACE 4 +#define SPRINT_FLAG_ALTERNATE_CONVERSION 8 +#define SPRINT_FLAG_PAD_ZERO 16 +#define SPRINT_FLAG_SHORT_INT 32 +#define SPRINT_FLAG_LONG_INT 64 +#define SPRINT_FLAG_LONG_DOUBLE 128 +#define SPRINT_FLAG_LONG_LONG 256 + + + +/* decoded string argument type */ +typedef struct STRING_ARG +{ + char *data; + int size; /* in bytes without the terminating '\0' */ + struct STRING_ARG *next; +} STRING_ARG; + + + +/* LONGEST: + * 64-bit integers on platforms that support it, 32-bit otherwise. + */ +#ifdef LONG_LONG + #define LONGEST LONG_LONG +#else + #define LONGEST long +#endif + + + +/* va_int: + * Helper for reading an integer from the varargs list. + */ +#ifdef LONG_LONG + + #define va_int(args, flags) \ + ( \ + ((flags) & SPRINT_FLAG_SHORT_INT) ? \ + va_arg(args, signed int) \ + : \ + (((flags) & SPRINT_FLAG_LONG_LONG) ? \ + va_arg(args, signed LONG_LONG) \ + : \ + (((flags) & SPRINT_FLAG_LONG_INT) ? \ + va_arg(args, signed long int) \ + : \ + va_arg(args, signed int))) \ + ) + +#else + + #define va_int(args, flags) \ + ( \ + ((flags) & SPRINT_FLAG_SHORT_INT) ? \ + va_arg(args, signed int) \ + : \ + (((flags) & SPRINT_FLAG_LONG_INT) ? \ + va_arg(args, signed long int) \ + : \ + va_arg(args, signed int)) \ + ) + +#endif + + + +/* va_uint: + * Helper for reading an unsigned integer from the varargs list. + */ +#ifdef LONG_LONG + + #define va_uint(args, flags) \ + ( \ + ((flags) & SPRINT_FLAG_SHORT_INT) ? \ + va_arg(args, unsigned int) \ + : \ + (((flags) & SPRINT_FLAG_LONG_LONG) ? \ + va_arg(args, unsigned LONG_LONG) \ + : \ + (((flags) & SPRINT_FLAG_LONG_INT) ? \ + va_arg(args, unsigned long int) \ + : \ + va_arg(args, unsigned int))) \ + ) + +#else + + #define va_uint(args, flags) \ + ( \ + ((flags) & SPRINT_FLAG_SHORT_INT) ? \ + va_arg(args, unsigned int) \ + : \ + (((flags) & SPRINT_FLAG_LONG_INT) ? \ + va_arg(args, unsigned long int) \ + : \ + va_arg(args, unsigned int)) \ + ) + +#endif + + + +/* sprint_char: + * Helper for formatting (!) a character. + */ +static int sprint_char(STRING_ARG *string_arg, SPRINT_INFO *info, long val) +{ + int pos = 0; + + /* 1 character max for... a character */ + string_arg->data = _AL_MALLOC((MAX(1, info->field_width) * uwidth_max(U_CURRENT) + + ucwidth(0)) * sizeof(char)); + + pos += usetc(string_arg->data, val); + + string_arg->size = pos; + usetc(string_arg->data+pos, 0); + + return 1; +} + + + +/* sprint_i: + * Worker function for formatting integers. + */ +static int sprint_i(STRING_ARG *string_arg, unsigned LONGEST val, int precision) +{ + char tmp[24]; /* for 64-bit integers */ + int i = 0, pos = string_arg->size; + int len; + + do { + tmp[i++] = val % 10; + val /= 10; + } while (val); + + for (len=i; lendata+pos, '0'); + + while (i > 0) + pos += usetc(string_arg->data+pos, tmp[--i] + '0'); + + string_arg->size = pos; + usetc(string_arg->data+pos, 0); + + return len; +} + + + +/* sprint_plus_sign: + * Helper to add a plus sign or space in front of a number. + */ +#define sprint_plus_sign(len) \ +{ \ + if (info->flags & SPRINT_FLAG_FORCE_PLUS_SIGN) { \ + pos += usetc(string_arg->data+pos, '+'); \ + len++; \ + } \ + else if (info->flags & SPRINT_FLAG_FORCE_SPACE) { \ + pos += usetc(string_arg->data+pos, ' '); \ + len++; \ + } \ +} + + + +/* sprint_int: + * Helper for formatting a signed integer. + */ +static int sprint_int(STRING_ARG *string_arg, SPRINT_INFO *info, LONGEST val) +{ + int pos = 0, len = 0; + + /* 24 characters max for a 64-bit integer */ + string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + + ucwidth(0)) * sizeof(char)); + + if (val < 0) { + val = -val; + pos += usetc(string_arg->data+pos, '-'); + len++; + } + else + sprint_plus_sign(len); + + info->num_special = len; + + string_arg->size = pos; + + return sprint_i(string_arg, val, info->precision) + info->num_special; +} + + + +/* sprint_unsigned: + * Helper for formatting an unsigned integer. + */ +static int sprint_unsigned(STRING_ARG *string_arg, SPRINT_INFO *info, unsigned LONGEST val) +{ + int pos = 0; + + /* 24 characters max for a 64-bit integer */ + string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + + ucwidth(0)) * sizeof(char)); + + sprint_plus_sign(info->num_special); + + string_arg->size = pos; + + return sprint_i(string_arg, val, info->precision) + info->num_special; +} + + + +/* sprint_hex: + * Helper for formatting a hex integer. + */ +static int sprint_hex(STRING_ARG *string_arg, SPRINT_INFO *info, int caps, unsigned LONGEST val) +{ + static char hex_digit_caps[] = "0123456789ABCDEF"; + static char hex_digit[] = "0123456789abcdef"; + + char tmp[24]; /* for 64-bit integers */ + char *table; + int pos = 0, i = 0; + int len; + + /* 24 characters max for a 64-bit integer */ + string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + + ucwidth(0)) * sizeof(char)); + + sprint_plus_sign(info->num_special); + + if (info->flags & SPRINT_FLAG_ALTERNATE_CONVERSION) { + pos += usetc(string_arg->data+pos, '0'); + pos += usetc(string_arg->data+pos, 'x'); + info->num_special += 2; + } + + do { + tmp[i++] = val & 15; + val >>= 4; + } while (val); + + for (len=i; lenprecision; len++) + pos += usetc(string_arg->data+pos, '0'); + + if (caps) + table = hex_digit_caps; + else + table = hex_digit; + + while (i > 0) + pos += usetc(string_arg->data+pos, table[(int)tmp[--i]]); + + string_arg->size = pos; + usetc(string_arg->data+pos, 0); + + return len + info->num_special; +} + + + +/* sprint_octal: + * Helper for formatting an octal integer. + */ +static int sprint_octal(STRING_ARG *string_arg, SPRINT_INFO *info, unsigned LONGEST val) +{ + char tmp[24]; /* for 64-bit integers */ + int pos = 0, i = 0; + int len; + + /* 24 characters max for a 64-bit integer */ + string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + + ucwidth(0)) * sizeof(char)); + + sprint_plus_sign(info->num_special); + + if (info->flags & SPRINT_FLAG_ALTERNATE_CONVERSION) { + pos += usetc(string_arg->data+pos, '0'); + info->num_special++; + } + + do { + tmp[i++] = val & 7; + val >>= 3; + } while (val); + + for (len=i; lenprecision; len++) + pos += usetc(string_arg->data+pos, '0'); + + while (i > 0) + pos += usetc(string_arg->data+pos, tmp[--i] + '0'); + + string_arg->size = pos; + usetc(string_arg->data+pos, 0); + + return len + info->num_special; +} + + + +/* sprint_float: + * Helper for formatting a float (piggyback on the libc implementation). + */ +static int sprint_float(STRING_ARG *string_arg, SPRINT_INFO *info, double val, int conversion) +{ + char format[256], tmp[256]; + int len = 0, size; + + format[len++] = '%'; + + if (info->flags & SPRINT_FLAG_LEFT_JUSTIFY) + format[len++] = '-'; + + if (info->flags & SPRINT_FLAG_FORCE_PLUS_SIGN) + format[len++] = '+'; + + if (info->flags & SPRINT_FLAG_FORCE_SPACE) + format[len++] = ' '; + + if (info->flags & SPRINT_FLAG_ALTERNATE_CONVERSION) + format[len++] = '#'; + + if (info->flags & SPRINT_FLAG_PAD_ZERO) + format[len++] = '0'; + + if (info->field_width > 0) + len += sprintf(format+len, "%d", info->field_width); + + if (info->precision >= 0) + len += sprintf(format+len, ".%d", info->precision); + + format[len++] = conversion; + format[len] = 0; + + len = sprintf(tmp, format, val); + size = len * uwidth_max(U_CURRENT) + ucwidth(0); + + string_arg->data = _AL_MALLOC(size * sizeof(char)); + + do_uconvert(tmp, U_ASCII, string_arg->data, U_CURRENT, size); + + info->field_width = 0; + + string_arg->size = ustrsize(string_arg->data); + + return len; +} + + + +/* sprint_string: + * Helper for formatting a string. + */ +static int sprint_string(STRING_ARG *string_arg, SPRINT_INFO *info, AL_CONST char *s) +{ + int pos = 0, len = 0; + int c; + + string_arg->data = _AL_MALLOC((MAX(ustrlen(s), info->field_width) * uwidth_max(U_CURRENT) + + ucwidth(0)) * sizeof(char)); + + while ((c = ugetxc(&s)) != 0) { + if ((info->precision >= 0) && (len >= info->precision)) + break; + + pos += usetc(string_arg->data+pos, c); + len++; + } + + string_arg->size = pos; + usetc(string_arg->data+pos, 0); + + return len; +} + + + +/* decode_format_string: + * Worker function for decoding the format string (with those pretty '%' characters) + */ +static int decode_format_string(char *buf, STRING_ARG *string_arg, AL_CONST char *format, va_list args) +{ + SPRINT_INFO info; + int *pstr_pos; + int done, slen, c, i, pos; + int shift, shiftbytes, shiftfiller; + int len = 0; + + while ((c = ugetxc(&format)) != 0) { + + if (c == '%') { + if ((c = ugetc(format)) == '%') { + /* percent sign escape */ + format += uwidth(format); + buf += usetc(buf, '%'); + buf += usetc(buf, '%'); + len++; + } + else { + /* format specifier */ + #define NEXT_C() \ + { \ + format += uwidth(format); \ + c = ugetc(format); \ + } + + /* set default conversion flags */ + info.flags = 0; + info.field_width = 0; + info.precision = -1; + info.num_special = 0; + + /* check for conversion flags */ + done = FALSE; + + do { + switch (c) { + + case '-': + info.flags |= SPRINT_FLAG_LEFT_JUSTIFY; + NEXT_C(); + break; + + case '+': + info.flags |= SPRINT_FLAG_FORCE_PLUS_SIGN; + NEXT_C(); + break; + + case ' ': + info.flags |= SPRINT_FLAG_FORCE_SPACE; + NEXT_C(); + break; + + case '#': + info.flags |= SPRINT_FLAG_ALTERNATE_CONVERSION; + NEXT_C(); + break; + + case '0': + info.flags |= SPRINT_FLAG_PAD_ZERO; + NEXT_C(); + break; + + default: + done = TRUE; + break; + } + + } while (!done); + + /* check for a field width specifier */ + if (c == '*') { + NEXT_C(); + info.field_width = va_arg(args, int); + if (info.field_width < 0) { + info.flags |= SPRINT_FLAG_LEFT_JUSTIFY; + info.field_width = -info.field_width; + } + } + else if ((c >= '0') && (c <= '9')) { + info.field_width = 0; + do { + info.field_width *= 10; + info.field_width += c - '0'; + NEXT_C(); + } while ((c >= '0') && (c <= '9')); + } + + /* check for a precision specifier */ + if (c == '.') + NEXT_C(); + + if (c == '*') { + NEXT_C(); + info.precision = va_arg(args, int); + if (info.precision < 0) + info.precision = 0; + } + else if ((c >= '0') && (c <= '9')) { + info.precision = 0; + do { + info.precision *= 10; + info.precision += c - '0'; + NEXT_C(); + } while ((c >= '0') && (c <= '9')); + } + + /* check for size qualifiers */ + done = FALSE; + + do { + switch (c) { + + case 'h': + info.flags |= SPRINT_FLAG_SHORT_INT; + NEXT_C(); + break; + + case 'l': + if (info.flags & SPRINT_FLAG_LONG_INT) + info.flags |= SPRINT_FLAG_LONG_LONG; + else + info.flags |= SPRINT_FLAG_LONG_INT; + NEXT_C(); + break; + + case 'L': + info.flags |= (SPRINT_FLAG_LONG_DOUBLE | SPRINT_FLAG_LONG_LONG); + NEXT_C(); + break; + + default: + done = TRUE; + break; + } + + } while (!done); + + /* format the data */ + switch (c) { + + case 'c': + /* character */ + slen = sprint_char(string_arg, &info, va_arg(args, int)); + NEXT_C(); + break; + + case 'd': + case 'i': + /* signed integer */ + slen = sprint_int(string_arg, &info, va_int(args, info.flags)); + NEXT_C(); + break; + + case 'D': + /* signed long integer */ + slen = sprint_int(string_arg, &info, va_int(args, info.flags | SPRINT_FLAG_LONG_INT)); + NEXT_C(); + break; + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + /* double */ + if (info.flags & SPRINT_FLAG_LONG_DOUBLE) + slen = sprint_float(string_arg, &info, va_arg(args, long double), c); + else + slen = sprint_float(string_arg, &info, va_arg(args, double), c); + NEXT_C(); + break; + + case 'n': + /* store current string position */ + pstr_pos = va_arg(args, int *); + *pstr_pos = len; + slen = -1; + NEXT_C(); + break; + + case 'o': + /* unsigned octal integer */ + slen = sprint_octal(string_arg, &info, va_uint(args, info.flags)); + NEXT_C(); + break; + + case 'p': + /* pointer */ + slen = sprint_hex(string_arg, &info, FALSE, (unsigned long)(va_arg(args, void *))); + NEXT_C(); + break; + + case 's': + /* string */ + slen = sprint_string(string_arg, &info, va_arg(args, char *)); + NEXT_C(); + break; + + case 'u': + /* unsigned integer */ + slen = sprint_unsigned(string_arg, &info, va_uint(args, info.flags)); + NEXT_C(); + break; + + case 'U': + /* unsigned long integer */ + slen = sprint_unsigned(string_arg, &info, va_uint(args, info.flags | SPRINT_FLAG_LONG_INT)); + NEXT_C(); + break; + + case 'x': + case 'X': + /* unsigned hex integer */ + slen = sprint_hex(string_arg, &info, (c == 'X'), va_uint(args, info.flags)); + NEXT_C(); + break; + + default: + /* weird shit... */ + slen = -1; + break; + } + + if (slen >= 0) { + if (slen < info.field_width) { + if (info.flags & SPRINT_FLAG_LEFT_JUSTIFY) { + /* left align the result */ + pos = string_arg->size; + while (slen < info.field_width) { + pos += usetc(string_arg->data+pos, ' '); + slen++; + } + + string_arg->size = pos; + usetc(string_arg->data+pos, 0); + } + else { + /* right align the result */ + shift = info.field_width - slen; + + if (shift > 0) { + pos = 0; + + if (info.flags & SPRINT_FLAG_PAD_ZERO) { + shiftfiller = '0'; + + for (i=0; idata+pos); + } + else + shiftfiller = ' '; + + shiftbytes = shift * ucwidth(shiftfiller); + memmove(string_arg->data+pos+shiftbytes, string_arg->data+pos, string_arg->size-pos+ucwidth(0)); + + string_arg->size += shiftbytes; + slen += shift; + + for (i=0; idata+pos, shiftfiller); + } + } + } + + buf += usetc(buf, '%'); + buf += usetc(buf, 's'); + len += slen; + + /* allocate next item */ + string_arg->next = _AL_MALLOC(sizeof(STRING_ARG)); + string_arg = string_arg->next; + string_arg->next = NULL; + } + } + } + else { + /* normal character */ + buf += usetc(buf, c); + len++; + } + } + + usetc(buf, 0); + + return len; +} + + + +/* uvszprintf: + * Enhanced Unicode-aware version of the ANSI vsprintf() function + * than can handle the size (in bytes) of the destination buffer. + * The raw Unicode-aware version of ANSI vsprintf() is defined as: + * #define uvsprintf(buf, format, args) uvszprintf(buf, INT_MAX, format, args) + */ +int uvszprintf(char *buf, int size, AL_CONST char *format, va_list args) +{ + char *decoded_format, *df; + STRING_ARG *string_args, *iter_arg; + int c, len; + ASSERT(buf); + ASSERT(size >= 0); + ASSERT(format); + + /* decoding can only lower the length of the format string */ + df = decoded_format = _AL_MALLOC_ATOMIC(ustrsizez(format) * sizeof(char)); + + /* allocate first item */ + string_args = _AL_MALLOC(sizeof(STRING_ARG)); + string_args->next = NULL; + + /* 1st pass: decode */ + len = decode_format_string(decoded_format, string_args, format, args); + + size -= ucwidth(0); + iter_arg = string_args; + + /* 2nd pass: concatenate */ + while ((c = ugetx(&decoded_format)) != 0) { + + if (c == '%') { + if ((c = ugetx(&decoded_format)) == '%') { + /* percent sign escape */ + size -= ucwidth('%'); + if (size<0) + break; + buf += usetc(buf, '%'); + } + else if (c == 's') { + /* string argument */ + ustrzcpy(buf, size+ucwidth(0), iter_arg->data); + buf += iter_arg->size; + size -= iter_arg->size; + if (size<0) { + buf += size; + break; + } + iter_arg = iter_arg->next; + } + } + else { + /* normal character */ + size -= ucwidth(c); + if (size<0) + break; + buf += usetc(buf, c); + } + } + + usetc(buf, 0); + + /* free allocated resources */ + while (string_args->next) { + _AL_FREE(string_args->data); + iter_arg = string_args; + string_args = string_args->next; + _AL_FREE(iter_arg); + } + _AL_FREE(string_args); + _AL_FREE(df); /* alias for decoded_format */ + + return len; +} + + + +/* usprintf: + * Unicode-aware version of the ANSI sprintf() function. + */ +int usprintf(char *buf, AL_CONST char *format, ...) +{ + int ret; + va_list ap; + ASSERT(buf); + ASSERT(format); + + va_start(ap, format); + ret = uvszprintf(buf, INT_MAX, format, ap); + va_end(ap); + + return ret; +} + + + +/* uszprintf: + * Enhanced Unicode-aware version of the ANSI sprintf() function + * that can handle the size (in bytes) of the destination buffer. + */ +int uszprintf(char *buf, int size, AL_CONST char *format, ...) +{ + int ret; + va_list ap; + ASSERT(buf); + ASSERT(size >= 0); + ASSERT(format); + + va_start(ap, format); + ret = uvszprintf(buf, size, format, ap); + va_end(ap); + + return ret; +} + diff --git a/libsrc/allegro/src/unix/ufile.c b/libsrc/allegro/src/unix/ufile.c new file mode 100644 index 00000000000..f9fda47a16b --- /dev/null +++ b/libsrc/allegro/src/unix/ufile.c @@ -0,0 +1,467 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Helper routines to make file.c work on Unix (POSIX) platforms. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + +/* libc should use 64-bit for file sizes when possible */ +#define _FILE_OFFSET_BITS 64 + +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + +#ifdef ALLEGRO_HAVE_SYS_STAT_H +#include +#endif + +#ifdef ALLEGRO_HAVE_DIRENT_H + #include + #include + #define NAMLEN(dirent) (strlen((dirent)->d_name)) +#else + /* Apparently all new systems have `dirent.h'. */ + #error ALLEGRO_HAVE_DIRENT_H not defined +#endif + +#ifdef ALLEGRO_HAVE_SYS_TIME_H + #include +#endif +#ifdef ALLEGRO_HAVE_TIME_H + #include +#endif + +#define PREFIX_I "al-unix INFO: " + +#define PREFIX_I "al-unix INFO: " + + +/* _al_file_isok: + * Helper function to check if it is safe to access a file on a floppy + * drive. + */ +int _al_file_isok(AL_CONST char *filename) +{ + return TRUE; +} + + + +/* _al_file_size_ex: + * Measures the size of the specified file. + */ +uint64_t _al_file_size_ex(AL_CONST char *filename) +{ + struct stat s; + char tmp[1024]; + + if (stat(uconvert(filename, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) != 0) { + *allegro_errno = errno; + return 0; + } + + return s.st_size; +} + + + +/* ff_get_filename: + * When passed a completely specified file path, this returns a pointer + * to the filename portion. + */ +static char *ff_get_filename(AL_CONST char *path) +{ + char *p = (char*)path + strlen(path); + + while ((p > path) && (*(p - 1) != '/')) + p--; + + return p; +} + + + +/* ff_put_backslash: + * If the last character of the filename is not a /, this routine will + * concatenate a / on to it. + */ +static void ff_put_backslash(char *filename, int size) +{ + int len = strlen(filename); + + if ((len > 0) && (len < (size - 1)) && (filename[len - 1] != '/')) { + filename[len] = '/'; + filename[len + 1] = 0; + } +} + + + +#define FF_MATCH_TRY 0 +#define FF_MATCH_ONE 1 +#define FF_MATCH_ANY 2 + + +struct FF_MATCH_DATA +{ + int type; + AL_CONST char *s1; + AL_CONST char *s2; +}; + + + +/* ff_match: + * Matches two strings ('*' matches any number of characters, + * '?' matches any character). + */ +static int ff_match(AL_CONST char *s1, AL_CONST char *s2) +{ + static unsigned int size = 0; + static struct FF_MATCH_DATA *data = NULL; + AL_CONST char *s1end; + int index, c1, c2; + + /* handle NULL arguments */ + if ((!s1) && (!s2)) { + if (data) { + _AL_FREE(data); + data = NULL; + } + + return 0; + } + + s1end = s1 + strlen(s1); + + /* allocate larger working area if necessary */ + if (data && (size < strlen(s2))) { + _AL_FREE(data); + data = NULL; + } + + if (!data) { + size = strlen(s2); + data = _AL_MALLOC(sizeof(struct FF_MATCH_DATA) * size * 2 + 1); + if (!data) + return 0; + } + + index = 0; + data[0].s1 = s1; + data[0].s2 = s2; + data[0].type = FF_MATCH_TRY; + + while (index >= 0) { + s1 = data[index].s1; + s2 = data[index].s2; + c1 = *s1; + c2 = *s2; + + switch (data[index].type) { + + case FF_MATCH_TRY: + if (c2 == 0) { + /* pattern exhausted */ + if (c1 == 0) + return 1; + else + index--; + } + else if (c1 == 0) { + /* string exhausted */ + while (*s2 == '*') + s2++; + if (*s2 == 0) + return 1; + else + index--; + } + else if (c2 == '*') { + /* try to match the rest of pattern with empty string */ + data[index++].type = FF_MATCH_ANY; + data[index].s1 = s1end; + data[index].s2 = s2 + 1; + data[index].type = FF_MATCH_TRY; + } + else if ((c2 == '?') || (c1 == c2)) { + /* try to match the rest */ + data[index++].type = FF_MATCH_ONE; + data[index].s1 = s1 + 1; + data[index].s2 = s2 + 1; + data[index].type = FF_MATCH_TRY; + } + else + index--; + break; + + case FF_MATCH_ONE: + /* the rest of string did not match, try earlier */ + index--; + break; + + case FF_MATCH_ANY: + /* rest of string did not match, try add more chars to string tail */ + if (--data[index + 1].s1 >= s1) { + data[index + 1].type = FF_MATCH_TRY; + index++; + } + else + index--; + break; + + default: + /* this is a bird? This is a plane? No it's a bug!!! */ + return 0; + } + } + + return 0; +} + + + +/* ff_get_attrib: + * Builds up the attribute list of the file pointed to by name and s. + */ +static int ff_get_attrib(AL_CONST char *name, struct stat *s) +{ + int attrib = 0; + +#if ALLEGRO_CHECK_FILE_PERMISSIONS + uid_t euid = geteuid(); + + if (euid != 0) { + if (s->st_uid == euid) { + if ((s->st_mode & S_IWUSR) == 0) + attrib |= FA_RDONLY; + } + else if (s->st_gid == getegid()) { + if ((s->st_mode & S_IWGRP) == 0) + attrib |= FA_RDONLY; + } + else if ((s->st_mode & S_IWOTH) == 0) { + attrib |= FA_RDONLY; + } + } +#endif + + if (S_ISDIR(s->st_mode)) + attrib |= FA_DIREC; + + if ((name[0] == '.') && ((name[1] != '.') || (name[2] != '\0'))) + attrib |= FA_HIDDEN; + + return attrib; +} + + + +/* structure for use by the directory scanning routines */ +#define FF_MAXPATHLEN 1024 + +struct FF_DATA +{ + DIR *dir; + char dirname[FF_MAXPATHLEN]; + char pattern[FF_MAXPATHLEN]; + int attrib; + uint64_t size; +}; + + + +/* al_findfirst: + * Initiates a directory search. + */ +int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) +{ + struct FF_DATA *ff_data; + struct stat s; + int actual_attrib; + char tmp[1024]; + char *p; + + /* allocate ff_data structure */ + ff_data = _AL_MALLOC(sizeof(struct FF_DATA)); + if (!ff_data) { + *allegro_errno = ENOMEM; + return -1; + } + + memset(ff_data, 0, sizeof *ff_data); + info->ff_data = (void *) ff_data; + + /* if the pattern contains no wildcard, we use stat() */ + if (!ustrpbrk(pattern, uconvert("?*", U_ASCII, tmp, U_CURRENT, sizeof(tmp)))) { + /* start the search */ + errno = *allegro_errno = 0; + + if (stat(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) == 0) { + /* get file attributes */ + actual_attrib = ff_get_attrib(ff_get_filename(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp))), &s); + + /* does it match ? */ + if ((actual_attrib & ~attrib) == 0) { + info->attrib = actual_attrib; + info->time = s.st_mtime; + info->size = s.st_size; /* overflows at 2GB */ + ff_data->size = s.st_size; + ustrzcpy(info->name, sizeof(info->name), get_filename(pattern)); + return 0; + } + } + + _AL_FREE(ff_data); + info->ff_data = NULL; + *allegro_errno = (errno ? errno : ENOENT); + return -1; + } + + ff_data->attrib = attrib; + + do_uconvert(pattern, U_CURRENT, ff_data->dirname, U_UTF8, sizeof(ff_data->dirname)); + p = ff_get_filename(ff_data->dirname); + _al_sane_strncpy(ff_data->pattern, p, sizeof(ff_data->pattern)); + if (p == ff_data->dirname) + _al_sane_strncpy(ff_data->dirname, "./", FF_MAXPATHLEN); + else + *p = 0; + + /* nasty bodge, but gives better compatibility with DOS programs */ + if (strcmp(ff_data->pattern, "*.*") == 0) + _al_sane_strncpy(ff_data->pattern, "*", FF_MAXPATHLEN); + + /* start the search */ + errno = *allegro_errno = 0; + + ff_data->dir = opendir(ff_data->dirname); + + if (!ff_data->dir) { + *allegro_errno = (errno ? errno : ENOENT); + _AL_FREE(ff_data); + info->ff_data = NULL; + return -1; + } + + if (al_findnext(info) != 0) { + al_findclose(info); + return -1; + } + + return 0; +} + + + +/* al_findnext: + * Retrieves the next file from a directory search. + */ +int al_findnext(struct al_ffblk *info) +{ + char tempname[FF_MAXPATHLEN]; + char filename[FF_MAXPATHLEN]; + int attrib; + struct dirent *entry; + struct stat s; + struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; + + ASSERT(ff_data); + + /* if the pattern contained no wildcard */ + if (!ff_data->dir) + return -1; + + while (TRUE) { + /* read directory entry */ + entry = readdir(ff_data->dir); + if (!entry) { + *allegro_errno = (errno ? errno : ENOENT); + return -1; + } + + /* try to match file name with pattern */ + tempname[0] = 0; + if (NAMLEN(entry) >= sizeof(tempname)) + strncat(tempname, entry->d_name, sizeof(tempname) - 1); + else + strncat(tempname, entry->d_name, NAMLEN(entry)); + + if (ff_match(tempname, ff_data->pattern)) { + _al_sane_strncpy(filename, ff_data->dirname, FF_MAXPATHLEN); + ff_put_backslash(filename, sizeof(filename)); + strncat(filename, tempname, sizeof(filename) - strlen(filename) - 1); + + /* get file attributes */ + if (stat(filename, &s) == 0) { + attrib = ff_get_attrib(tempname, &s); + + /* does it match ? */ + if ((attrib & ~ff_data->attrib) == 0) + break; + } + else { + /* evil! but no other way to avoid exiting for_each_file() */ + *allegro_errno = 0; + } + } + } + + info->attrib = attrib; + info->time = s.st_mtime; + info->size = s.st_size; /* overflows at 2GB */ + ff_data->size = s.st_size; + + do_uconvert(tempname, U_UTF8, info->name, U_CURRENT, sizeof(info->name)); + + return 0; +} + + + +/* al_findclose: + * Cleans up after a directory search. + */ +void al_findclose(struct al_ffblk *info) +{ + struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; + + if (ff_data) { + if (ff_data->dir) { + closedir(ff_data->dir); + } + _AL_FREE(ff_data); + info->ff_data = NULL; + + /* to avoid leaking memory */ + ff_match(NULL, NULL); + } +} + + + +/* _al_getdcwd: + * Returns the current directory on the specified drive. + */ +void _al_getdcwd(int drive, char *buf, int size) +{ + char tmp[1024]; + + if (getcwd(tmp, sizeof(tmp))) + do_uconvert(tmp, U_UTF8, buf, U_CURRENT, size); + else + usetc(buf, 0); +} diff --git a/libsrc/allegro/src/vtable.c b/libsrc/allegro/src/vtable.c new file mode 100644 index 00000000000..d15300ccaac --- /dev/null +++ b/libsrc/allegro/src/vtable.c @@ -0,0 +1,57 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * List of available bitmap vtables, kept in a seperate file so that + * they can be overriden by user programs. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + + +#ifndef ALLEGRO_COLOR8 +#undef COLOR_DEPTH_8 +#define COLOR_DEPTH_8 +#endif + + +#ifndef ALLEGRO_COLOR16 +#undef COLOR_DEPTH_15 +#undef COLOR_DEPTH_16 +#define COLOR_DEPTH_15 +#define COLOR_DEPTH_16 +#endif + + +#ifndef ALLEGRO_COLOR24 +#undef COLOR_DEPTH_24 +#define COLOR_DEPTH_24 +#endif + + +#ifndef ALLEGRO_COLOR32 +#undef COLOR_DEPTH_32 +#define COLOR_DEPTH_32 +#endif + + +BEGIN_COLOR_DEPTH_LIST + COLOR_DEPTH_8 + COLOR_DEPTH_15 + COLOR_DEPTH_16 + COLOR_DEPTH_24 + COLOR_DEPTH_32 +END_COLOR_DEPTH_LIST + + diff --git a/libsrc/allegro/src/vtable15.c b/libsrc/allegro/src/vtable15.c new file mode 100644 index 00000000000..c0df02d484a --- /dev/null +++ b/libsrc/allegro/src/vtable15.c @@ -0,0 +1,100 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Table of functions for drawing onto 15 bit linear bitmaps. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#ifdef ALLEGRO_COLOR16 + + +void _linear_draw_sprite16_end(void); +void _linear_blit16_end(void); + + +GFX_VTABLE __linear_vtable15 = +{ + 15, + MASK_COLOR_15, + _stub_unbank_switch, + NULL, + NULL, + NULL, + NULL, + NULL, + _linear_getpixel16, + _linear_putpixel15, + _linear_vline15, + _linear_hline15, + _linear_hline15, + _normal_line, + NULL, // _fast_line, + _normal_rectfill, + _soft_triangle, + _linear_draw_sprite16, + _linear_draw_256_sprite16, + _linear_draw_sprite_v_flip16, + _linear_draw_sprite_h_flip16, + _linear_draw_sprite_vh_flip16, + _linear_draw_trans_sprite15, + _linear_draw_trans_rgba_sprite15, + _linear_draw_lit_sprite15, + NULL, // _linear_draw_rle_sprite15, + NULL, // _linear_draw_trans_rle_sprite15, + NULL, // _linear_draw_trans_rgba_rle_sprite15, + NULL, // _linear_draw_lit_rle_sprite15, + NULL, // _linear_draw_character16, + NULL, // _linear_draw_glyph16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit_backward16, + _blit_between_formats, + _linear_masked_blit16, + _linear_clear_to_color16, + NULL, // _pivot_scaled_sprite_flip, + NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) + NULL, // _soft_draw_gouraud_sprite, + _linear_draw_sprite16_end, + _linear_blit16_end, + _soft_polygon, + _soft_rect, + NULL, // _soft_circle, + _soft_circlefill, + NULL, // _soft_ellipse, + NULL, // _soft_ellipsefill, + NULL, // _soft_arc, + NULL, // _soft_spline, + _soft_floodfill, + + NULL, // _soft_polygon3d, + NULL, // _soft_polygon3d_f, + NULL, // _soft_triangle3d, + NULL, // _soft_triangle3d_f, + NULL, // _soft_quad3d, + NULL, // _soft_quad3d_f, + NULL, // _linear_draw_sprite_ex16 +}; + + +#endif + diff --git a/libsrc/allegro/src/vtable16.c b/libsrc/allegro/src/vtable16.c new file mode 100644 index 00000000000..406b21f4f52 --- /dev/null +++ b/libsrc/allegro/src/vtable16.c @@ -0,0 +1,100 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Table of functions for drawing onto 16 bit linear bitmaps. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#ifdef ALLEGRO_COLOR16 + + +void _linear_draw_sprite16_end(void); +void _linear_blit16_end(void); + + +GFX_VTABLE __linear_vtable16 = +{ + 16, + MASK_COLOR_16, + _stub_unbank_switch, + NULL, + NULL, + NULL, + NULL, + NULL, + _linear_getpixel16, + _linear_putpixel16, + _linear_vline16, + _linear_hline16, + _linear_hline16, + _normal_line, + NULL, // _fast_line, + _normal_rectfill, + _soft_triangle, + _linear_draw_sprite16, + _linear_draw_256_sprite16, + _linear_draw_sprite_v_flip16, + _linear_draw_sprite_h_flip16, + _linear_draw_sprite_vh_flip16, + _linear_draw_trans_sprite16, + _linear_draw_trans_rgba_sprite16, + _linear_draw_lit_sprite16, + NULL, // _linear_draw_rle_sprite16, + NULL, // _linear_draw_trans_rle_sprite16, + NULL, // _linear_draw_trans_rgba_rle_sprite16, + NULL, // _linear_draw_lit_rle_sprite16, + NULL, // _linear_draw_character16, + NULL, // _linear_draw_glyph16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit16, + _linear_blit_backward16, + _blit_between_formats, + _linear_masked_blit16, + _linear_clear_to_color16, + _pivot_scaled_sprite_flip, + NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) + NULL, // _soft_draw_gouraud_sprite, + _linear_draw_sprite16_end, + _linear_blit16_end, + _soft_polygon, + _soft_rect, + NULL, // _soft_circle, + _soft_circlefill, + NULL, // _soft_ellipse, + NULL, // _soft_ellipsefill, + NULL, // _soft_arc, + NULL, // _soft_spline, + _soft_floodfill, + + NULL, // _soft_polygon3d, + NULL, // _soft_polygon3d_f, + NULL, // _soft_triangle3d, + NULL, // _soft_triangle3d_f, + NULL, // _soft_quad3d, + NULL, // _soft_quad3d_f, + NULL, // _linear_draw_sprite_ex16 +}; + + +#endif + diff --git a/libsrc/allegro/src/vtable24.c b/libsrc/allegro/src/vtable24.c new file mode 100644 index 00000000000..130a15f5690 --- /dev/null +++ b/libsrc/allegro/src/vtable24.c @@ -0,0 +1,99 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Table of functions for drawing onto 24 bit linear bitmaps. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#ifdef ALLEGRO_COLOR24 + + +void _linear_draw_sprite24_end(void); +void _linear_blit24_end(void); + + +GFX_VTABLE __linear_vtable24 = +{ + 24, + MASK_COLOR_24, + _stub_unbank_switch, + NULL, + NULL, + NULL, + NULL, + NULL, + _linear_getpixel24, + _linear_putpixel24, + _linear_vline24, + _linear_hline24, + _linear_hline24, + _normal_line, + NULL, // _fast_line, + _normal_rectfill, + _soft_triangle, + _linear_draw_sprite24, + _linear_draw_256_sprite24, + _linear_draw_sprite_v_flip24, + _linear_draw_sprite_h_flip24, + _linear_draw_sprite_vh_flip24, + _linear_draw_trans_sprite24, + _linear_draw_trans_rgba_sprite24, + _linear_draw_lit_sprite24, + NULL, // _linear_draw_rle_sprite24, + NULL, // _linear_draw_trans_rle_sprite24, + NULL, // _linear_draw_trans_rgba_rle_sprite24, + NULL, // _linear_draw_lit_rle_sprite24, + NULL, // _linear_draw_character24, + NULL, // _linear_draw_glyph24, + _linear_blit24, + _linear_blit24, + _linear_blit24, + _linear_blit24, + _linear_blit24, + _linear_blit24, + _linear_blit_backward24, + _blit_between_formats, + _linear_masked_blit24, + _linear_clear_to_color24, + _pivot_scaled_sprite_flip, + NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) + NULL, // _soft_draw_gouraud_sprite, + _linear_draw_sprite24_end, + _linear_blit24_end, + _soft_polygon, + _soft_rect, + NULL, // _soft_circle, + _soft_circlefill, + NULL, // _soft_ellipse, + NULL, // _soft_ellipsefill, + NULL, // _soft_arc, + NULL, // _soft_spline, + _soft_floodfill, + + NULL, // _soft_polygon3d, + NULL, // _soft_polygon3d_f, + NULL, // _soft_triangle3d, + NULL, // _soft_triangle3d_f, + NULL, // _soft_quad3d, + NULL, // _soft_quad3d_f, + NULL, // _linear_draw_sprite_ex24 +}; + + +#endif diff --git a/libsrc/allegro/src/vtable32.c b/libsrc/allegro/src/vtable32.c new file mode 100644 index 00000000000..cbccc6036ac --- /dev/null +++ b/libsrc/allegro/src/vtable32.c @@ -0,0 +1,99 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Table of functions for drawing onto 32 bit linear bitmaps. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#ifdef ALLEGRO_COLOR32 + + +void _linear_draw_sprite32_end(void); +void _linear_blit32_end(void); + + +GFX_VTABLE __linear_vtable32 = +{ + 32, + MASK_COLOR_32, + _stub_unbank_switch, + NULL, + NULL, + NULL, + NULL, + NULL, + _linear_getpixel32, + _linear_putpixel32, + _linear_vline32, + _linear_hline32, + _linear_hline32, + _normal_line, + NULL, // _fast_line, + _normal_rectfill, + _soft_triangle, + _linear_draw_sprite32, + _linear_draw_256_sprite32, + _linear_draw_sprite_v_flip32, + _linear_draw_sprite_h_flip32, + _linear_draw_sprite_vh_flip32, + _linear_draw_trans_sprite32, + _linear_draw_trans_sprite32, + _linear_draw_lit_sprite32, + NULL, // _linear_draw_rle_sprite32, + NULL, // _linear_draw_trans_rle_sprite32, + NULL, // _linear_draw_trans_rle_sprite32, + NULL, // _linear_draw_lit_rle_sprite32, + NULL, // _linear_draw_character32, + NULL, // _linear_draw_glyph32, + _linear_blit32, + _linear_blit32, + _linear_blit32, + _linear_blit32, + _linear_blit32, + _linear_blit32, + _linear_blit_backward32, + _blit_between_formats, + _linear_masked_blit32, + _linear_clear_to_color32, + _pivot_scaled_sprite_flip, + NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) + NULL, // _soft_draw_gouraud_sprite, + _linear_draw_sprite32_end, + _linear_blit32_end, + _soft_polygon, + _soft_rect, + NULL, // _soft_circle, + _soft_circlefill, + NULL, // _soft_ellipse, + NULL, // _soft_ellipsefill, + NULL, // _soft_arc, + NULL, // _soft_spline, + _soft_floodfill, + + NULL, // _soft_polygon3d, + NULL, // _soft_polygon3d_f, + NULL, // _soft_triangle3d, + NULL, // _soft_triangle3d_f, + NULL, // _soft_quad3d, + NULL, // _soft_quad3d_f, + NULL, // _linear_draw_sprite_ex32 +}; + + +#endif diff --git a/libsrc/allegro/src/vtable8.c b/libsrc/allegro/src/vtable8.c new file mode 100644 index 00000000000..99b251f0121 --- /dev/null +++ b/libsrc/allegro/src/vtable8.c @@ -0,0 +1,100 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Table of functions for drawing onto 8 bit linear bitmaps. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" + + + +#ifdef ALLEGRO_COLOR8 + + +void _linear_draw_sprite8_end(void); +void _linear_blit8_end(void); + + +GFX_VTABLE __linear_vtable8 = +{ + 8, + MASK_COLOR_8, + _stub_unbank_switch, + NULL, + NULL, + NULL, + NULL, + NULL, + _linear_getpixel8, + _linear_putpixel8, + _linear_vline8, + _linear_hline8, + _linear_hline8, + _normal_line, + NULL, // _fast_line, + _normal_rectfill, + _soft_triangle, + _linear_draw_sprite8, + _linear_draw_sprite8, + _linear_draw_sprite_v_flip8, + _linear_draw_sprite_h_flip8, + _linear_draw_sprite_vh_flip8, + _linear_draw_trans_sprite8, + NULL, + _linear_draw_lit_sprite8, + NULL, // _linear_draw_rle_sprite8, + NULL, // _linear_draw_trans_rle_sprite8, + NULL, + NULL, // _linear_draw_lit_rle_sprite8, + NULL, // _linear_draw_character8, + NULL, // _linear_draw_glyph8, + _linear_blit8, + _linear_blit8, + _linear_blit8, + _linear_blit8, + _linear_blit8, + _linear_blit8, + _linear_blit_backward8, + _blit_between_formats, + _linear_masked_blit8, + _linear_clear_to_color8, + _pivot_scaled_sprite_flip, + NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) + NULL, // _soft_draw_gouraud_sprite, + _linear_draw_sprite8_end, + _linear_blit8_end, + _soft_polygon, + _soft_rect, + NULL, // _soft_circle, + _soft_circlefill, + NULL, // _soft_ellipse, + NULL, // _soft_ellipsefill, + NULL, // _soft_arc, + NULL, // _soft_spline, + _soft_floodfill, + + NULL, // _soft_polygon3d, + NULL, // _soft_polygon3d_f, + NULL, // _soft_triangle3d, + NULL, // _soft_triangle3d_f, + NULL, // _soft_quad3d, + NULL, // _soft_quad3d_f, + NULL, // _linear_draw_sprite_ex8 +}; + + +#endif + diff --git a/libsrc/allegro/src/win/gdi.c b/libsrc/allegro/src/win/gdi.c new file mode 100644 index 00000000000..9fa8d833b4d --- /dev/null +++ b/libsrc/allegro/src/win/gdi.c @@ -0,0 +1,660 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Functions for drawing to GDI without using DirectX. + * + * By Marian Dvorsky. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" +#include "winalleg.h" + +#ifndef ALLEGRO_WINDOWS + #error something is wrong with the makefile +#endif + + +static HPALETTE current_hpalette = NULL; + + + +/* set_gdi_color_format: + * Sets right values for pixel color format to work with GDI. + */ +void set_gdi_color_format(void) +{ + _rgb_r_shift_15 = 10; + _rgb_g_shift_15 = 5; + _rgb_b_shift_15 = 0; + + _rgb_r_shift_16 = 11; + _rgb_g_shift_16 = 5; + _rgb_b_shift_16 = 0; + + _rgb_r_shift_24 = 16; + _rgb_g_shift_24 = 8; + _rgb_b_shift_24 = 0; + + _rgb_r_shift_32 = 16; + _rgb_g_shift_32 = 8; + _rgb_b_shift_32 = 0; +} + + + +/* destroy_current_hpalette: + * Destroys the current Windows PALETTE. + */ +static void destroy_current_hpalette(void) +{ + if (current_hpalette) { + DeleteObject(current_hpalette); + current_hpalette = NULL; + } + + _remove_exit_func(destroy_current_hpalette); +} + + + +/* set_palette_to_hdc: + * Selects and realizes an Allegro PALETTE to a Windows DC. + */ +void set_palette_to_hdc(HDC dc, PALETTE pal) +{ + PALETTEENTRY palPalEntry[256]; + int i; + + if (current_hpalette) { + for (i = 0; i < 256; i++) { + palPalEntry[i].peRed = _rgb_scale_6[pal[i].r]; + palPalEntry[i].peGreen = _rgb_scale_6[pal[i].g]; + palPalEntry[i].peBlue = _rgb_scale_6[pal[i].b]; + palPalEntry[i].peFlags = 0; + } + + SetPaletteEntries(current_hpalette, 0, 256, (LPPALETTEENTRY) & palPalEntry); + } + else { + current_hpalette = convert_palette_to_hpalette(pal); + _add_exit_func(destroy_current_hpalette, + "destroy_current_hpalette"); + } + + SelectPalette(dc, current_hpalette, FALSE); + RealizePalette(dc); + select_palette(pal); +} + + + +/* convert_palette_to_hpalette: + * Converts an Allegro PALETTE to a Windows PALETTE. + */ +HPALETTE convert_palette_to_hpalette(PALETTE pal) +{ + HPALETTE hpal; + LOGPALETTE *lp; + int i; + + lp = (LOGPALETTE *) _AL_MALLOC(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256); + if (!lp) + return NULL; + + lp->palNumEntries = 256; + lp->palVersion = 0x300; + + for (i = 0; i < 256; i++) { + lp->palPalEntry[i].peRed = _rgb_scale_6[pal[i].r]; + lp->palPalEntry[i].peGreen = _rgb_scale_6[pal[i].g]; + lp->palPalEntry[i].peBlue = _rgb_scale_6[pal[i].b]; + lp->palPalEntry[i].peFlags = 0; + } + + hpal = CreatePalette(lp); + + _AL_FREE(lp); + + return hpal; +} + + + +/* convert_hpalette_to_palette: + * Converts a Windows PALETTE to an Allegro PALETTE. + */ +void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal) +{ + PALETTEENTRY lp[256]; + int i; + + GetPaletteEntries(hpal, 0, 256, (LPPALETTEENTRY) & lp); + + for (i = 0; i < 256; i++) { + pal[i].r = lp[i].peRed >> 2; + pal[i].g = lp[i].peGreen >> 2; + pal[i].b = lp[i].peBlue >> 2; + } +} + + + +/* get_bitmap_info: + * Returns a BITMAPINFO structure suited to an Allegro BITMAP. + * You have to free the memory allocated by this function. + */ +static BITMAPINFO *get_bitmap_info(BITMAP *bitmap, PALETTE pal) +{ + BITMAPINFO *bi; + int bpp, i; + + bi = (BITMAPINFO *) _AL_MALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256); + + bpp = bitmap_color_depth(bitmap); + if (bpp == 15) + bpp = 16; + + ZeroMemory(&bi->bmiHeader, sizeof(BITMAPINFOHEADER)); + + bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi->bmiHeader.biBitCount = bpp; + bi->bmiHeader.biPlanes = 1; + bi->bmiHeader.biWidth = bitmap->w; + bi->bmiHeader.biHeight = -bitmap->h; + bi->bmiHeader.biClrUsed = 256; + bi->bmiHeader.biCompression = BI_RGB; + + if (pal) { + for (i = 0; i < 256; i++) { + bi->bmiColors[i].rgbRed = _rgb_scale_6[pal[i].r]; + bi->bmiColors[i].rgbGreen = _rgb_scale_6[pal[i].g]; + bi->bmiColors[i].rgbBlue = _rgb_scale_6[pal[i].b]; + bi->bmiColors[i].rgbReserved = 0; + } + } + + return bi; +} + + + +/* get_dib_from_bitmap: + * Creates a Windows device-independent bitmap (DIB) from an Allegro BITMAP. + * You have to free the memory allocated by this function. + */ +static BYTE *get_dib_from_bitmap(BITMAP *bitmap) +{ + int bpp; + int x, y; + int pitch; + int col; + BYTE *pixels; + BYTE *src, *dst; + + bpp = bitmap_color_depth(bitmap); + pitch = bitmap->w * BYTES_PER_PIXEL(bpp); + pitch = (pitch + 3) & ~3; /* align on dword */ + + pixels = (BYTE *) _AL_MALLOC_ATOMIC(bitmap->h * pitch); + if (!pixels) + return NULL; + + switch (bpp) { + + case 8: + for (y = 0; y < bitmap->h; y++) { + memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w); + } + break; + + case 15: + if ((_rgb_r_shift_15 == 10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == 0)) { + for (y = 0; y < bitmap->h; y++) + memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 2); + } + else { + for (y = 0; y < bitmap->h; y++) { + src = bitmap->line[y]; + dst = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + col = *(WORD *) (src); + *((WORD *) (dst)) = (WORD) ((getb15(col) >> 3) | ((getg15(col) >> 3) << 5) | ((getr15(col) >> 3) << 10)); + src += 2; + dst += 2; + } + } + } + break; + + case 16: + /* the format of a 16-bit DIB is 5-5-5 as above */ + for (y = 0; y < bitmap->h; y++) { + src = bitmap->line[y]; + dst = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + col = *(WORD *) (src); + *((WORD *) (dst)) = (WORD) ((getb16(col) >> 3) | ((getg16(col) >> 3) << 5) | ((getr16(col) >> 3) << 10)); + src += 2; + dst += 2; + } + } + break; + + case 24: + if ((_rgb_r_shift_24 == 16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == 0)) { + for (y = 0; y < bitmap->h; y++) + memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 3); + } + else { + for (y = 0; y < bitmap->h; y++) { + src = bitmap->line[y]; + dst = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + col = *(DWORD *) (src); + src += 3; + *(dst++) = getb24(col); + *(dst++) = getg24(col); + *(dst++) = getr24(col); + } + } + } + break; + + case 32: + if ((_rgb_r_shift_32 == 16) && (_rgb_g_shift_32 == 8) && (_rgb_b_shift_32 == 0)) { + for (y = 0; y < bitmap->h; y++) + memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 4); + } + else { + for (y = 0; y < bitmap->h; y++) { + src = bitmap->line[y]; + dst = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + col = *(DWORD *) (src); + src += 4; + *(dst++) = getb32(col); + *(dst++) = getg32(col); + *(dst++) = getr32(col); + dst++; + } + } + } + break; + } + + return pixels; +} + + + +/* get_dib_from_hbitmap: + * Creates a Windows device-independent bitmap (DIB) from a Windows BITMAP. + * You have to free the memory allocated by this function. + */ +static BYTE *get_dib_from_hbitmap(int bpp, HBITMAP hbitmap) +{ + BITMAPINFOHEADER bi; + BITMAPINFO *binfo; + HDC hdc; + HPALETTE hpal, holdpal; + int col; + WINDOWS_BITMAP bm; + int pitch; + BYTE *pixels; + BYTE *ptr; + int x, y; + + if (!hbitmap) + return NULL; + + if (bpp == 15) + bpp = 16; + + if (!GetObject(hbitmap, sizeof(bm), (LPSTR) & bm)) + return NULL; + + pitch = bm.bmWidth * BYTES_PER_PIXEL(bpp); + pitch = (pitch + 3) & ~3; /* align on dword */ + + pixels = (BYTE *) _AL_MALLOC_ATOMIC(bm.bmHeight * pitch); + if (!pixels) + return NULL; + + ZeroMemory(&bi, sizeof(BITMAPINFOHEADER)); + + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biBitCount = bpp; + bi.biPlanes = 1; + bi.biWidth = bm.bmWidth; + bi.biHeight = -abs(bm.bmHeight); + bi.biClrUsed = 256; + bi.biCompression = BI_RGB; + + binfo = _AL_MALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256); + binfo->bmiHeader = bi; + + hdc = GetDC(NULL); + + hpal = convert_palette_to_hpalette(_current_palette); + holdpal = SelectPalette(hdc, hpal, TRUE); + RealizePalette(hdc); + + GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pixels, binfo, DIB_RGB_COLORS); + + ptr = pixels; + + /* This never occurs, because if screen or memory bitmap is 8-bit, + * we ask Windows to convert it to truecolor. It is safer, but a little + * bit slower. + */ + + if (bpp == 8) { + for (y = 0; y < bm.bmWidth; y++) { + for (x = 0; x < bm.bmHeight; x++) { + col = *ptr; + + if ((col < 10) || (col >= 246)) { + /* we have to remap colors from system palette */ + *(ptr++) = makecol8(binfo->bmiColors[col].rgbRed, binfo->bmiColors[col].rgbGreen, binfo->bmiColors[col].rgbBlue); + } + else { + /* our palette is shifted by 10 */ + *(ptr++) = col - 10; + } + } + } + } + + _AL_FREE(binfo); + + SelectPalette(hdc, holdpal, TRUE); + DeleteObject(hpal); + ReleaseDC(NULL, hdc); + + return pixels; +} + + + +/* get_bitmap_from_dib: + * Creates an Allegro BITMAP from a Windows device-independent bitmap (DIB). + */ +static BITMAP *get_bitmap_from_dib(int bpp, int w, int h, BYTE *pixels) +{ + int x, y; + int pitch; + int col; + int b, g, r; + BYTE *src, *dst; + BITMAP *bitmap; + + bitmap = create_bitmap_ex(bpp, w, h); + pitch = bitmap->w * BYTES_PER_PIXEL(bpp); + pitch = (pitch + 3) & ~3; /* align on dword */ + + switch (bpp) { + + case 8: + for (y = 0; y < bitmap->h; y++) { + memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w); + } + break; + + case 15: + if ((_rgb_r_shift_15 == 10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == 0)) { + for (y = 0; y < bitmap->h; y++) + memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 2); + } + else { + for (y = 0; y < bitmap->h; y++) { + dst = bitmap->line[y]; + src = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + col = *(WORD *) (src); + *((WORD *) (dst)) = makecol15(_rgb_scale_5[(col >> 10) & 0x1F], _rgb_scale_5[(col >> 5) & 0x1F], _rgb_scale_5[col & 0x1F]); + src += 2; + dst += 2; + } + } + } + break; + + case 16: + /* the format of a 16-bit DIB is 5-5-5 as above */ + for (y = 0; y < bitmap->h; y++) { + dst = bitmap->line[y]; + src = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + col = *(WORD *) (src); + *((WORD *) (dst)) = makecol16(_rgb_scale_5[(col >> 10) & 0x1F], _rgb_scale_5[(col >> 5) & 0x1F], _rgb_scale_5[col & 0x1F]); + src += 2; + dst += 2; + } + } + break; + + case 24: + if ((_rgb_r_shift_24 == 16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == 0)) { + for (y = 0; y < bitmap->h; y++) + memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 3); + } + else { + for (y = 0; y < bitmap->h; y++) { + dst = bitmap->line[y]; + src = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + r = *(src++); + g = *(src++); + b = *(src++); + col = makecol24(r, g, b); + *((WORD *) dst) = (col & 0xFFFF); + dst += 2; + *(dst++) = (col >> 16); + } + } + } + break; + + case 32: + if ((_rgb_r_shift_32 == 16) && (_rgb_g_shift_32 == 8) && (_rgb_b_shift_32 == 0)) { + for (y = 0; y < bitmap->h; y++) + memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 4); + } + else { + for (y = 0; y < bitmap->h; y++) { + dst = bitmap->line[y]; + src = pixels + y * pitch; + + for (x = 0; x < bitmap->w; x++) { + b = *(src++); + g = *(src++); + r = *(src++); + col = makecol32(r, g, b); + src++; + *((DWORD *) dst) = col; + dst += 4; + } + } + } + break; + } + + return bitmap; +} + + + +/* convert_bitmap_to_hbitmap: + * Converts an Allegro BITMAP to a Windows BITMAP. + */ +HBITMAP convert_bitmap_to_hbitmap(BITMAP *bitmap) +{ + HDC hdc; + HBITMAP hbmp; + BITMAPINFO *bi; + HPALETTE hpal, holdpal; + BYTE *pixels; + + /* get the DIB first */ + bi = get_bitmap_info(bitmap, NULL); + pixels = get_dib_from_bitmap(bitmap); + hpal = convert_palette_to_hpalette(_current_palette); + + /* now that we have the DIB, convert it to a DDB */ + hdc = GetDC(NULL); + holdpal = SelectPalette(hdc, hpal, TRUE); + RealizePalette(hdc); + hbmp = CreateDIBitmap(hdc, &bi->bmiHeader, CBM_INIT, pixels, bi, DIB_RGB_COLORS); + ReleaseDC(NULL, hdc); + + SelectPalette(hdc, holdpal, TRUE); + DeleteObject(hpal); + + _AL_FREE(pixels); + _AL_FREE(bi); + + return hbmp; +} + + + +/* convert_hbitmap_to_bitmap: + * Converts a Windows BITMAP to an Allegro BITMAP. + */ +BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap) +{ + BYTE *pixels; + BITMAP *bmp; + WINDOWS_BITMAP bm; + int bpp; + + if (!GetObject(bitmap, sizeof(bm), (LPSTR) & bm)) + return NULL; + + if (bm.bmBitsPixel == 8) { + /* ask windows to save truecolor image, then convert to our format */ + bpp = 24; + } + else + bpp = bm.bmBitsPixel; + + /* get the DIB first */ + pixels = get_dib_from_hbitmap(bpp, bitmap); + + /* now that we have the DIB, convert it to a BITMAP */ + bmp = get_bitmap_from_dib(bpp, bm.bmWidth, bm.bmHeight, pixels); + + _AL_FREE(pixels); + + return bmp; +} + + + +/* draw_to_hdc: + * Draws an entire Allegro BITMAP to a Windows DC. Has a syntax similar to draw_sprite(). + */ +void draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y) +{ + stretch_blit_to_hdc(bitmap, dc, 0, 0, bitmap->w, bitmap->h, x, y, bitmap->w, bitmap->h); +} + + + +/* blit_to_hdc: + * Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to blit(). + */ +void blit_to_hdc(BITMAP *bitmap, HDC dc, int src_x, int src_y, int dest_x, int dest_y, int w, int h) +{ + stretch_blit_to_hdc(bitmap, dc, src_x, src_y, w, h, dest_x, dest_y, w, h); +} + + + +/* stretch_blit_to_hdc: + * Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to stretch_blit(). + */ +void stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h) +{ + AL_CONST int bottom_up_src_y = bitmap->h - src_y - src_h; + BYTE *pixels; + BITMAPINFO *bi; + + bi = get_bitmap_info(bitmap, _current_palette); + pixels = get_dib_from_bitmap(bitmap); + + /* Windows treats all source bitmaps as bottom-up when using StretchDIBits + * unless the source (x,y) is (0,0). To work around this buggy behavior, we + * can use negative heights to reverse the direction of the blits. + * + * See for a detailed explanation. + */ + if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap->h) { + StretchDIBits(dc, dest_x, dest_h+dest_y-1, dest_w, -dest_h, + src_x, bitmap->h-src_y+1, src_w, -src_h, pixels, bi, + DIB_RGB_COLORS, SRCCOPY); + } + else { + StretchDIBits(dc, dest_x, dest_y, dest_w, dest_h, + src_x, bottom_up_src_y, src_w, src_h, pixels, bi, + DIB_RGB_COLORS, SRCCOPY); + } + + _AL_FREE(pixels); + _AL_FREE(bi); +} + + + +/* blit_from_hdc: + * Blits from a Windows DC to an Allegro BITMAP. Has a syntax similar to blit(). + */ +void blit_from_hdc(HDC dc, BITMAP *bitmap, int src_x, int src_y, int dest_x, int dest_y, int w, int h) +{ + stretch_blit_from_hdc(dc, bitmap, src_x, src_y, w, h, dest_x, dest_y, w, h); +} + + + +/* stretch_blit_from_hdc: + * Blits from a Windows DC to an Allegro BITMAP. Has a syntax similar to stretch_blit(). + */ +void stretch_blit_from_hdc(HDC dc, BITMAP *bitmap, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h) +{ + HBITMAP hbmp, holdbmp; + HDC hmemdc; + BITMAP *newbmp; + + hmemdc = CreateCompatibleDC(dc); + hbmp = CreateCompatibleBitmap(dc, dest_w, dest_h); + + holdbmp = SelectObject(hmemdc, hbmp); + + StretchBlt(hmemdc, 0, 0, dest_w, dest_h, dc, src_x, src_y, src_w, src_h, SRCCOPY); + SelectObject(hmemdc, holdbmp); + + newbmp = convert_hbitmap_to_bitmap(hbmp); + blit(newbmp, bitmap, 0, 0, dest_x, dest_y, dest_w, dest_h); + + destroy_bitmap(newbmp); + DeleteObject(hbmp); + DeleteDC(hmemdc); +} diff --git a/libsrc/allegro/src/win/wfile.c b/libsrc/allegro/src/win/wfile.c new file mode 100644 index 00000000000..d659aeed9ed --- /dev/null +++ b/libsrc/allegro/src/win/wfile.c @@ -0,0 +1,362 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Helper routines to make file.c work on Windows platforms. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include +#endif + +#include "allegro.h" +#include "winalleg.h" +#include "allegro/internal/aintern.h" + +#ifndef ALLEGRO_WINDOWS +#error something is wrong with the makefile +#endif + + + +/* _al_file_isok: + * Helper function to check if it is safe to access a file on a floppy + * drive. This really only applies to the DOS library, so we don't bother + * with it. + */ +int _al_file_isok(AL_CONST char *filename) +{ + return TRUE; +} + + + +/* _al_file_size_ex: + * Measures the size of the specified file. + */ +uint64_t _al_file_size_ex(AL_CONST char *filename) +{ + struct _stat s; + char tmp[1024]; + + if (get_filename_encoding() != U_UNICODE) { + if (_stat(uconvert(filename, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &s) != 0) { + *allegro_errno = errno; + return 0; + } + } + else { + if (_wstat((wchar_t*)uconvert(filename, U_CURRENT, tmp, U_UNICODE, + sizeof(tmp)), &s) != 0) { + *allegro_errno = errno; + return 0; + } + } + + return s.st_size; +} + + + +/* _al_file_time: + * Returns the timestamp of the specified file. + */ +time_t _al_file_time(AL_CONST char *filename) +{ + struct _stat s; + char tmp[1024]; + + if (get_filename_encoding() != U_UNICODE) { + if (_stat(uconvert(filename, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &s) != 0) { + *allegro_errno = errno; + return 0; + } + } + else { + if (_wstat((wchar_t*)uconvert(filename, U_CURRENT, tmp, U_UNICODE, sizeof(tmp)), &s) != 0) { + *allegro_errno = errno; + return 0; + } + } + + return s.st_mtime; +} + + + +/* structure for use by the directory scanning routines */ +struct FF_DATA +{ + union { + struct _finddata_t a; + struct _wfinddata_t w; + } data; + long handle; + int attrib; +}; + + + +/* fill_ffblk: + * Helper function to fill in an al_ffblk structure. + */ +static void fill_ffblk(struct al_ffblk *info) +{ + struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; + + if (get_filename_encoding() != U_UNICODE) { + info->attrib = ff_data->data.a.attrib; + info->time = ff_data->data.a.time_write; + info->size = ff_data->data.a.size; + + do_uconvert(ff_data->data.a.name, U_ASCII, info->name, U_CURRENT, + sizeof(info->name)); + } + else { + info->attrib = ff_data->data.w.attrib; + info->time = ff_data->data.w.time_write; + info->size = ff_data->data.w.size; + + do_uconvert((const char*)ff_data->data.w.name, U_UNICODE, info->name, + U_CURRENT, sizeof(info->name)); + } +} + + + +/* al_findfirst: + * Initiates a directory search. + */ +int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) +{ + struct FF_DATA *ff_data; + char tmp[1024]; + + /* allocate ff_data structure */ + ff_data = _AL_MALLOC(sizeof(struct FF_DATA)); + + if (!ff_data) { + *allegro_errno = ENOMEM; + return -1; + } + + /* attach it to the info structure */ + info->ff_data = (void *) ff_data; + + /* Windows defines specific flags for NTFS permissions: + * FA_TEMPORARY 0x0100 + * FA_SPARSE_FILE 0x0200 + * FA_REPARSE_POINT 0x0400 + * FA_COMPRESSED 0x0800 + * FA_OFFLINE 0x1000 + * FA_NOT_CONTENT_INDEXED 0x2000 + * FA_ENCRYPTED 0x4000 + * so we must set them in the mask by default; moreover, + * in order to avoid problems with flags added in the + * future, we simply set all bits past the first byte. + */ + ff_data->attrib = attrib | 0xFFFFFF00; + + /* start the search */ + errno = *allegro_errno = 0; + + if (get_filename_encoding() != U_UNICODE) { + ff_data->handle = _findfirst(uconvert(pattern, U_CURRENT, tmp, + U_ASCII, sizeof(tmp)), + &ff_data->data.a); + + if (ff_data->handle < 0) { + *allegro_errno = errno; + _AL_FREE(ff_data); + info->ff_data = NULL; + return -1; + } + + if (ff_data->data.a.attrib & ~ff_data->attrib) { + if (al_findnext(info) != 0) { + al_findclose(info); + return -1; + } + else + return 0; + } + } + else { + ff_data->handle = _wfindfirst((wchar_t*)uconvert(pattern, U_CURRENT, tmp, + U_UNICODE, sizeof(tmp)), + &ff_data->data.w); + + if (ff_data->handle < 0) { + *allegro_errno = errno; + _AL_FREE(ff_data); + info->ff_data = NULL; + return -1; + } + + if (ff_data->data.w.attrib & ~ff_data->attrib) { + if (al_findnext(info) != 0) { + al_findclose(info); + return -1; + } + else + return 0; + } + } + + fill_ffblk(info); + return 0; +} + + + +/* al_findnext: + * Retrieves the next file from a directory search. + */ +int al_findnext(struct al_ffblk *info) +{ + struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; + + if (get_filename_encoding() != U_UNICODE) { + do { + if (_findnext(ff_data->handle, &ff_data->data.a) != 0) { + *allegro_errno = errno; + return -1; + } + } while (ff_data->data.a.attrib & ~ff_data->attrib); + } + else { + do { + if (_wfindnext(ff_data->handle, &ff_data->data.w) != 0) { + *allegro_errno = errno; + return -1; + } + } while (ff_data->data.w.attrib & ~ff_data->attrib); + } + + fill_ffblk(info); + return 0; +} + + + +/* al_findclose: + * Cleans up after a directory search. + */ +void al_findclose(struct al_ffblk *info) +{ + struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; + + if (ff_data) { + _findclose(ff_data->handle); + _AL_FREE(ff_data); + info->ff_data = NULL; + } +} + + + +/* _al_drive_exists: + * Checks whether the specified drive is valid. + */ +int _al_drive_exists(int drive) +{ + return GetLogicalDrives() & (1 << drive); +} + + + +/* _al_getdrive: + * Returns the current drive number (0=A, 1=B, etc). + */ +int _al_getdrive(void) +{ + return _getdrive() - 1; +} + + + +/* _al_getdcwd: + * Returns the current directory on the specified drive. + */ +void _al_getdcwd(int drive, char *buf, int size) +{ + char tmp[1024]; + + if (get_filename_encoding() != U_UNICODE) { + if (_getdcwd(drive+1, tmp, sizeof(tmp))) + do_uconvert(tmp, U_ASCII, buf, U_CURRENT, size); + else + usetc(buf, 0); + } + else { + if (_wgetdcwd(drive+1, (wchar_t*)tmp, sizeof(tmp)/sizeof(wchar_t))) + do_uconvert(tmp, U_UNICODE, buf, U_CURRENT, size); + else + usetc(buf, 0); + } +} + + + +/* _al_ffblk_get_size: + * Returns the size out of an _al_ffblk structure. + */ +uint64_t al_ffblk_get_size(struct al_ffblk *info) +{ + struct FF_DATA *ff_data; + + ASSERT(info); + ff_data = (struct FF_DATA *) info->ff_data; + + if (get_filename_encoding() != U_UNICODE) { + return ff_data->data.a.size; + } + else { + return ff_data->data.w.size; + } +} + + + +/* _al_win_open: + * Open a file with open() or _wopen() depending on whether Unicode filenames + * are supported by this version of Windows and compiler. + */ +int _al_win_open(const char *filename, int mode, int perm) +{ + if (get_filename_encoding() != U_UNICODE) { + return open(filename, mode, perm); + } + else { + return _wopen((wchar_t*)filename, mode, perm); + } +} + + + +/* _al_win_unlink: + * Remove a file with unlink() or _wunlink() depending on whether Unicode + * filenames are supported by this version of Windows and compiler. + */ +int _al_win_unlink(const char *pathname) +{ + if (get_filename_encoding() != U_UNICODE) { + return unlink(pathname); + } + else { + return _wunlink((wchar_t*)pathname); + } +} + From 6f02815b280e2ae20fbfaec2d7250cf436c469f7 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 20 Nov 2020 21:11:33 +0300 Subject: [PATCH 31/41] Platform detection for stripped Allegro lib --- .../include/allegro/internal/alconfig.h | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/libsrc/allegro/include/allegro/internal/alconfig.h b/libsrc/allegro/include/allegro/internal/alconfig.h index 0b27004486a..ec2e18345f8 100644 --- a/libsrc/allegro/include/allegro/internal/alconfig.h +++ b/libsrc/allegro/include/allegro/internal/alconfig.h @@ -23,10 +23,32 @@ #define ALLEGRO_COLOR32 -/* for backward compatibility */ -#ifdef USE_CONSOLE - #define ALLEGRO_NO_MAGIC_MAIN - #define ALLEGRO_USE_CONSOLE +/* autodetect platform */ +#if defined(__ANDROID__) || defined(ANDROID) + #define ALLEGRO_ANDROID +#elif defined(_MSC_VER) + #define ALLEGRO_MSVC +#elif defined(__APPLE__) + #include "TargetConditionals.h" + #ifndef TARGET_OS_SIMULATOR + #define TARGET_OS_SIMULATOR (0) + #endif + #ifndef TARGET_OS_IOS + #define TARGET_OS_IOS (0) + #endif + #ifndef TARGET_OS_OSX + #define TARGET_OS_OSX (0) + #endif + + #if TARGET_OS_SIMULATOR || TARGET_IPHONE_SIMULATOR + #define ALLEGRO_IOS + #elif TARGET_OS_IOS || TARGET_OS_IPHONE + #define ALLEGRO_IOS + #elif TARGET_OS_OSX || TARGET_OS_MAC + #define ALLEGRO_MACOSX + #endif +#elif defined(__linux__) + #define ALLEGRO_UNIX #endif From f7893e0fce6d4a25b378d0fbf2fdc0b80da753a3 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Wed, 11 Nov 2020 01:37:34 +0300 Subject: [PATCH 32/41] APEG: removed screen bitmap reference --- Engine/libsrc/apeg-1.2.1/adisplay.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Engine/libsrc/apeg-1.2.1/adisplay.c b/Engine/libsrc/apeg-1.2.1/adisplay.c index 1f183220c6a..94d92a9bd88 100644 --- a/Engine/libsrc/apeg-1.2.1/adisplay.c +++ b/Engine/libsrc/apeg-1.2.1/adisplay.c @@ -217,8 +217,6 @@ void apeg_initialize_display(APEG_LAYER *layer, int cs) // Set the color depth, and make sure it's valid if(override_depth > 0) depth = override_depth; - else if(screen != NULL) - depth = bitmap_color_depth(screen); else depth = 32; From cda448e0106dec620fd56433ee320902f651af92 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 13 Nov 2020 17:28:07 +0300 Subject: [PATCH 33/41] Rewrote FLI playback in the engine, using Allegro only to read frames --- Engine/media/video/video.cpp | 67 +++++++++++++++++++--------- libsrc/allegro/include/allegro/fli.h | 2 +- libsrc/allegro/src/fli.c | 33 +++----------- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/Engine/media/video/video.cpp b/Engine/media/video/video.cpp index fd38eaa4d0a..f0ceaa5ac8d 100644 --- a/Engine/media/video/video.cpp +++ b/Engine/media/video/video.cpp @@ -15,12 +15,9 @@ #include "media/video/video.h" #ifndef AGS_NO_VIDEO_PLAYER - +#include #include "apeg.h" #include "core/platform.h" -#define AGS_FLI_FROM_PACK_FILE ((ALLEGRO_DATE >= 20190303) || \ - AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_MACOS) - #include "debug/debug_log.h" #include "debug/out.h" #include "ac/asset_helper.h" @@ -68,6 +65,7 @@ Bitmap *hicol_buf=nullptr; IDriverDependantBitmap *fli_ddb = nullptr; Bitmap *fli_target = nullptr; int fliTargetWidth, fliTargetHeight; +volatile int fli_timer = 0; // TODO: use SDL thread conditions instead? int check_if_user_input_should_cancel_video() { int key, mbut, mwheelz; @@ -83,11 +81,13 @@ int check_if_user_input_should_cancel_video() return 0; } -#if AGS_PLATFORM_OS_WINDOWS -int __cdecl fli_callback() { -#else -extern "C" int fli_callback() { -#endif +Uint32 fli_timer_callback(Uint32 interval, void *param) +{ + fli_timer++; + return interval; +} + +int fli_callback() { Bitmap *usebuf = fli_buffer; update_audio_system_on_game_loop (); @@ -183,24 +183,50 @@ void play_flc_file(int numb,int playflags) { fli_target = BitmapHelper::CreateBitmap(view.GetWidth(), view.GetHeight(), game.GetColorDepth()); fli_ddb = gfxDriver->CreateDDBFromBitmap(fli_target, false, true); - // TODO: find a better solution. - // Make only certain versions of the engineuse play_fli_pf from the patched version of Allegro for now. - // Add more versions as their Allegro lib becomes patched too, or they use newer version of Allegro 4. - // Ports can still play FLI if separate file is put into game's directory. -#if AGS_FLI_FROM_PACK_FILE size_t asset_size; PACKFILE *pf = PackfileFromAsset(AssetPath("", flicname), asset_size); - if (play_fli_pf(pf, (BITMAP*)fli_buffer->GetAllegroBitmap(), fli_callback)==FLI_ERROR) -#else - if (play_fli(flicname, (BITMAP*)fli_buffer->GetAllegroBitmap(), 0, fli_callback)==FLI_ERROR) -#endif + if (open_fli_pf(pf) == FLI_OK) + { + // TODO: refactor all this later!!! + SDL_AddTimer(fli_speed, fli_timer_callback, nullptr); + const int loop = 0; // TODO: add looping FLIC support to API? + + // actual FLI playback state, base on original Allegro 4's do_play_fli + fli_timer = 1; + int ret = next_fli_frame(loop); + while (ret == FLI_OK) { + /* update the palette */ + if (fli_pal_dirty_from <= fli_pal_dirty_to) + set_palette_range(fli_palette, fli_pal_dirty_from, fli_pal_dirty_to, TRUE); + + /* update the screen */ + if (fli_bmp_dirty_from <= fli_bmp_dirty_to) { + blit(fli_bitmap, fli_buffer->GetAllegroBitmap(), 0, fli_bmp_dirty_from, 0, fli_bmp_dirty_from, + fli_bitmap->w, 1 + fli_bmp_dirty_to - fli_bmp_dirty_from); + } + + reset_fli_variables(); + + ret = fli_callback(); + if (ret != FLI_OK) + break; + + ret = next_fli_frame(loop); + fli_timer--; + + while (fli_timer <= 0) { + /* wait a bit */ + SDL_Delay(1); + } + } + } + else { // This is not a fatal error that should prevent the game from continuing Debug::Printf("FLI/FLC animation play error"); } -#if AGS_FLI_FROM_PACK_FILE pack_fclose(pf); -#endif + video_type = kVideoNone; delete fli_buffer; @@ -372,7 +398,6 @@ void play_theora_video(const char *name, int skip, int flags) stop_all_sound_and_music(); } - //fli_buffer = BitmapHelper::CreateBitmap_(scsystem.coldepth, videoWidth, videoHeight); calculate_destination_size_maintain_aspect_ratio(videoWidth, videoHeight, &fliTargetWidth, &fliTargetHeight); if ((fliTargetWidth == videoWidth) && (fliTargetHeight == videoHeight) && (stretch_flc)) diff --git a/libsrc/allegro/include/allegro/fli.h b/libsrc/allegro/include/allegro/fli.h index 5760789ffd3..e6a0da794c8 100644 --- a/libsrc/allegro/include/allegro/fli.h +++ b/libsrc/allegro/include/allegro/fli.h @@ -51,7 +51,7 @@ AL_VAR(int, fli_pal_dirty_to); AL_VAR(int, fli_frame); /* current frame number */ -AL_VAR(volatile int, fli_timer); /* for timing FLI playback */ +AL_VAR(int, fli_speed); /* FLI playback speed factor, in milliseconds */ #ifdef __cplusplus } diff --git a/libsrc/allegro/src/fli.c b/libsrc/allegro/src/fli.c index 8b5876aa0ae..8ff8760ffaf 100644 --- a/libsrc/allegro/src/fli.c +++ b/libsrc/allegro/src/fli.c @@ -85,7 +85,7 @@ int fli_pal_dirty_to = INT_MIN; int fli_frame = 0; /* current frame number in the FLI */ -volatile int fli_timer = 0; /* for timing FLI playback */ +int fli_speed = 0; /* speed of the fli playback */ static PACKFILE *fli_file = NULL; /* the file we are reading */ static char *fli_filename = NULL; /* name of the file */ @@ -100,18 +100,6 @@ static unsigned char _fli_broken_data[3 * 256]; /* data substituted for broken c -/* fli_timer_callback: - * Timer interrupt handler for syncing FLI files. - */ -static void fli_timer_callback(void) -{ - fli_timer++; -} - -END_OF_STATIC_FUNCTION(fli_timer_callback); - - - /* fli_read: * Helper function to get a block of data from the FLI, which can read * from disk or a copy of the FLI held in memory. If buf is set, that is @@ -871,22 +859,15 @@ static int do_open_fli(void) reset_fli_variables(); fli_frame = 0; - fli_timer = 2; fli_status = FLI_OK; - /* install the timer handler */ - LOCK_VARIABLE(fli_timer); - LOCK_FUNCTION(fli_timer_callback); - if (fli_header.type == FLI_MAGIC1) - speed = BPS_TO_TIMER(70) * (long)fli_header.speed; + fli_speed = (1000 * (long)fli_header.speed) / 70; else - speed = MSEC_TO_TIMER((long)fli_header.speed); + fli_speed = (long)fli_header.speed; - if (speed == 0) - speed = BPS_TO_TIMER(70); - - install_int_ex(fli_timer_callback, speed); + if (fli_speed == 0) + fli_speed = 1000 / 70; return fli_status; } @@ -969,7 +950,7 @@ int open_memory_fli(void *fli_data) */ void close_fli(void) { - remove_int(fli_timer_callback); + fli_speed = 0; if (fli_file) { /* if fli_filename is NULL this means that the packfile was @@ -1017,8 +998,6 @@ int next_fli_frame(int loop) if (fli_status != FLI_OK) return fli_status; - fli_timer--; - /* end of file? should we loop? */ if (fli_frame >= fli_header.frame_count) { if (loop) { From 9bc8d3d04002abc97e71485a676e7f2394c02fbf Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 12 Nov 2020 04:29:58 +0300 Subject: [PATCH 34/41] Editor: fixed compilation with the stripped allegro source --- Editor/AGS.Native/NativeDLL.vcxproj | 8 ++++---- Editor/AGS.Native/agsnative.cpp | 27 ++++++++++++++------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Editor/AGS.Native/NativeDLL.vcxproj b/Editor/AGS.Native/NativeDLL.vcxproj index 3d47d963b37..bfc55dbed3d 100644 --- a/Editor/AGS.Native/NativeDLL.vcxproj +++ b/Editor/AGS.Native/NativeDLL.vcxproj @@ -99,7 +99,7 @@ false - Common_md_d.lib;Compiler_md_d.lib;winmm.lib;imm32.lib;shlwapi.lib;alleg-debug-static.lib;ddraw.lib;dsound.lib;dinput.lib;dxguid.lib;%(AdditionalDependencies) + Common_md_d.lib;Compiler_md_d.lib;winmm.lib;imm32.lib;shlwapi.lib;%(AdditionalDependencies) $(SolutionDir)\.lib\Debug_MD;$(SolutionDir)\..\Windows\lib;%(AdditionalLibraryDirectories) LIBCMTD.lib;%(IgnoreSpecificDefaultLibraries) @@ -132,8 +132,8 @@ MaxSpeed - ..\..;..\..\Common;..\..\Common\libinclude;..\..\Compiler;..\Native;..\scintilla\include;..\..\Windows\include;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;NDEBUG;_USRDLL;WINDOWS_VERSION;ALLEGRO_STATICLINK;ALLEGRO_NO_FIX_ALIASES;_MERGE_PROXYSTUB;STATIC_BUILD;SCI_LEXER;USE_ALFONT;_BIND_TO_CURRENT_VCLIBS_VERSION=1;%(PreprocessorDefinitions) + ..\..;..\..\Common;..\..\Common\libinclude;..\..\Compiler;..\Native;..\scintilla\include;..\..\Windows\include;..\..\libsrc\allegro\include;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;NDEBUG;_USRDLL;WINDOWS_VERSION;ALLEGRO_STATICLINK;ALLEGRO_NO_FIX_ALIASES;ALLEGRO_NO_MAGIC_MAIN;ALLEGRO_MSVC;_MERGE_PROXYSTUB;STATIC_BUILD;SCI_LEXER;USE_ALFONT;_BIND_TO_CURRENT_VCLIBS_VERSION=1;%(PreprocessorDefinitions) MultiThreadedDLL 4Bytes @@ -149,7 +149,7 @@ false - Common_md.lib;Compiler_md.lib;winmm.lib;imm32.lib;shlwapi.lib;alleg-static.lib;ddraw.lib;dsound.lib;dinput.lib;dxguid.lib;%(AdditionalDependencies) + Common_md.lib;Compiler_md.lib;winmm.lib;imm32.lib;shlwapi.lib;%(AdditionalDependencies) $(SolutionDir)\.lib\Release_MD;$(SolutionDir)\..\Windows\lib;%(AdditionalLibraryDirectories) LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) diff --git a/Editor/AGS.Native/agsnative.cpp b/Editor/AGS.Native/agsnative.cpp index 47fb4b6cfe2..7c8f94e139d 100644 --- a/Editor/AGS.Native/agsnative.cpp +++ b/Editor/AGS.Native/agsnative.cpp @@ -6,9 +6,10 @@ extern bool Scintilla_RegisterClasses(void *hInstance); extern int Scintilla_LinkLexers(); #include "agsnative.h" -#include "util/wgt2allg.h" +#include #include #include "util/misc.h" +#include "util/wgt2allg.h" #include "ac/spritecache.h" #include "ac/actiontype.h" #include "ac/scriptmodule.h" @@ -76,7 +77,7 @@ int antiAliasFonts = 0; int dsc_want_hires = 0; bool enable_greyed_out_masks = true; bool outlineGuiObjects = false; -color*palette = NULL; +RGB*palette = NULL; GameSetupStruct thisgame; SpriteCache spriteset(thisgame.SpriteInfos); GUIMain tempgui; @@ -750,7 +751,7 @@ void restore_from_undo_buffer(void *roomptr, int maskType) void setup_greyed_out_palette(int selCol) { - color thisColourOnlyPal[256]; + RGB thisColourOnlyPal[256]; // The code below makes it so that all the hotspot colours // except the selected one are greyed out. It doesn't work @@ -1298,7 +1299,7 @@ void drawGUIAt (int hdc, int x,int y,int x1,int y1,int x2,int y2, int resolution #define SIMP_NONE 6 // Adjusts sprite's transparency using the chosen method -void sort_out_transparency(Common::Bitmap *toimp, int sprite_import_method, color*itspal, int importedColourDepth, +void sort_out_transparency(Common::Bitmap *toimp, int sprite_import_method, RGB*itspal, int importedColourDepth, int &transcol) { if (sprite_import_method == SIMP_LEAVEALONE) @@ -1361,7 +1362,7 @@ void sort_out_transparency(Common::Bitmap *toimp, int sprite_import_method, colo } // Adjusts 8-bit sprite's palette -void sort_out_palette(Common::Bitmap *toimp, color*itspal, bool useBgSlots, int transcol) +void sort_out_palette(Common::Bitmap *toimp, RGB*itspal, bool useBgSlots, int transcol) { set_palette_range(palette, 0, 255, 0); if ((thisgame.color_depth == 1) && (itspal != NULL)) { @@ -1370,7 +1371,7 @@ void sort_out_palette(Common::Bitmap *toimp, color*itspal, bool useBgSlots, int itspal[transcol] = itspal[0]; wsetrgb(0,0,0,0,itspal); // set index 0 to black __wremap_keep_transparent = 1; - color oldpale[256]; + RGB oldpale[256]; for (int uu=0;uu<255;uu++) { if (useBgSlots) // use background scene palette oldpale[uu]=palette[uu]; @@ -1517,7 +1518,7 @@ void free_old_game_data() } // remap the scene, from its current palette oldpale to palette -void remap_background (Common::Bitmap *scene, color *oldpale, color*palette, int exactPal) { +void remap_background (Common::Bitmap *scene, RGB *oldpale, RGB*palette, int exactPal) { int a; if (exactPal) { @@ -1549,7 +1550,7 @@ void remap_background (Common::Bitmap *scene, color *oldpale, color*palette, int } // count up the number of unique colours in the image int numclr=0,bb; - color tpal[256]; + RGB tpal[256]; for (a=0;a<256;a++) { if (thisgame.paluses[a]==PAL_BACKGROUND) wsetrgb(a,0,0,0,palette); // black out the bg slots before starting @@ -2337,7 +2338,7 @@ void drawViewLoop (int hdc, ViewLoop^ loopToDraw, int x, int y, int size, int cu free(frames); } -Common::Bitmap *CreateBlockFromBitmap(System::Drawing::Bitmap ^bmp, color *imgpal, bool fixColourDepth, bool keepTransparency, int *originalColDepth) +Common::Bitmap *CreateBlockFromBitmap(System::Drawing::Bitmap ^bmp, RGB *imgpal, bool fixColourDepth, bool keepTransparency, int *originalColDepth) { int colDepth; if (bmp->PixelFormat == PixelFormat::Format8bppIndexed) @@ -2488,7 +2489,7 @@ void DeleteBackground(Room ^room, int backgroundNumber) void ImportBackground(Room ^room, int backgroundNumber, System::Drawing::Bitmap ^bmp, bool useExactPalette, bool sharePalette) { - color oldpale[256]; + RGB oldpale[256]; Common::Bitmap *newbg = CreateBlockFromBitmap(bmp, oldpale, true, false, NULL); RoomStruct *theRoom = (RoomStruct*)(void*)room->_roomStructPtr; theRoom->Width = room->Width; @@ -2507,7 +2508,7 @@ void ImportBackground(Room ^room, int backgroundNumber, System::Drawing::Bitmap // sharing palette with main background - so copy it across if (sharePalette) { - memcpy (&theRoom->BgFrames[backgroundNumber].Palette[0], &palette[0], sizeof(color) * 256); + memcpy (&theRoom->BgFrames[backgroundNumber].Palette[0], &palette[0], sizeof(RGB) * 256); theRoom->BgFrames[backgroundNumber].IsPaletteShared = 1; if ((size_t)backgroundNumber >= theRoom->BgFrameCount - 1) theRoom->BgFrames[0].IsPaletteShared = 1; @@ -2549,7 +2550,7 @@ void ImportBackground(Room ^room, int backgroundNumber, System::Drawing::Bitmap void import_area_mask(void *roomptr, int maskType, System::Drawing::Bitmap ^bmp) { - color oldpale[256]; + RGB oldpale[256]; Common::Bitmap *importedImage = CreateBlockFromBitmap(bmp, oldpale, false, false, NULL); Common::Bitmap *mask = get_bitmap_for_mask((RoomStruct*)roomptr, (RoomAreaMask)maskType); @@ -2603,7 +2604,7 @@ void set_opaque_alpha_channel(Common::Bitmap *image) AGS::Types::SpriteImportResolution SetNewSpriteFromBitmap(int slot, System::Drawing::Bitmap^ bmp, int spriteImportMethod, bool remapColours, bool useRoomBackgroundColours, bool alphaChannel) { - color imgPalBuf[256]; + RGB imgPalBuf[256]; int importedColourDepth; Common::Bitmap *tempsprite = CreateBlockFromBitmap(bmp, imgPalBuf, true, (spriteImportMethod != SIMP_NONE), &importedColourDepth); From cd33b9a2c9cb135af2c7312fbd818fab70e47333 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Mon, 16 Nov 2020 12:10:52 +0300 Subject: [PATCH 35/41] Common: compat version of make_unique (w/o C++14 support) --- Common/util/memory_compat.h | 30 +++++++++++++++++++ Engine/media/audio/audio_core.cpp | 1 + Solutions/Common.Lib/Common.Lib.vcxproj | 1 + .../Common.Lib/Common.Lib.vcxproj.filters | 3 ++ 4 files changed, 35 insertions(+) create mode 100644 Common/util/memory_compat.h diff --git a/Common/util/memory_compat.h b/Common/util/memory_compat.h new file mode 100644 index 00000000000..37ece3fc862 --- /dev/null +++ b/Common/util/memory_compat.h @@ -0,0 +1,30 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// http://www.opensource.org/licenses/artistic-license-2.0.php +// +//============================================================================= +#ifndef __AGS_CN_UTIL__MEMORY_COMPAT_H +#define __AGS_CN_UTIL__MEMORY_COMPAT_H +#include + +// C++14 features +#if __cplusplus < 201402L && !((defined(_MSC_VER) && _MSC_VER >= 1900)) +namespace std +{ + template + std::unique_ptr make_unique(Args&&... args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } +} // std +#endif + +#endif // __AGS_CN_UTIL__MEMORY_COMPAT_H diff --git a/Engine/media/audio/audio_core.cpp b/Engine/media/audio/audio_core.cpp index b39dc04add6..e1f7af6a9ff 100644 --- a/Engine/media/audio/audio_core.cpp +++ b/Engine/media/audio/audio_core.cpp @@ -23,6 +23,7 @@ #include #include "debug/out.h" #include "media/audio/openaldecoder.h" +#include "util/memory_compat.h" namespace ags = AGS::Common; namespace agsdbg = AGS::Common::Debug; diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj b/Solutions/Common.Lib/Common.Lib.vcxproj index 39cce34a2f0..2d64a06b25d 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj +++ b/Solutions/Common.Lib/Common.Lib.vcxproj @@ -496,6 +496,7 @@ + diff --git a/Solutions/Common.Lib/Common.Lib.vcxproj.filters b/Solutions/Common.Lib/Common.Lib.vcxproj.filters index 208a6d57583..4b0bf0252e2 100644 --- a/Solutions/Common.Lib/Common.Lib.vcxproj.filters +++ b/Solutions/Common.Lib/Common.Lib.vcxproj.filters @@ -793,5 +793,8 @@ Library Sources\allegro\c + + Header Files\util + \ No newline at end of file From 4d26d62451f7587f2328d61c0fe38ee86438436c Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Mon, 16 Nov 2020 12:50:16 +0300 Subject: [PATCH 36/41] Removed hq2x filter source --- Engine/libsrc/hq2x/CMakeLists.txt | 17 - Engine/libsrc/hq2x/hq2x3x.cpp | 6681 ----------------- Engine/libsrc/hq2x/hq2x3x.h | 30 - Solutions/Engine.App/Engine.App.vcxproj | 1 - .../Engine.App/Engine.App.vcxproj.filters | 18 +- 5 files changed, 6 insertions(+), 6741 deletions(-) delete mode 100644 Engine/libsrc/hq2x/CMakeLists.txt delete mode 100644 Engine/libsrc/hq2x/hq2x3x.cpp delete mode 100644 Engine/libsrc/hq2x/hq2x3x.h diff --git a/Engine/libsrc/hq2x/CMakeLists.txt b/Engine/libsrc/hq2x/CMakeLists.txt deleted file mode 100644 index d2f4938c9cf..00000000000 --- a/Engine/libsrc/hq2x/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_library(hq2x) - -set_target_properties(hq2x PROPERTIES - CXX_STANDARD 11 - CXX_EXTENSIONS NO -) - -target_include_directories(hq2x PUBLIC . ) - -target_sources(hq2x - PRIVATE - hq2x3x.cpp -) - -target_link_libraries(hq2x PUBLIC AGS::Common) - -add_library(HQ2X::hq2x ALIAS hq2x) diff --git a/Engine/libsrc/hq2x/hq2x3x.cpp b/Engine/libsrc/hq2x/hq2x3x.cpp deleted file mode 100644 index c0cacea24f4..00000000000 --- a/Engine/libsrc/hq2x/hq2x3x.cpp +++ /dev/null @@ -1,6681 +0,0 @@ -//hq2x filter demo program -//---------------------------------------------------------- -//Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) - -//This program is free software; you can redistribute it and/or -//modify it under the terms of the GNU Lesser General Public -//License as published by the Free Software Foundation; either -//version 2.1 of the License, or (at your option) any later version. -// -//This program 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 -//Lesser General Public License for more details. -// -//You should have received a copy of the GNU Lesser General Public -//License along with this program; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#include -#include "core/types.h" - -static int LUT16to32[65536]; -static int RGBtoYUV[65536]; -static int YUV1, YUV2; -const int Ymask = 0x00FF0000; -const int Umask = 0x0000FF00; -const int Vmask = 0x000000FF; -const int trY = 0x00300000; -const int trU = 0x00000700; -const int trV = 0x00000006; - -inline void Interp1(unsigned char * pc, int c1, int c2) -{ - *((int*)pc) = (c1*3+c2) >> 2; -} - -inline void Interp2(unsigned char * pc, int c1, int c2, int c3) -{ - *((int*)pc) = (c1*2+c2+c3) >> 2; -} - -inline void Interp3(unsigned char * pc, int c1, int c2) -{ - //*((int*)pc) = (c1*7+c2)/8; - - *((int*)pc) = ((((c1 & 0x00FF00)*7 + (c2 & 0x00FF00) ) & 0x0007F800) + - (((c1 & 0xFF00FF)*7 + (c2 & 0xFF00FF) ) & 0x07F807F8)) >> 3; -} - -inline void Interp4(unsigned char * pc, int c1, int c2, int c3) -{ - //*((int*)pc) = (c1*2+(c2+c3)*7)/16; - - *((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*7 ) & 0x000FF000) + - (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*7 ) & 0x0FF00FF0)) >> 4; -} - -inline void Interp5(unsigned char * pc, int c1, int c2) -{ - *((int*)pc) = (c1+c2) >> 1; -} - -inline void Interp6(unsigned char * pc, int c1, int c2, int c3) -{ - //*((int*)pc) = (c1*5+c2*2+c3)/8; - - *((int*)pc) = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*2 + (c3 & 0x00FF00) ) & 0x0007F800) + - (((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*2 + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; -} - -inline void Interp7(unsigned char * pc, int c1, int c2, int c3) -{ - //*((int*)pc) = (c1*6+c2+c3)/8; - - *((int*)pc) = ((((c1 & 0x00FF00)*6 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x0007F800) + - (((c1 & 0xFF00FF)*6 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; -} - -inline void Interp9(unsigned char * pc, int c1, int c2, int c3) -{ - //*((int*)pc) = (c1*2+(c2+c3)*3)/8; - - *((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*3 ) & 0x0007F800) + - (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*3 ) & 0x07F807F8)) >> 3; -} - -inline void Interp10(unsigned char * pc, int c1, int c2, int c3) -{ - //*((int*)pc) = (c1*14+c2+c3)/16; - - *((int*)pc) = ((((c1 & 0x00FF00)*14 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x000FF000) + - (((c1 & 0xFF00FF)*14 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x0FF00FF0)) >> 4; -} - - -#define PIXEL00_0 *((int*)(pOut)) = c[5]; -#define PIXEL00_10 Interp1(pOut, c[5], c[1]); -#define PIXEL00_11 Interp1(pOut, c[5], c[4]); -#define PIXEL00_12 Interp1(pOut, c[5], c[2]); -#define PIXEL00_20 Interp2(pOut, c[5], c[4], c[2]); -#define PIXEL00_21 Interp2(pOut, c[5], c[1], c[2]); -#define PIXEL00_22 Interp2(pOut, c[5], c[1], c[4]); -#define PIXEL00_60 Interp6(pOut, c[5], c[2], c[4]); -#define PIXEL00_61 Interp6(pOut, c[5], c[4], c[2]); -#define PIXEL00_70 Interp7(pOut, c[5], c[4], c[2]); -#define PIXEL00_90 Interp9(pOut, c[5], c[4], c[2]); -#define PIXEL00_100 Interp10(pOut, c[5], c[4], c[2]); -#define PIXEL01_0 *((int*)(pOut+4)) = c[5]; -#define PIXEL01_10 Interp1(pOut+4, c[5], c[3]); -#define PIXEL01_11 Interp1(pOut+4, c[5], c[2]); -#define PIXEL01_12 Interp1(pOut+4, c[5], c[6]); -#define PIXEL01_20 Interp2(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_21 Interp2(pOut+4, c[5], c[3], c[6]); -#define PIXEL01_22 Interp2(pOut+4, c[5], c[3], c[2]); -#define PIXEL01_60 Interp6(pOut+4, c[5], c[6], c[2]); -#define PIXEL01_61 Interp6(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_70 Interp7(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_90 Interp9(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_100 Interp10(pOut+4, c[5], c[2], c[6]); -#define PIXEL10_0 *((int*)(pOut+BpL)) = c[5]; -#define PIXEL10_10 Interp1(pOut+BpL, c[5], c[7]); -#define PIXEL10_11 Interp1(pOut+BpL, c[5], c[8]); -#define PIXEL10_12 Interp1(pOut+BpL, c[5], c[4]); -#define PIXEL10_20 Interp2(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_21 Interp2(pOut+BpL, c[5], c[7], c[4]); -#define PIXEL10_22 Interp2(pOut+BpL, c[5], c[7], c[8]); -#define PIXEL10_60 Interp6(pOut+BpL, c[5], c[4], c[8]); -#define PIXEL10_61 Interp6(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_70 Interp7(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_90 Interp9(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_100 Interp10(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL11_0 *((int*)(pOut+BpL+4)) = c[5]; -#define PIXEL11_10 Interp1(pOut+BpL+4, c[5], c[9]); -#define PIXEL11_11 Interp1(pOut+BpL+4, c[5], c[6]); -#define PIXEL11_12 Interp1(pOut+BpL+4, c[5], c[8]); -#define PIXEL11_20 Interp2(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_21 Interp2(pOut+BpL+4, c[5], c[9], c[8]); -#define PIXEL11_22 Interp2(pOut+BpL+4, c[5], c[9], c[6]); -#define PIXEL11_60 Interp6(pOut+BpL+4, c[5], c[8], c[6]); -#define PIXEL11_61 Interp6(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_70 Interp7(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_90 Interp9(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_100 Interp10(pOut+BpL+4, c[5], c[6], c[8]); - - - -inline bool Diff(unsigned int w1, unsigned int w2) -{ - YUV1 = RGBtoYUV[w1]; - YUV2 = RGBtoYUV[w2]; - return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || - ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || - ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); -} - -#define INPUT_IMAGE_PIXEL_SIZE uint32_t -#define INPUT_IMAGE_PIXEL_SIZE_IN_BYTES sizeof(INPUT_IMAGE_PIXEL_SIZE) - -void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ) -{ - int i, j, k; - int prevline, nextline; - int w[10]; - int c[10]; - - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ - - for (j=0; j0) prevline = -Xres*4; else prevline = 0; - if (j0) - { - w[1] = *((INPUT_IMAGE_PIXEL_SIZE*)(pIn + prevline - INPUT_IMAGE_PIXEL_SIZE_IN_BYTES)); - w[4] = *((INPUT_IMAGE_PIXEL_SIZE*)(pIn - INPUT_IMAGE_PIXEL_SIZE_IN_BYTES)); - w[7] = *((INPUT_IMAGE_PIXEL_SIZE*)(pIn + nextline - INPUT_IMAGE_PIXEL_SIZE_IN_BYTES)); - } - else - { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } - - if (i> 16) & 0x00ff) / 8) << 11) + - ((((w[k] >> 8) & 0x00ff) / 4) << 5) + - ((w[k] & 0x00ff) / 8)) & 0x000ffff; - } - - int pattern = 0; - int flag = 1; - - YUV1 = RGBtoYUV[w[5]]; - - for (k=1; k<=9; k++) - { - if (k==5) continue; - - if ( w[k] != w[5] ) - { - YUV2 = RGBtoYUV[w[k]]; - if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || - ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || - ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) - pattern |= flag; - } - flag <<= 1; - } - - for (k=1; k<=9; k++) - c[k] = LUT16to32[w[k]]; - - switch (pattern) - { - case 0: - case 1: - case 4: - case 32: - case 128: - case 5: - case 132: - case 160: - case 33: - case 129: - case 36: - case 133: - case 164: - case 161: - case 37: - case 165: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_20 - PIXEL11_20 - break; - } - case 2: - case 34: - case 130: - case 162: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_20 - PIXEL11_20 - break; - } - case 16: - case 17: - case 48: - case 49: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_20 - PIXEL11_21 - break; - } - case 64: - case 65: - case 68: - case 69: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_21 - PIXEL11_22 - break; - } - case 8: - case 12: - case 136: - case 140: - { - PIXEL00_21 - PIXEL01_20 - PIXEL10_22 - PIXEL11_20 - break; - } - case 3: - case 35: - case 131: - case 163: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_20 - PIXEL11_20 - break; - } - case 6: - case 38: - case 134: - case 166: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - } - case 20: - case 21: - case 52: - case 53: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_21 - break; - } - case 144: - case 145: - case 176: - case 177: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_20 - PIXEL11_12 - break; - } - case 192: - case 193: - case 196: - case 197: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_21 - PIXEL11_11 - break; - } - case 96: - case 97: - case 100: - case 101: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_22 - break; - } - case 40: - case 44: - case 168: - case 172: - { - PIXEL00_21 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - } - case 9: - case 13: - case 137: - case 141: - { - PIXEL00_12 - PIXEL01_20 - PIXEL10_22 - PIXEL11_20 - break; - } - case 18: - case 50: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_20 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 80: - case 81: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_20 - } - break; - } - case 72: - case 76: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 10: - case 138: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_22 - PIXEL11_20 - break; - } - case 66: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_21 - PIXEL11_22 - break; - } - case 24: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_22 - PIXEL11_21 - break; - } - case 7: - case 39: - case 135: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - } - case 148: - case 149: - case 180: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_12 - break; - } - case 224: - case 228: - case 225: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_11 - break; - } - case 41: - case 169: - case 45: - { - PIXEL00_12 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - } - case 22: - case 54: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 208: - case 209: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 104: - case 108: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 11: - case 139: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_22 - PIXEL11_20 - break; - } - case 19: - case 51: - { - if (Diff(w[2], w[6])) - { - PIXEL00_11 - PIXEL01_10 - } - else - { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 146: - case 178: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - PIXEL11_12 - } - else - { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_20 - break; - } - case 84: - case 85: - { - PIXEL00_20 - if (Diff(w[6], w[8])) - { - PIXEL01_11 - PIXEL11_10 - } - else - { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_21 - break; - } - case 112: - case 113: - { - PIXEL00_20 - PIXEL01_22 - if (Diff(w[6], w[8])) - { - PIXEL10_12 - PIXEL11_10 - } - else - { - PIXEL10_61 - PIXEL11_90 - } - break; - } - case 200: - case 204: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - PIXEL11_11 - } - else - { - PIXEL10_90 - PIXEL11_60 - } - break; - } - case 73: - case 77: - { - if (Diff(w[8], w[4])) - { - PIXEL00_12 - PIXEL10_10 - } - else - { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_20 - PIXEL11_22 - break; - } - case 42: - case 170: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - PIXEL10_11 - } - else - { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_21 - PIXEL11_20 - break; - } - case 14: - case 142: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - PIXEL01_12 - } - else - { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_22 - PIXEL11_20 - break; - } - case 67: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_21 - PIXEL11_22 - break; - } - case 70: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_21 - PIXEL11_22 - break; - } - case 28: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_22 - PIXEL11_21 - break; - } - case 152: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_22 - PIXEL11_12 - break; - } - case 194: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_21 - PIXEL11_11 - break; - } - case 98: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_12 - PIXEL11_22 - break; - } - case 56: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_11 - PIXEL11_21 - break; - } - case 25: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_22 - PIXEL11_21 - break; - } - case 26: - case 31: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_21 - break; - } - case 82: - case 214: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 88: - case 248: - { - PIXEL00_21 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 74: - case 107: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 27: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_22 - PIXEL11_21 - break; - } - case 86: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_21 - PIXEL11_10 - break; - } - case 216: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 106: - { - PIXEL00_10 - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 30: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_21 - break; - } - case 210: - { - PIXEL00_22 - PIXEL01_10 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 120: - { - PIXEL00_21 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 75: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_10 - PIXEL11_22 - break; - } - case 29: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_22 - PIXEL11_21 - break; - } - case 198: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_21 - PIXEL11_11 - break; - } - case 184: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_11 - PIXEL11_12 - break; - } - case 99: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_12 - PIXEL11_22 - break; - } - case 57: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_11 - PIXEL11_21 - break; - } - case 71: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_21 - PIXEL11_22 - break; - } - case 156: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_22 - PIXEL11_12 - break; - } - case 226: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_12 - PIXEL11_11 - break; - } - case 60: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_11 - PIXEL11_21 - break; - } - case 195: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_21 - PIXEL11_11 - break; - } - case 102: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_12 - PIXEL11_22 - break; - } - case 153: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_22 - PIXEL11_12 - break; - } - case 58: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 83: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 92: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 202: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_11 - break; - } - case 78: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_22 - break; - } - case 154: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_22 - PIXEL11_12 - break; - } - case 114: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 89: - { - PIXEL00_12 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 90: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 55: - case 23: - { - if (Diff(w[2], w[6])) - { - PIXEL00_11 - PIXEL01_0 - } - else - { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 182: - case 150: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - PIXEL11_12 - } - else - { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_20 - break; - } - case 213: - case 212: - { - PIXEL00_20 - if (Diff(w[6], w[8])) - { - PIXEL01_11 - PIXEL11_0 - } - else - { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_21 - break; - } - case 241: - case 240: - { - PIXEL00_20 - PIXEL01_22 - if (Diff(w[6], w[8])) - { - PIXEL10_12 - PIXEL11_0 - } - else - { - PIXEL10_61 - PIXEL11_90 - } - break; - } - case 236: - case 232: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - PIXEL11_11 - } - else - { - PIXEL10_90 - PIXEL11_60 - } - break; - } - case 109: - case 105: - { - if (Diff(w[8], w[4])) - { - PIXEL00_12 - PIXEL10_0 - } - else - { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_20 - PIXEL11_22 - break; - } - case 171: - case 43: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL10_11 - } - else - { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_21 - PIXEL11_20 - break; - } - case 143: - case 15: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL01_12 - } - else - { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_22 - PIXEL11_20 - break; - } - case 124: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 203: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_10 - PIXEL11_11 - break; - } - case 62: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 211: - { - PIXEL00_11 - PIXEL01_10 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 118: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_12 - PIXEL11_10 - break; - } - case 217: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 110: - { - PIXEL00_10 - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 155: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_22 - PIXEL11_12 - break; - } - case 188: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_11 - PIXEL11_12 - break; - } - case 185: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_11 - PIXEL11_12 - break; - } - case 61: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_11 - PIXEL11_21 - break; - } - case 157: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_22 - PIXEL11_12 - break; - } - case 103: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_12 - PIXEL11_22 - break; - } - case 227: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_12 - PIXEL11_11 - break; - } - case 230: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_12 - PIXEL11_11 - break; - } - case 199: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_21 - PIXEL11_11 - break; - } - case 220: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 158: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_12 - break; - } - case 234: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_11 - break; - } - case 242: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 59: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 121: - { - PIXEL00_12 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 87: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 79: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_22 - break; - } - case 122: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 94: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 218: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 91: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 229: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_11 - break; - } - case 167: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - } - case 173: - { - PIXEL00_12 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - } - case 181: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_12 - break; - } - case 186: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_12 - break; - } - case 115: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 93: - { - PIXEL00_12 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 206: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_11 - break; - } - case 205: - case 201: - { - PIXEL00_12 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_11 - break; - } - case 174: - case 46: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_12 - PIXEL10_11 - PIXEL11_20 - break; - } - case 179: - case 147: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_20 - PIXEL11_12 - break; - } - case 117: - case 116: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 189: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_11 - PIXEL11_12 - break; - } - case 231: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_12 - PIXEL11_11 - break; - } - case 126: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 219: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 125: - { - if (Diff(w[8], w[4])) - { - PIXEL00_12 - PIXEL10_0 - } - else - { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_11 - PIXEL11_10 - break; - } - case 221: - { - PIXEL00_12 - if (Diff(w[6], w[8])) - { - PIXEL01_11 - PIXEL11_0 - } - else - { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_10 - break; - } - case 207: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL01_12 - } - else - { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_10 - PIXEL11_11 - break; - } - case 238: - { - PIXEL00_10 - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - PIXEL11_11 - } - else - { - PIXEL10_90 - PIXEL11_60 - } - break; - } - case 190: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - PIXEL11_12 - } - else - { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_11 - break; - } - case 187: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL10_11 - } - else - { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_10 - PIXEL11_12 - break; - } - case 243: - { - PIXEL00_11 - PIXEL01_10 - if (Diff(w[6], w[8])) - { - PIXEL10_12 - PIXEL11_0 - } - else - { - PIXEL10_61 - PIXEL11_90 - } - break; - } - case 119: - { - if (Diff(w[2], w[6])) - { - PIXEL00_11 - PIXEL01_0 - } - else - { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_12 - PIXEL11_10 - break; - } - case 237: - case 233: - { - PIXEL00_12 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - PIXEL11_11 - break; - } - case 175: - case 47: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - PIXEL01_12 - PIXEL10_11 - PIXEL11_20 - break; - } - case 183: - case 151: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_20 - PIXEL11_12 - break; - } - case 245: - case 244: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 250: - { - PIXEL00_10 - PIXEL01_10 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 123: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 95: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_10 - PIXEL11_10 - break; - } - case 222: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 252: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 249: - { - PIXEL00_12 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 235: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - PIXEL11_11 - break; - } - case 111: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 63: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 159: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_22 - PIXEL11_12 - break; - } - case 215: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 246: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 254: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 253: - { - PIXEL00_12 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 251: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 239: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - PIXEL11_11 - break; - } - case 127: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 191: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_11 - PIXEL11_12 - break; - } - case 223: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 247: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 255: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - } - pIn += INPUT_IMAGE_PIXEL_SIZE_IN_BYTES; - pOut+=8; - } - pOut+=BpL + (BpL - Xres * 8); - } -} - -void InitLUTs(void) -{ - int i, j, k, r, g, b, Y, u, v; - - for (i=0; i<65536; i++) - LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3); - - for (i=0; i<32; i++) - for (j=0; j<64; j++) - for (k=0; k<32; k++) - { - r = i << 3; - g = j << 2; - b = k << 3; - Y = (r + g + b) >> 2; - u = 128 + ((r - b) >> 2); - v = 128 + ((-r + 2*g -b)>>3); - RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v; - } -} - - - -//// **** HQ3X BELOW **** ///// - - -#define PIXEL00_1M Interp1(pOut, c[5], c[1]); -#define PIXEL00_1U Interp1(pOut, c[5], c[2]); -#define PIXEL00_1L Interp1(pOut, c[5], c[4]); -#define PIXEL00_2 Interp2(pOut, c[5], c[4], c[2]); -#define PIXEL00_4 Interp4(pOut, c[5], c[4], c[2]); -#define PIXEL00_5 Interp5(pOut, c[4], c[2]); -#define PIXEL00_C *((int*)(pOut)) = c[5]; - -#define PIXEL01_1 Interp1(pOut+4, c[5], c[2]); -#define PIXEL01_3 Interp3(pOut+4, c[5], c[2]); -#define PIXEL01_6 Interp1(pOut+4, c[2], c[5]); -#define PIXEL01_C *((int*)(pOut+4)) = c[5]; - -#define PIXEL02_1M Interp1(pOut+8, c[5], c[3]); -#define PIXEL02_1U Interp1(pOut+8, c[5], c[2]); -#define PIXEL02_1R Interp1(pOut+8, c[5], c[6]); -#define PIXEL02_2 Interp2(pOut+8, c[5], c[2], c[6]); -#define PIXEL02_4 Interp4(pOut+8, c[5], c[2], c[6]); -#define PIXEL02_5 Interp5(pOut+8, c[2], c[6]); -#define PIXEL02_C *((int*)(pOut+8)) = c[5]; - -#define PIXEL10_1 Interp1(pOut+BpL, c[5], c[4]); -#define PIXEL10_3 Interp3(pOut+BpL, c[5], c[4]); -#define PIXEL10_6 Interp1(pOut+BpL, c[4], c[5]); -#define PIXEL10_C *((int*)(pOut+BpL)) = c[5]; - -#define PIXEL11 *((int*)(pOut+BpL+4)) = c[5]; - -#define PIXEL12_1 Interp1(pOut+BpL+8, c[5], c[6]); -#define PIXEL12_3 Interp3(pOut+BpL+8, c[5], c[6]); -#define PIXEL12_6 Interp1(pOut+BpL+8, c[6], c[5]); -#define PIXEL12_C *((int*)(pOut+BpL+8)) = c[5]; - -#define PIXEL20_1M Interp1(pOut+BpL+BpL, c[5], c[7]); -#define PIXEL20_1D Interp1(pOut+BpL+BpL, c[5], c[8]); -#define PIXEL20_1L Interp1(pOut+BpL+BpL, c[5], c[4]); -#define PIXEL20_2 Interp2(pOut+BpL+BpL, c[5], c[8], c[4]); -#define PIXEL20_4 Interp4(pOut+BpL+BpL, c[5], c[8], c[4]); -#define PIXEL20_5 Interp5(pOut+BpL+BpL, c[8], c[4]); -#define PIXEL20_C *((int*)(pOut+BpL+BpL)) = c[5]; - -#define PIXEL21_1 Interp1(pOut+BpL+BpL+4, c[5], c[8]); -#define PIXEL21_3 Interp3(pOut+BpL+BpL+4, c[5], c[8]); -#define PIXEL21_6 Interp1(pOut+BpL+BpL+4, c[8], c[5]); -#define PIXEL21_C *((int*)(pOut+BpL+BpL+4)) = c[5]; - -#define PIXEL22_1M Interp1(pOut+BpL+BpL+8, c[5], c[9]); -#define PIXEL22_1D Interp1(pOut+BpL+BpL+8, c[5], c[8]); -#define PIXEL22_1R Interp1(pOut+BpL+BpL+8, c[5], c[6]); -#define PIXEL22_2 Interp2(pOut+BpL+BpL+8, c[5], c[6], c[8]); -#define PIXEL22_4 Interp4(pOut+BpL+BpL+8, c[5], c[6], c[8]); -#define PIXEL22_5 Interp5(pOut+BpL+BpL+8, c[6], c[8]); -#define PIXEL22_C *((int*)(pOut+BpL+BpL+8)) = c[5]; - - - -void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ) -{ - int i, j, k; - int prevline, nextline; - int w[10]; - int c[10]; - - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ - - for (j=0; j0) prevline = -Xres*4; else prevline = 0; - if (j0) - { - w[1] = *((INPUT_IMAGE_PIXEL_SIZE*)(pIn + prevline - INPUT_IMAGE_PIXEL_SIZE_IN_BYTES)); - w[4] = *((INPUT_IMAGE_PIXEL_SIZE*)(pIn - INPUT_IMAGE_PIXEL_SIZE_IN_BYTES)); - w[7] = *((INPUT_IMAGE_PIXEL_SIZE*)(pIn + nextline - INPUT_IMAGE_PIXEL_SIZE_IN_BYTES)); - } - else - { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } - - if (i> 16) & 0x00ff) / 8) << 11) + - ((((w[k] >> 8) & 0x00ff) / 4) << 5) + - ((w[k] & 0x00ff) / 8)) & 0x000ffff; - } - - int pattern = 0; - int flag = 1; - - YUV1 = RGBtoYUV[w[5]]; - - for (k=1; k<=9; k++) - { - if (k==5) continue; - - if ( w[k] != w[5] ) - { - YUV2 = RGBtoYUV[w[k]]; - if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || - ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || - ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) - pattern |= flag; - } - flag <<= 1; - } - - for (k=1; k<=9; k++) - c[k] = LUT16to32[w[k]]; - - switch (pattern) - { - case 0: - case 1: - case 4: - case 32: - case 128: - case 5: - case 132: - case 160: - case 33: - case 129: - case 36: - case 133: - case 164: - case 161: - case 37: - case 165: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - } - case 2: - case 34: - case 130: - case 162: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - } - case 16: - case 17: - case 48: - case 49: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - } - case 64: - case 65: - case 68: - case 69: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 8: - case 12: - case 136: - case 140: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - } - case 3: - case 35: - case 131: - case 163: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - } - case 6: - case 38: - case 134: - case 166: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - } - case 20: - case 21: - case 52: - case 53: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - } - case 144: - case 145: - case 176: - case 177: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - } - case 192: - case 193: - case 196: - case 197: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 96: - case 97: - case 100: - case 101: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 40: - case 44: - case 168: - case 172: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - } - case 9: - case 13: - case 137: - case 141: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - } - case 18: - case 50: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_1M - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - } - case 80: - case 81: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_1M - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 72: - case 76: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_1M - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 10: - case 138: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - } - case 66: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 24: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 7: - case 39: - case 135: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - } - case 148: - case 149: - case 180: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - } - case 224: - case 228: - case 225: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - } - case 41: - case 169: - case 45: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - } - case 22: - case 54: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - } - case 208: - case 209: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 104: - case 108: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 11: - case 139: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - } - case 19: - case 51: - { - if (Diff(w[2], w[6])) - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL12_C - } - else - { - PIXEL00_2 - PIXEL01_6 - PIXEL02_5 - PIXEL12_1 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - } - case 146: - case 178: - { - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_1M - PIXEL12_C - PIXEL22_1D - } - else - { - PIXEL01_1 - PIXEL02_5 - PIXEL12_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - break; - } - case 84: - case 85: - { - if (Diff(w[6], w[8])) - { - PIXEL02_1U - PIXEL12_C - PIXEL21_C - PIXEL22_1M - } - else - { - PIXEL02_2 - PIXEL12_6 - PIXEL21_1 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL10_1 - PIXEL11 - PIXEL20_1M - break; - } - case 112: - case 113: - { - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - } - else - { - PIXEL12_1 - PIXEL20_2 - PIXEL21_6 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - break; - } - case 200: - case 204: - { - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - } - else - { - PIXEL10_1 - PIXEL20_5 - PIXEL21_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - break; - } - case 73: - case 77: - { - if (Diff(w[8], w[4])) - { - PIXEL00_1U - PIXEL10_C - PIXEL20_1M - PIXEL21_C - } - else - { - PIXEL00_2 - PIXEL10_6 - PIXEL20_5 - PIXEL21_1 - } - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - PIXEL22_1M - break; - } - case 42: - case 170: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - PIXEL01_C - PIXEL10_C - PIXEL20_1D - } - else - { - PIXEL00_5 - PIXEL01_1 - PIXEL10_6 - PIXEL20_2 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL21_1 - PIXEL22_2 - break; - } - case 14: - case 142: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_C - } - else - { - PIXEL00_5 - PIXEL01_6 - PIXEL02_2 - PIXEL10_1 - } - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - } - case 67: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 70: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 28: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 152: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 194: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 98: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 56: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 25: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 26: - case 31: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL10_3 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 82: - case 214: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - } - else - { - PIXEL01_3 - PIXEL02_4 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 88: - case 248: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - } - else - { - PIXEL10_3 - PIXEL20_4 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL22_4 - } - break; - } - case 74: - case 107: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - } - else - { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 27: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 86: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 216: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 106: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 30: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 210: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 120: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 75: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 29: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - } - case 198: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 184: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - } - case 99: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 57: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 71: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 156: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 226: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - } - case 60: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 195: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 102: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 153: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 58: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 83: - { - PIXEL00_1L - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 92: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 202: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - } - case 78: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1M - break; - } - case 154: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 114: - { - PIXEL00_1M - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 89: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 90: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 55: - case 23: - { - if (Diff(w[2], w[6])) - { - PIXEL00_1L - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL00_2 - PIXEL01_6 - PIXEL02_5 - PIXEL12_1 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - } - case 182: - case 150: - { - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - PIXEL22_1D - } - else - { - PIXEL01_1 - PIXEL02_5 - PIXEL12_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - break; - } - case 213: - case 212: - { - if (Diff(w[6], w[8])) - { - PIXEL02_1U - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL02_2 - PIXEL12_6 - PIXEL21_1 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL10_1 - PIXEL11 - PIXEL20_1M - break; - } - case 241: - case 240: - { - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL20_1L - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_1 - PIXEL20_2 - PIXEL21_6 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - break; - } - case 236: - case 232: - { - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - PIXEL22_1R - } - else - { - PIXEL10_1 - PIXEL20_5 - PIXEL21_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - break; - } - case 109: - case 105: - { - if (Diff(w[8], w[4])) - { - PIXEL00_1U - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL00_2 - PIXEL10_6 - PIXEL20_5 - PIXEL21_1 - } - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - PIXEL22_1M - break; - } - case 171: - case 43: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - PIXEL20_1D - } - else - { - PIXEL00_5 - PIXEL01_1 - PIXEL10_6 - PIXEL20_2 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL21_1 - PIXEL22_2 - break; - } - case 143: - case 15: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL02_1R - PIXEL10_C - } - else - { - PIXEL00_5 - PIXEL01_6 - PIXEL02_2 - PIXEL10_1 - } - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - } - case 124: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 203: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 62: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 211: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 118: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 217: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 110: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 155: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 188: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - } - case 185: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - } - case 61: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 157: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 103: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 227: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - } - case 230: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - } - case 199: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 220: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 158: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 234: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1M - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1R - break; - } - case 242: - { - PIXEL00_1M - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1L - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 59: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 121: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 87: - { - PIXEL00_1L - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1M - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 79: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1R - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1M - break; - } - case 122: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 94: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 218: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 91: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 229: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - } - case 167: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - } - case 173: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - } - case 181: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - } - case 186: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - } - case 115: - { - PIXEL00_1L - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 93: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 206: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - } - case 205: - case 201: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_1M - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - } - case 174: - case 46: - { - if (Diff(w[4], w[2])) - { - PIXEL00_1M - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - } - case 179: - case 147: - { - PIXEL00_1L - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_1M - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - } - case 117: - case 116: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_1M - } - else - { - PIXEL22_2 - } - break; - } - case 189: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - } - case 231: - { - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - } - case 126: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 219: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 125: - { - if (Diff(w[8], w[4])) - { - PIXEL00_1U - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL00_2 - PIXEL10_6 - PIXEL20_5 - PIXEL21_1 - } - PIXEL01_1 - PIXEL02_1U - PIXEL11 - PIXEL12_C - PIXEL22_1M - break; - } - case 221: - { - if (Diff(w[6], w[8])) - { - PIXEL02_1U - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL02_2 - PIXEL12_6 - PIXEL21_1 - PIXEL22_5 - } - PIXEL00_1U - PIXEL01_1 - PIXEL10_C - PIXEL11 - PIXEL20_1M - break; - } - case 207: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL02_1R - PIXEL10_C - } - else - { - PIXEL00_5 - PIXEL01_6 - PIXEL02_2 - PIXEL10_1 - } - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - } - case 238: - { - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - PIXEL22_1R - } - else - { - PIXEL10_1 - PIXEL20_5 - PIXEL21_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL11 - PIXEL12_1 - break; - } - case 190: - { - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - PIXEL22_1D - } - else - { - PIXEL01_1 - PIXEL02_5 - PIXEL12_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL10_C - PIXEL11 - PIXEL20_1D - PIXEL21_1 - break; - } - case 187: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - PIXEL20_1D - } - else - { - PIXEL00_5 - PIXEL01_1 - PIXEL10_6 - PIXEL20_2 - } - PIXEL02_1M - PIXEL11 - PIXEL12_C - PIXEL21_1 - PIXEL22_1D - break; - } - case 243: - { - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL20_1L - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_1 - PIXEL20_2 - PIXEL21_6 - PIXEL22_5 - } - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - break; - } - case 119: - { - if (Diff(w[2], w[6])) - { - PIXEL00_1L - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL00_2 - PIXEL01_6 - PIXEL02_5 - PIXEL12_1 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - } - case 237: - case 233: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_C - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - } - case 175: - case 47: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - } - case 183: - case 151: - { - PIXEL00_1L - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - } - case 245: - case 244: - { - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_C - } - else - { - PIXEL22_2 - } - break; - } - case 250: - { - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - } - else - { - PIXEL10_3 - PIXEL20_4 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL22_4 - } - break; - } - case 123: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - } - else - { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 95: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL10_3 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - } - case 222: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - } - else - { - PIXEL01_3 - PIXEL02_4 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 252: - { - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - } - else - { - PIXEL10_3 - PIXEL20_4 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_C - } - else - { - PIXEL22_2 - } - break; - } - case 249: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL20_C - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL22_4 - } - break; - } - case 235: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - } - else - { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_C - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - } - case 111: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 63: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - } - case 159: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL10_3 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - } - else - { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - } - case 215: - { - PIXEL00_1L - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 246: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - } - else - { - PIXEL01_3 - PIXEL02_4 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_C - } - else - { - PIXEL22_2 - } - break; - } - case 254: - { - PIXEL00_1M - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - } - else - { - PIXEL01_3 - PIXEL02_4 - } - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - } - else - { - PIXEL10_3 - PIXEL20_4 - } - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL21_3 - PIXEL22_2 - } - break; - } - case 253: - { - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_C - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_C - } - else - { - PIXEL22_2 - } - break; - } - case 251: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - } - else - { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL10_3 - PIXEL20_2 - PIXEL21_3 - } - if (Diff(w[6], w[8])) - { - PIXEL12_C - PIXEL22_C - } - else - { - PIXEL12_3 - PIXEL22_4 - } - break; - } - case 239: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - } - else - { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (Diff(w[8], w[4])) - { - PIXEL20_C - } - else - { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - } - case 127: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } - else - { - PIXEL00_2 - PIXEL01_3 - PIXEL10_3 - } - if (Diff(w[2], w[6])) - { - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - if (Diff(w[8], w[4])) - { - PIXEL20_C - PIXEL21_C - } - else - { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - } - case 191: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - } - case 223: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - PIXEL10_C - } - else - { - PIXEL00_4 - PIXEL10_3 - } - if (Diff(w[2], w[6])) - { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } - else - { - PIXEL01_3 - PIXEL02_2 - PIXEL12_3 - } - PIXEL11 - PIXEL20_1M - if (Diff(w[6], w[8])) - { - PIXEL21_C - PIXEL22_C - } - else - { - PIXEL21_3 - PIXEL22_4 - } - break; - } - case 247: - { - PIXEL00_1L - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - } - else - { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_C - } - else - { - PIXEL22_2 - } - break; - } - case 255: - { - if (Diff(w[4], w[2])) - { - PIXEL00_C - } - else - { - PIXEL00_2 - } - PIXEL01_C - if (Diff(w[2], w[6])) - { - PIXEL02_C - } - else - { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - if (Diff(w[8], w[4])) - { - PIXEL20_C - } - else - { - PIXEL20_2 - } - PIXEL21_C - if (Diff(w[6], w[8])) - { - PIXEL22_C - } - else - { - PIXEL22_2 - } - break; - } - } - pIn += INPUT_IMAGE_PIXEL_SIZE_IN_BYTES; - pOut+=12; - } - pOut+=BpL + (BpL - Xres * 12); - pOut+=BpL; - } -} diff --git a/Engine/libsrc/hq2x/hq2x3x.h b/Engine/libsrc/hq2x/hq2x3x.h deleted file mode 100644 index 3560d168910..00000000000 --- a/Engine/libsrc/hq2x/hq2x3x.h +++ /dev/null @@ -1,30 +0,0 @@ -//============================================================================= -// -// Adventure Game Studio (AGS) -// -// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others -// The full list of copyright holders can be found in the Copyright.txt -// file, which is part of this source code distribution. -// -// The AGS source code is provided under the Artistic License 2.0. -// A copy of this license can be found in the file License.txt and at -// http://www.opensource.org/licenses/artistic-license-2.0.php -// -//============================================================================= - -#ifndef __AC_HQ2X3X_H -#define __AC_HQ2X3X_H - -#include "core/platform.h" - -#if AGS_PLATFORM_OS_ANDROID -void InitLUTs(){} -void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ){} -void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ){} -#else -void InitLUTs(); -void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ); -void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ); -#endif - -#endif // __AC_HQ2X3X_H \ No newline at end of file diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index fd7f90c7e9c..03cfd3922f1 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -417,7 +417,6 @@ - diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index e766f920c72..a8398c609e3 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -136,9 +136,6 @@ {f9e0871b-6f2f-4d4d-944a-205740a1d5b5} - - {0d737144-e555-4eda-bc62-cc15d7e48657} - {84da057d-6fa3-435e-a3ba-203e836da7c1} @@ -783,9 +780,6 @@ Library Sources\apeg - - Library Sources\Hq2x - Library Sources\libcda @@ -840,12 +834,6 @@ Source Files\media\audio - - Source Files - - - Source Files - Source Files\main @@ -858,6 +846,12 @@ Source Files\gfx + + Source Files\media\audio + + + Source Files\media\audio + From baa084d7dfd3ccc270dd2dd8634f4af8e9654c22 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 19 Nov 2020 05:24:43 +0300 Subject: [PATCH 37/41] Adjust backend init/deinit order and error messages --- Engine/main/engine.cpp | 28 ++++++----- Engine/main/engine_setup.cpp | 6 --- Engine/main/main.cpp | 2 +- Engine/main/quit.cpp | 2 +- Engine/platform/android/acpland.cpp | 10 +--- Engine/platform/base/agsplatformdriver.cpp | 5 +- Engine/platform/base/agsplatformdriver.h | 10 ++-- Engine/platform/ios/acplios.cpp | 11 ----- Engine/platform/linux/acpllnx.cpp | 16 ++----- Engine/platform/osx/acplmac.cpp | 10 ---- Engine/platform/windows/acplwin.cpp | 56 +++------------------- 11 files changed, 35 insertions(+), 121 deletions(-) diff --git a/Engine/main/engine.cpp b/Engine/main/engine.cpp index 141354927c8..3b8d4f7b333 100644 --- a/Engine/main/engine.cpp +++ b/Engine/main/engine.cpp @@ -105,24 +105,30 @@ ResourcePaths ResPaths; t_engine_pre_init_callback engine_pre_init_callback = nullptr; -bool engine_init_allegro() +bool engine_init_backend() { - Debug::Printf(kDbgMsg_Info, "Initializing allegro"); - our_eip = -199; - // Initialize allegro + // Initialize SDL + Debug::Printf(kDbgMsg_Info, "Initializing backend libs"); + if (sys_main_init()) + { + const char *err = SDL_GetError(); + const char *user_hint = platform->GetBackendFailUserHint(); + platform->DisplayAlert("Unable to initialize SDL library.\n%s\n\n%s", + (err && err[0]) ? err : "SDL provided no further information on the problem.", + user_hint); + return false; + } + + // Initialize stripped allegro library set_uformat(U_ASCII); if (install_allegro(SYSTEM_NONE, &errno, atexit)) { - const char *al_err = SDL_GetError(); - const char *user_hint = platform->GetAllegroFailUserHint(); - platform->DisplayAlert("Unable to initialize Allegro system driver.\n%s\n\n%s", - al_err[0] ? al_err : "Allegro library provided no further information on the problem.", - user_hint); + platform->DisplayAlert("Internal error: unable to initialize stripped Allegro 4 library."); return false; } - sys_main_init(); + platform->PostBackendInit(); return true; } @@ -1230,7 +1236,7 @@ int initialize_engine(const ConfigTree &startup_opts) //----------------------------------------------------- // Install backend - if (!engine_init_allegro()) + if (!engine_init_backend()) return EXIT_ERROR; //----------------------------------------------------- diff --git a/Engine/main/engine_setup.cpp b/Engine/main/engine_setup.cpp index c44c4b730f7..bb1755ccd0e 100644 --- a/Engine/main/engine_setup.cpp +++ b/Engine/main/engine_setup.cpp @@ -331,12 +331,6 @@ void engine_post_gfxmode_setup(const Size &init_desktop) if (has_driver_changed) engine_post_gfxmode_draw_setup(dm); engine_post_gfxmode_mouse_setup(dm, init_desktop); - - // TODO: the only reason this call was put here is that it requires - // "windowed" flag to be specified. Find out whether this function - // has anything to do with graphics mode at all. It is quite possible - // that we may split it into two functions, or remove parameter. - platform->PostAllegroInit(scsystem.windowed != 0); video_on_gfxmode_changed(); invalidate_screen(); diff --git a/Engine/main/main.cpp b/Engine/main/main.cpp index 7a780f8b39b..fc4f918ed2a 100644 --- a/Engine/main/main.cpp +++ b/Engine/main/main.cpp @@ -466,7 +466,7 @@ int ags_entry_point(int argc, char *argv[]) { // TODO: refactor engine shutdown routine (must shutdown and delete everything started and created) sys_main_shutdown(); allegro_exit(); - platform->PostAllegroExit(); + platform->PostBackendExit(); return result; } #ifdef USE_CUSTOM_EXCEPTION_HANDLER diff --git a/Engine/main/quit.cpp b/Engine/main/quit.cpp index 98a9647a0fe..c643de86b20 100644 --- a/Engine/main/quit.cpp +++ b/Engine/main/quit.cpp @@ -289,7 +289,7 @@ void quit(const char *quitmsg) sys_main_shutdown(); allegro_exit(); - platform->PostAllegroExit(); + platform->PostBackendExit(); our_eip = 9903; diff --git a/Engine/platform/android/acpland.cpp b/Engine/platform/android/acpland.cpp index 04f5ca7555d..56e960bb237 100644 --- a/Engine/platform/android/acpland.cpp +++ b/Engine/platform/android/acpland.cpp @@ -47,11 +47,9 @@ struct AGSAndroid : AGSPlatformDriver { virtual void DisplayAlert(const char*, ...); virtual const char *GetAppOutputDirectory(); virtual unsigned long GetDiskFreeSpaceMB(); - virtual const char* GetNoMouseErrorString(); - virtual bool IsBackendResponsibleForMouseScaling() { return true; } virtual eScriptSystemOSID GetSystemOSID(); virtual int InitializeCDPlayer(); - virtual void PostAllegroExit(); + virtual void PostBackendExit(); virtual void ShutdownCDPlayer(); virtual void WriteStdOut(const char *fmt, ...); virtual void WriteStdErr(const char *fmt, ...); @@ -691,10 +689,6 @@ unsigned long AGSAndroid::GetDiskFreeSpaceMB() { return 100; } -const char* AGSAndroid::GetNoMouseErrorString() { - return "This game requires a mouse. You need to configure and setup your mouse to play this game.\n"; -} - eScriptSystemOSID AGSAndroid::GetSystemOSID() { return eOS_Android; } @@ -703,7 +697,7 @@ int AGSAndroid::InitializeCDPlayer() { return 1;//cd_player_init(); } -void AGSAndroid::PostAllegroExit() { +void AGSAndroid::PostBackendExit() { java_environment->DeleteGlobalRef(java_class); } diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index a33afe15fd7..59c785af8c9 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -43,16 +43,15 @@ AGSPlatformDriver *platform = nullptr; // ******** DEFAULT IMPLEMENTATIONS ******* void AGSPlatformDriver::AboutToQuitGame() { } -void AGSPlatformDriver::PostAllegroInit(bool windowed) { } void AGSPlatformDriver::AttachToParentConsole() { } void AGSPlatformDriver::PauseApplication() { } void AGSPlatformDriver::ResumeApplication() { } void AGSPlatformDriver::RegisterGameWithGameExplorer() { } void AGSPlatformDriver::UnRegisterGameWithGameExplorer() { } -const char* AGSPlatformDriver::GetAllegroFailUserHint() +const char* AGSPlatformDriver::GetBackendFailUserHint() { - return "Make sure you have latest version of Allegro 4 libraries installed, and your system is running in graphical mode."; + return "Make sure you have latest version of SDL2 libraries installed, and your system is running in graphical mode."; } const char *AGSPlatformDriver::GetDiskWriteAccessTroubleshootingText() diff --git a/Engine/platform/base/agsplatformdriver.h b/Engine/platform/base/agsplatformdriver.h index 0aa4eb2985b..b9ac794a27b 100644 --- a/Engine/platform/base/agsplatformdriver.h +++ b/Engine/platform/base/agsplatformdriver.h @@ -74,15 +74,11 @@ struct AGSPlatformDriver virtual const char *GetDiskWriteAccessTroubleshootingText(); virtual const char *GetGraphicsTroubleshootingText() { return ""; } virtual unsigned long GetDiskFreeSpaceMB() = 0; - virtual const char* GetNoMouseErrorString() = 0; - // Tells whether this platform's backend library deals with mouse cursor - // virtual->real coordinate transformation itself (otherwise AGS engine should do it) - virtual bool IsBackendResponsibleForMouseScaling() { return false; } - virtual const char* GetAllegroFailUserHint(); + virtual const char* GetBackendFailUserHint(); virtual eScriptSystemOSID GetSystemOSID() = 0; virtual void GetSystemTime(ScriptDateTime*); - virtual void PostAllegroInit(bool windowed); - virtual void PostAllegroExit() = 0; + virtual void PostBackendInit() { }; + virtual void PostBackendExit() { }; virtual SetupReturnValue RunSetup(const Common::ConfigTree &cfg_in, Common::ConfigTree &cfg_out); // Formats message and writes to standard platform's output; // Always adds trailing '\n' after formatted string diff --git a/Engine/platform/ios/acplios.cpp b/Engine/platform/ios/acplios.cpp index 96bbe432509..618e3a69b2c 100644 --- a/Engine/platform/ios/acplios.cpp +++ b/Engine/platform/ios/acplios.cpp @@ -119,11 +119,8 @@ struct AGSIOS : AGSPlatformDriver { virtual void DisplayAlert(const char*, ...); virtual const char *GetAppOutputDirectory(); virtual unsigned long GetDiskFreeSpaceMB(); - virtual const char* GetNoMouseErrorString(); - virtual bool IsBackendResponsibleForMouseScaling() { return true; } virtual eScriptSystemOSID GetSystemOSID(); virtual int InitializeCDPlayer(); - virtual void PostAllegroExit(); virtual void SetGameWindowIcon(); virtual void ShutdownCDPlayer(); }; @@ -604,10 +601,6 @@ unsigned long AGSIOS::GetDiskFreeSpaceMB() { return 100; } -const char* AGSIOS::GetNoMouseErrorString() { - return "This game requires a mouse. You need to configure and setup your mouse to play this game.\n"; -} - eScriptSystemOSID AGSIOS::GetSystemOSID() { return eOS_iOS; } @@ -616,10 +609,6 @@ int AGSIOS::InitializeCDPlayer() { return 0;//cd_player_init(); } -void AGSIOS::PostAllegroExit() { - // do nothing -} - void AGSIOS::SetGameWindowIcon() { // do nothing } diff --git a/Engine/platform/linux/acpllnx.cpp b/Engine/platform/linux/acpllnx.cpp index 623cdefbea4..06013ca10ec 100644 --- a/Engine/platform/linux/acpllnx.cpp +++ b/Engine/platform/linux/acpllnx.cpp @@ -47,11 +47,9 @@ struct AGSLinux : AGSPlatformDriver { const char *GetUserGlobalConfigDirectory() override; const char *GetAppOutputDirectory() override; unsigned long GetDiskFreeSpaceMB() override; - const char* GetNoMouseErrorString() override; - const char* GetAllegroFailUserHint() override; + const char* GetBackendFailUserHint() override; eScriptSystemOSID GetSystemOSID() override; int InitializeCDPlayer() override; - void PostAllegroExit() override; void ShutdownCDPlayer() override; }; @@ -141,13 +139,9 @@ unsigned long AGSLinux::GetDiskFreeSpaceMB() { return 100; } -const char* AGSLinux::GetNoMouseErrorString() { - return "This game requires a mouse. You need to configure and setup your mouse to play this game.\n"; -} - -const char* AGSLinux::GetAllegroFailUserHint() +const char* AGSLinux::GetBackendFailUserHint() { - return "Make sure you have latest version of Allegro 4 libraries installed, and X server is running."; + return "Make sure you have latest version of SDL2 libraries installed, and X server is running."; } eScriptSystemOSID AGSLinux::GetSystemOSID() { @@ -158,10 +152,6 @@ int AGSLinux::InitializeCDPlayer() { return cd_player_init(); } -void AGSLinux::PostAllegroExit() { - // do nothing -} - void AGSLinux::ShutdownCDPlayer() { cd_exit(); } diff --git a/Engine/platform/osx/acplmac.cpp b/Engine/platform/osx/acplmac.cpp index 246c9279eb7..cde12db0d0c 100644 --- a/Engine/platform/osx/acplmac.cpp +++ b/Engine/platform/osx/acplmac.cpp @@ -44,10 +44,8 @@ struct AGSMac : AGSPlatformDriver { virtual int CDPlayerCommand(int cmdd, int datt) override; virtual void DisplayAlert(const char*, ...) override; virtual unsigned long GetDiskFreeSpaceMB() override; - virtual const char* GetNoMouseErrorString() override; virtual eScriptSystemOSID GetSystemOSID() override; virtual int InitializeCDPlayer() override; - virtual void PostAllegroExit() override; virtual void ShutdownCDPlayer() override; virtual const char *GetUserSavedgamesDirectory() override; @@ -88,10 +86,6 @@ unsigned long AGSMac::GetDiskFreeSpaceMB() { return 100; } -const char* AGSMac::GetNoMouseErrorString() { - return "This game requires a mouse. You need to configure and setup your mouse to play this game.\n"; -} - eScriptSystemOSID AGSMac::GetSystemOSID() { // override performed if `override.os` is set in config. return eOS_Mac; @@ -102,10 +96,6 @@ int AGSMac::InitializeCDPlayer() { return 0; } -void AGSMac::PostAllegroExit() { - // do nothing -} - void AGSMac::ShutdownCDPlayer() { //cd_exit(); } diff --git a/Engine/platform/windows/acplwin.cpp b/Engine/platform/windows/acplwin.cpp index 5eec6713aee..3ddec2991cf 100644 --- a/Engine/platform/windows/acplwin.cpp +++ b/Engine/platform/windows/acplwin.cpp @@ -85,12 +85,11 @@ struct AGSWin32 : AGSPlatformDriver { virtual const char *GetIllegalFileChars(); virtual const char *GetGraphicsTroubleshootingText(); virtual unsigned long GetDiskFreeSpaceMB(); - virtual const char* GetNoMouseErrorString(); - virtual const char* GetAllegroFailUserHint(); + virtual const char* GetBackendFailUserHint(); virtual eScriptSystemOSID GetSystemOSID(); virtual int InitializeCDPlayer(); - virtual void PostAllegroInit(bool windowed); - virtual void PostAllegroExit(); + virtual void PostBackendInit(); + virtual void PostBackendExit(); virtual SetupReturnValue RunSetup(const ConfigTree &cfg_in, ConfigTree &cfg_out); virtual void ShutdownCDPlayer(); virtual void WriteStdOut(const char *fmt, ...); @@ -129,43 +128,6 @@ AGSWin32::~AGSWin32() { } } -void check_parental_controls() { - /* this doesn't work, it always just returns access depedning - on whether unrated games are allowed because of digital signature - BOOL bHasAccess = FALSE; - IGameExplorer* pFwGameExplorer = NULL; - - CoInitialize(NULL); - // Create an instance of the Game Explorer Interface - HRESULT hr = CoCreateInstance( __uuidof(GameExplorer), NULL, CLSCTX_INPROC_SERVER, __uuidof(IGameExplorer), (void**)&pFwGameExplorer); - if( FAILED(hr) || pFwGameExplorer == NULL ) { - // not Vista, do nothing - } - else { - char theexename[MAX_PATH] = "e:\\code\\ags\\acwin\\release\\acwin.exe"; - WCHAR wstrBinPath[MAX_PATH] = {0}; - MultiByteToWideChar(CP_ACP, 0, theexename, MAX_PATH, wstrBinPath, MAX_PATH); - BSTR bstrGDFBinPath = SysAllocString(wstrBinPath); - - hr = pFwGameExplorer->VerifyAccess( bstrGDFBinPath, &bHasAccess ); - SysFreeString(bstrGDFBinPath); - - if( FAILED(hr) || !bHasAccess ) { - char buff[300]; - sprintf(buff, "Parental controls block: %X b: %d", hr, bHasAccess); - quit(buff); - } - else { - platform->DisplayAlert("Parental controls: Access granted."); - } - - } - - if( pFwGameExplorer ) pFwGameExplorer->Release(); - CoUninitialize(); - */ -} - void AGSWin32::create_shortcut(const char *pathToEXE, const char *workingFolder, const char *arguments, const char *shortcutPath) { IShellLink* pShellLink = NULL; @@ -485,10 +447,8 @@ void AGSWin32::UnRegisterGameWithGameExplorer() } } -void AGSWin32::PostAllegroInit(bool windowed) +void AGSWin32::PostBackendInit() { - check_parental_controls(); - // Set the Windows timer resolution to 1 ms so that calls to // Sleep() don't take more time than specified MMRESULT result = timeBeginPeriod(win32TimerPeriod); @@ -764,11 +724,7 @@ unsigned long AGSWin32::GetDiskFreeSpaceMB() { return returnMb; } -const char* AGSWin32::GetNoMouseErrorString() { - return "No mouse was detected on your system, or your mouse is not configured to work with DirectInput. You must have a mouse to play this game."; -} - -const char* AGSWin32::GetAllegroFailUserHint() +const char* AGSWin32::GetBackendFailUserHint() { return "Make sure you have DirectX 5 or above installed."; } @@ -789,7 +745,7 @@ void AGSWin32::AboutToQuitGame() { } -void AGSWin32::PostAllegroExit() { +void AGSWin32::PostBackendExit() { // Release the timer setting timeEndPeriod(win32TimerPeriod); } From 485730c7fdcb3537699a78381dd84aa3f4766cf6 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 20 Nov 2020 11:41:07 +0300 Subject: [PATCH 38/41] Linux: amend allegro's alucfg.h with defines from removed alunixac.h --- .../allegro/include/allegro/platform/alucfg.h | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/libsrc/allegro/include/allegro/platform/alucfg.h b/libsrc/allegro/include/allegro/platform/alucfg.h index 32870d8bcc3..3891ad9fdaa 100644 --- a/libsrc/allegro/include/allegro/platform/alucfg.h +++ b/libsrc/allegro/include/allegro/platform/alucfg.h @@ -21,23 +21,42 @@ /* Describe this platform. */ #define ALLEGRO_PLATFORM_STR "Unix" -#define ALLEGRO_CONSOLE_OK -#define ALLEGRO_VRAM_SINGLE_SURFACE -/* These defines will be provided by configure script. */ -#undef ALLEGRO_COLOR8 -#undef ALLEGRO_COLOR16 -#undef ALLEGRO_COLOR24 -#undef ALLEGRO_COLOR32 -/* Include configuration generated by configure script. */ -#include "allegro/platform/alunixac.h" -/* Enable multithreaded library */ -#ifdef ALLEGRO_HAVE_LIBPTHREAD -#define ALLEGRO_MULTITHREADED +/* Define to 1 if you have the corresponding header file. */ +#define ALLEGRO_HAVE_DIRENT_H +#define ALLEGRO_HAVE_INTTYPES_H +#define ALLEGRO_HAVE_STDINT_H + +#define ALLEGRO_HAVE_SYS_STAT_H +#define ALLEGRO_HAVE_SYS_TIME_H + +/* Define to 1 if the corresponding functions are available. */ +#define ALLEGRO_HAVE_MEMCMP +/* #undef ALLEGRO_HAVE_STRICMP */ +/* #undef ALLEGRO_HAVE_STRLWR */ +/* #undef ALLEGRO_HAVE_STRUPR */ + +/*---------------------------------------------------------------------------*/ + +/* Define if target machine is little endian or big endian. */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define ALLEGRO_LITTLE_ENDIAN +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define ALLEGRO_BIG_ENDIAN +#else + #error platform not supported #endif +/* Define for Unix platforms, to use C convention for bank switching. */ +#define ALLEGRO_NO_ASM + +/* Define if constructor attribute is supported. */ +#define ALLEGRO_USE_CONSTRUCTOR + + + /* Provide implementations of missing functions. */ #ifndef ALLEGRO_HAVE_STRICMP #define ALLEGRO_NO_STRICMP From 5efacc84ed04cadd55ab43ddb048f8b9e99c307e Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Mon, 16 Nov 2020 20:07:19 +0300 Subject: [PATCH 39/41] Linux: fixed compilation with new backend libraries --- Engine/Makefile | 8 +--- Engine/Makefile-defs.allegro | 55 ++++++++++++++++++++++ Engine/Makefile-defs.linux | 16 +++---- Engine/Makefile-objs | 46 +----------------- Engine/ac/sys_events.cpp | 2 +- Engine/debug/filebasedagsdebugger.cpp | 3 +- Engine/device/mousew32.cpp | 5 ++ Engine/gfx/ali3dogl.cpp | 2 +- Engine/gfx/ali3dsw.cpp | 2 +- Engine/media/audio/clip_openal.cpp | 1 + Engine/platform/base/agsplatformdriver.cpp | 2 +- Engine/platform/linux/acpllnx.cpp | 3 +- Engine/platform/windows/gfx/ali3dd3d.cpp | 2 +- 13 files changed, 78 insertions(+), 69 deletions(-) create mode 100644 Engine/Makefile-defs.allegro diff --git a/Engine/Makefile b/Engine/Makefile index 20e89fb12f9..c54096035c4 100644 --- a/Engine/Makefile +++ b/Engine/Makefile @@ -14,16 +14,12 @@ else include Makefile-defs.linux endif -ifneq ($(USE_MIDI_PATCH), 1) -AL_MIDI_PATCH := -endif - -OBJS := $(ALMP3) $(ALOGG) $(APEG) $(AASTR) $(HQ2X3X) $(AL_MIDI_PATCH) $(CDA) $(ALDUMB) $(GLAD) $(PLUGINS) $(BASE) $(BASE_PLATFORM) +OBJS := $(APEG) $(AASTR) $(MOJOAL) $(CDA) $(GLAD) $(PLUGINS) $(BASE) $(BASE_PLATFORM) OBJS := $(OBJS:.mm=.o) OBJS := $(OBJS:.cpp=.o) OBJS := $(OBJS:.c=.o) -OBJS_COMMON := $(COMMON) $(ALFONT) $(FREETYPE) +OBJS_COMMON := $(COMMON) $(ALLEGRO) $(ALFONT) $(FREETYPE) OBJS_COMMON := $(OBJS_COMMON:.mm=.o) OBJS_COMMON := $(OBJS_COMMON:.cpp=.o) OBJS_COMMON := $(OBJS_COMMON:.c=.o) diff --git a/Engine/Makefile-defs.allegro b/Engine/Makefile-defs.allegro new file mode 100644 index 00000000000..45124673d47 --- /dev/null +++ b/Engine/Makefile-defs.allegro @@ -0,0 +1,55 @@ +ALLEGRO_SRCS := \ + src/allegro.c \ + src/blit.c \ + src/bmp.c \ + src/colblend.c \ + src/color.c \ + src/dataregi.c \ + src/dither.c \ + src/file.c \ + src/fli.c \ + src/flood.c \ + src/gfx.c \ + src/graphics.c \ + src/inline.c \ + src/libc.c \ + src/math.c \ + src/pcx.c \ + src/polygon.c \ + src/quantize.c \ + src/readbmp.c \ + src/rotate.c \ + src/unicode.c \ + src/vtable.c \ + src/vtable8.c \ + src/vtable15.c \ + src/vtable16.c \ + src/vtable24.c \ + src/vtable32.c \ + src/c/cblit8.c \ + src/c/cblit16.c \ + src/c/cblit24.c \ + src/c/cblit32.c \ + src/c/cgfx8.c \ + src/c/cgfx15.c \ + src/c/cgfx16.c \ + src/c/cgfx24.c \ + src/c/cgfx32.c \ + src/c/cmisc.c \ + src/c/cspr8.c \ + src/c/cspr15.c \ + src/c/cspr16.c \ + src/c/cspr24.c \ + src/c/cspr32.c \ + src/c/cstretch.c \ + src/unix/ufile.c + +ALLEGRO_SRCDIR := ../libsrc/allegro +ALLEGRO := $(foreach file,$(ALLEGRO_SRCS),$(ALLEGRO_SRCDIR)/$(file)) +ALLEGRO_OBJS := $(ALLEGRO:.c=.o) +ALLEGRO_INC := $(ALLEGRO_SRCDIR)/include +$(ALLEGRO_SRCDIR)%.o: CFLAGS += -I $(ALLEGRO_INC) + +AL_CFLAGS := -I $(ALLEGRO_INC) +AL_LDFLAGS := + diff --git a/Engine/Makefile-defs.linux b/Engine/Makefile-defs.linux index 8f5cdbc7868..d8fa6bb838c 100644 --- a/Engine/Makefile-defs.linux +++ b/Engine/Makefile-defs.linux @@ -3,7 +3,7 @@ USE_MIDI_PATCH = 1 include Makefile-defs.freetype -INCDIR = ../Engine ../Common ../Common/libinclude ../Common/libsrc/alfont-2.0.9 ../Plugins ../Engine/libsrc/glad/include +INCDIR = ../Engine ../Common ../Common/libinclude ../Common/libsrc/alfont-2.0.9 ../Engine/libsrc/apeg-1.2.1/ ../libsrc/mojoAL ../Plugins ../Engine/libsrc/glad/include $(ALLEGRO_SRCDIR)/include LIBDIR = CFLAGS := -O2 -g \ @@ -13,7 +13,7 @@ CFLAGS := -O2 -g \ -Werror=write-strings -Werror=format -Werror=format-security -Werror=implicit-function-declaration \ -DNDEBUG \ -DALLEGRO_STATICLINK -DALLEGRO_NO_COMPATIBILITY -DALLEGRO_NO_FIX_ALIASES -DALLEGRO_NO_FIX_CLASS \ - -DLINUX_VERSION -DBUILTIN_PLUGINS -DHAVE_FSEEKO -DDISABLE_MPEG_AUDIO -DAGS_CASE_SENSITIVE_FILESYSTEM -DAGS_HAS_CD_AUDIO -DAGS_RUNTIME_PATCH_ALLEGRO \ + -DLINUX_VERSION -DBUILTIN_PLUGINS -DHAVE_FSEEKO -DDISABLE_MPEG_AUDIO -DAGS_CASE_SENSITIVE_FILESYSTEM -DAGS_HAS_CD_AUDIO \ -D_FILE_OFFSET_BITS=64 -DRTLD_NEXT \ $(FT_CFLAGS) $(CFLAGS) @@ -21,7 +21,6 @@ CXXFLAGS := -std=c++11 -Werror=delete-non-virtual-dtor $(CXXFLAGS) LIBS := -Wl,-Bdynamic LIBS += $(FT_LDFLAGS) -LIBS += $(shell pkg-config --libs allegro) LIBS += $(shell pkg-config --libs x11) LIBS += $(shell pkg-config --libs ogg) LIBS += $(shell pkg-config --libs theora) @@ -35,14 +34,11 @@ endif LIBS += $(shell pkg-config --libs vorbisfile) LIBS += -ldl -lpthread -lc -lm -lstdc++ -ifneq ($(USE_BUILT_IN_LIBSRC), 1) -ALDUMB := -LIBS += -Wl,--push-state,-Bstatic -laldmb -ldumb -Wl,--pop-state -endif +SDL2_CFLAGS = $(shell sdl2-config --cflags) +SDL2_LIBS = $(shell sdl2-config --libs) -ifeq ($(ALLEGRO_MAGIC_DRV), 1) - CFLAGS += -DALLEGRO_MAGIC_DRV -endif +CFLAGS += $(SDL2_CFLAGS) +LIBS += $(SDL2_LIBS) -lSDL2_sound ifdef BUILD_STR CFLAGS += -DBUILD_STR=\"$(BUILD_STR)\" diff --git a/Engine/Makefile-objs b/Engine/Makefile-objs index 3c4881477ca..be9d9a835b4 100644 --- a/Engine/Makefile-objs +++ b/Engine/Makefile-objs @@ -57,55 +57,13 @@ endif PLUGINS = ../Plugins/AGSflashlight/agsflashlight.cpp ../Plugins/agsblend/AGSBlend.cpp ../Plugins/ags_snowrain/ags_snowrain.cpp ../Plugins/ags_parallax/ags_parallax.cpp ../Plugins/agspalrender/ags_palrender.cpp ../Plugins/agspalrender/raycast.cpp -HQ2X3X = libsrc/hq2x/hq2x3x.cpp - ALFONT = ../Common/libsrc/alfont-2.0.9/alfont.c -ALMP3 = libsrc/almp3/almp3.c libsrc/almp3-2.0.5/decoder/common.c libsrc/almp3-2.0.5/decoder/dct64_i386.c libsrc/almp3-2.0.5/decoder/decode_i386.c libsrc/almp3-2.0.5/decoder/interface.c libsrc/almp3-2.0.5/decoder/layer2.c libsrc/almp3-2.0.5/decoder/layer3.c libsrc/almp3-2.0.5/decoder/tabinit.c - -ALOGG = libsrc/alogg/alogg.c +MOJOAL = ../libsrc/mojoAL/mojoal.c APEG = libsrc/apeg-1.2.1/adisplay.c libsrc/apeg-1.2.1/getbits.c libsrc/apeg-1.2.1/getblk.c libsrc/apeg-1.2.1/gethdr.c libsrc/apeg-1.2.1/getpic.c libsrc/apeg-1.2.1/idct.c libsrc/apeg-1.2.1/motion.c libsrc/apeg-1.2.1/mpeg1dec.c libsrc/apeg-1.2.1/ogg.c libsrc/apeg-1.2.1/recon.c libsrc/apeg-1.2.1/audio/apegcommon.c libsrc/apeg-1.2.1/audio/aaudio.c libsrc/apeg-1.2.1/audio/dct64.c libsrc/apeg-1.2.1/audio/decode_1to1.c libsrc/apeg-1.2.1/audio/decode_2to1.c libsrc/apeg-1.2.1/audio/decode_4to1.c libsrc/apeg-1.2.1/audio/layer1.c libsrc/apeg-1.2.1/audio/layer2.c libsrc/apeg-1.2.1/audio/layer3.c libsrc/apeg-1.2.1/audio/mpg123.c libsrc/apeg-1.2.1/audio/readers.c libsrc/apeg-1.2.1/audio/tabinit.c libsrc/apeg-1.2.1/audio/vbrhead.c AASTR = ../Common/libsrc/aastr-0.1.1/aarot.c ../Common/libsrc/aastr-0.1.1/aastr.c ../Common/libsrc/aastr-0.1.1/aautil.c -AL_MIDI_PATCH = libsrc/allegro-4.2.2-agspatch/midi.c +include Makefile-defs.allegro -ALDUMB = libsrc/dumb-0.9.2/allegro/alplay.c \ - libsrc/dumb-0.9.2/allegro/datduh.c \ - libsrc/dumb-0.9.2/allegro/datit.c \ - libsrc/dumb-0.9.2/allegro/datmod.c \ - libsrc/dumb-0.9.2/allegro/dats3m.c \ - libsrc/dumb-0.9.2/allegro/datunld.c \ - libsrc/dumb-0.9.2/allegro/datxm.c \ - libsrc/dumb-0.9.2/allegro/packfile.c \ - libsrc/dumb-0.9.2/core/atexit.c \ - libsrc/dumb-0.9.2/core/duhlen.c \ - libsrc/dumb-0.9.2/core/dumbfile.c \ - libsrc/dumb-0.9.2/core/loadduh.c \ - libsrc/dumb-0.9.2/core/makeduh.c \ - libsrc/dumb-0.9.2/core/rawsig.c \ - libsrc/dumb-0.9.2/core/readduh.c \ - libsrc/dumb-0.9.2/core/register.c \ - libsrc/dumb-0.9.2/core/rendduh.c \ - libsrc/dumb-0.9.2/core/rendsig.c \ - libsrc/dumb-0.9.2/core/unload.c \ - libsrc/dumb-0.9.2/helpers/clickrem.c \ - libsrc/dumb-0.9.2/helpers/memfile.c \ - libsrc/dumb-0.9.2/helpers/resample.c \ - libsrc/dumb-0.9.2/helpers/sampbuf.c \ - libsrc/dumb-0.9.2/helpers/silence.c \ - libsrc/dumb-0.9.2/helpers/stdfile.c \ - libsrc/dumb-0.9.2/it/itload.c \ - libsrc/dumb-0.9.2/it/itmisc.c \ - libsrc/dumb-0.9.2/it/itorder.c \ - libsrc/dumb-0.9.2/it/itread.c \ - libsrc/dumb-0.9.2/it/itrender.c \ - libsrc/dumb-0.9.2/it/itunload.c \ - libsrc/dumb-0.9.2/it/loadmod.c \ - libsrc/dumb-0.9.2/it/loads3m.c \ - libsrc/dumb-0.9.2/it/loadxm.c \ - libsrc/dumb-0.9.2/it/readmod.c \ - libsrc/dumb-0.9.2/it/reads3m.c \ - libsrc/dumb-0.9.2/it/readxm.c \ - libsrc/dumb-0.9.2/it/xmeffect.c diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index 59df8ff445f..8e43d68721a 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -359,7 +359,7 @@ int mgetbutton() // is this still necessary? // find an elegant way to reimplement this; e.g. allow to configure key->mouse mappings?! #define AGS_SIMULATE_RIGHT_CLICK (AGS_PLATFORM_OS_MACOS) -#if AGS_SIMULATE_RIGHT_CLICK__FIXME +#if defined (AGS_SIMULATE_RIGHT_CLICK__FIXME) // j Ctrl-left click should be right-click if (ags_iskeypressed(__allegro_KEY_LCONTROL) || ags_iskeypressed(__allegro_KEY_RCONTROL)) { diff --git a/Engine/debug/filebasedagsdebugger.cpp b/Engine/debug/filebasedagsdebugger.cpp index ae4ad2a559e..b3c997ac56f 100644 --- a/Engine/debug/filebasedagsdebugger.cpp +++ b/Engine/debug/filebasedagsdebugger.cpp @@ -11,8 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - -#include +#include #include "debug/filebasedagsdebugger.h" #include "util/file.h" #include "util/path.h" diff --git a/Engine/device/mousew32.cpp b/Engine/device/mousew32.cpp index 7a27efb07e0..5469848a150 100644 --- a/Engine/device/mousew32.cpp +++ b/Engine/device/mousew32.cpp @@ -221,12 +221,17 @@ void Mouse::UnlockFromWindow() void Mouse::SetMovementControl(bool on) { +#if defined (SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE) ControlEnabled = on; SDL_SetRelativeMouseMode(static_cast(on)); if (on) SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, String::FromFormat("%.2f", Mouse::Speed).GetCStr()); else SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, "1.0"); +#else + ControlEnabled = false; + Debug::Printf(kDbgMsg_Warn, "WARNING: SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE not supported, mouse control can't be enabled"); +#endif ags_clear_input_buffer(); } diff --git a/Engine/gfx/ali3dogl.cpp b/Engine/gfx/ali3dogl.cpp index aa1961f3531..8a4f7b2d06d 100644 --- a/Engine/gfx/ali3dogl.cpp +++ b/Engine/gfx/ali3dogl.cpp @@ -721,7 +721,7 @@ bool OGLGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *lo catch (Ali3DException exception) { if (exception._message != SDL_GetError()) - SDL_SetError(exception._message); + SDL_SetError("%s", exception._message); return false; } diff --git a/Engine/gfx/ali3dsw.cpp b/Engine/gfx/ali3dsw.cpp index 9b47b06a03a..a4922c491dd 100644 --- a/Engine/gfx/ali3dsw.cpp +++ b/Engine/gfx/ali3dsw.cpp @@ -30,7 +30,7 @@ namespace ALSW using namespace Common; -unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned long n); +static unsigned long _trans_alpha_blender32(unsigned long x, unsigned long y, unsigned long n); RGB faded_out_palette[256]; diff --git a/Engine/media/audio/clip_openal.cpp b/Engine/media/audio/clip_openal.cpp index b31bba6caa9..762ba052421 100644 --- a/Engine/media/audio/clip_openal.cpp +++ b/Engine/media/audio/clip_openal.cpp @@ -11,6 +11,7 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= +#include #include "media/audio/clip_openal.h" #include "media/audio/audio_core.h" #include "media/audio/audiodefines.h" diff --git a/Engine/platform/base/agsplatformdriver.cpp b/Engine/platform/base/agsplatformdriver.cpp index 59c785af8c9..b819fc63934 100644 --- a/Engine/platform/base/agsplatformdriver.cpp +++ b/Engine/platform/base/agsplatformdriver.cpp @@ -29,7 +29,7 @@ using namespace AGS::Common; using namespace AGS::Engine; #if defined (AGS_HAS_CD_AUDIO) -#include "libcda.h" +#include "libsrc/libcda-0.5/libcda.h" #endif // We don't have many places where we delay longer than a frame, but where we diff --git a/Engine/platform/linux/acpllnx.cpp b/Engine/platform/linux/acpllnx.cpp index 06013ca10ec..f3e9ae2fa1b 100644 --- a/Engine/platform/linux/acpllnx.cpp +++ b/Engine/platform/linux/acpllnx.cpp @@ -20,13 +20,12 @@ #include #include -#include #include "ac/runtime_defines.h" #include "gfx/gfxdefines.h" #include "platform/base/agsplatformdriver.h" #include "plugin/agsplugin.h" #include "util/string.h" -#include +#include "libsrc/libcda-0.5/libcda.h" #include #include diff --git a/Engine/platform/windows/gfx/ali3dd3d.cpp b/Engine/platform/windows/gfx/ali3dd3d.cpp index 23a0c942bde..ec67d06b962 100644 --- a/Engine/platform/windows/gfx/ali3dd3d.cpp +++ b/Engine/platform/windows/gfx/ali3dd3d.cpp @@ -768,7 +768,7 @@ bool D3DGraphicsDriver::SetDisplayMode(const DisplayMode &mode, volatile int *lo catch (Ali3DException exception) { if (exception._message != SDL_GetError()) - SDL_SetError(exception._message); + SDL_SetError("%s", exception._message); return false; } OnInit(loopTimer); From b32109a5cda2fa4a6b7f0a8874e7a823412d04f6 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 20 Nov 2020 14:16:47 +0300 Subject: [PATCH 40/41] Linux: include for GCC 4.7+ --- Common/util/misc.cpp | 1 + Engine/platform/linux/acpllnx.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Common/util/misc.cpp b/Common/util/misc.cpp index 13d7adb8de0..65419541bab 100644 --- a/Common/util/misc.cpp +++ b/Common/util/misc.cpp @@ -48,6 +48,7 @@ #include #if !AGS_PLATFORM_OS_WINDOWS #include +#include #endif #include // file path functions diff --git a/Engine/platform/linux/acpllnx.cpp b/Engine/platform/linux/acpllnx.cpp index f3e9ae2fa1b..1f6dc1d7f7e 100644 --- a/Engine/platform/linux/acpllnx.cpp +++ b/Engine/platform/linux/acpllnx.cpp @@ -19,6 +19,7 @@ // ********* LINUX PLACEHOLDER DRIVER ********* #include +#include #include #include "ac/runtime_defines.h" #include "gfx/gfxdefines.h" From b4708c9483db89eaedd1adaa94a28c8ba50e2450 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Sun, 29 Nov 2020 04:40:16 +0300 Subject: [PATCH 41/41] CMake: build with the new backend libs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the work of @ericoporto (Érico Vieira Porto) --- CMake/FetchSDL2.cmake | 30 +++ CMake/FetchSDL_Sound.cmake | 20 ++ CMake/FindLocalAllegro.cmake | 10 + CMake/FindLocalOpenAL.cmake | 16 ++ CMake/SDL_Sound/CMakeLists.txt | 239 ++++++++++++++++ CMakeLists.txt | 36 ++- Common/CMakeLists.txt | 4 +- Common/libsrc/freetype-2.1.3/CMakeLists.txt | 3 +- Engine/CMakeLists.txt | 80 +++--- Engine/libsrc/apeg-1.2.1/CMakeLists.txt | 2 +- libsrc/allegro/CMakeLists.txt | 285 ++++++++++++++++++++ libsrc/allegro/cmake/FileList.cmake | 94 +++++++ libsrc/mojoAL/CMakeLists.txt | 26 ++ 13 files changed, 793 insertions(+), 52 deletions(-) create mode 100644 CMake/FetchSDL2.cmake create mode 100644 CMake/FetchSDL_Sound.cmake create mode 100644 CMake/FindLocalAllegro.cmake create mode 100644 CMake/FindLocalOpenAL.cmake create mode 100644 CMake/SDL_Sound/CMakeLists.txt create mode 100644 libsrc/allegro/CMakeLists.txt create mode 100644 libsrc/allegro/cmake/FileList.cmake create mode 100644 libsrc/mojoAL/CMakeLists.txt diff --git a/CMake/FetchSDL2.cmake b/CMake/FetchSDL2.cmake new file mode 100644 index 00000000000..c7ee0197138 --- /dev/null +++ b/CMake/FetchSDL2.cmake @@ -0,0 +1,30 @@ +FetchContent_Declare( + sdl2_content + URL https://www.libsdl.org/release/SDL2-2.0.12.tar.gz + URL_HASH MD5=783b6f2df8ff02b19bb5ce492b99c8ff +) + +FetchContent_GetProperties(sdl2_content) +if(NOT sdl2_content_POPULATED) + FetchContent_Populate(sdl2_content) + if(ANDROID) + set(SDL_SHARED ON CACHE BOOL "shared") + set(SDL_STATIC ON CACHE BOOL "static") + add_subdirectory(${sdl2_content_SOURCE_DIR} ${sdl2_content_BINARY_DIR} EXCLUDE_FROM_ALL) + add_library(SDL2::SDL2 ALIAS SDL2) + add_library(SDL2::SDL2main ALIAS SDL2main) + elseif(WIN32 OR LINUX OR MACOS) + set(SDL_SHARED OFF CACHE BOOL "no shared") + set(SDL_STATIC ON CACHE BOOL "static") + set(SDL_STATIC_PIC ON CACHE BOOL "Static version of the library should be built with Position Independent Code") + set(SDL_SHARED OFF) + set(SDL_STATIC ON) + set(SDL_STATIC_PIC ON) + set(FORCE_STATIC_VCRT ON CACHE BOOL "static windows static vcrc") + add_subdirectory(${sdl2_content_SOURCE_DIR} ${sdl2_content_BINARY_DIR} EXCLUDE_FROM_ALL) + add_library(SDL2::SDL2 ALIAS SDL2-static) + add_library(SDL2::SDL2main ALIAS SDL2main) + endif() +endif() + + diff --git a/CMake/FetchSDL_Sound.cmake b/CMake/FetchSDL_Sound.cmake new file mode 100644 index 00000000000..0022b173fbb --- /dev/null +++ b/CMake/FetchSDL_Sound.cmake @@ -0,0 +1,20 @@ +FetchContent_Declare( + sdlsound_content + URL https://hg.icculus.org/icculus/SDL_sound/archive/9262f9205898.tar.gz + URL_HASH MD5=64ece3216dcc4877378e6f03064f51ca +) + +FetchContent_GetProperties(sdlsound_content) +if(NOT sdlsound_content) + FetchContent_Populate(sdlsound_content) + + set(SDLSOUND_BUILD_SHARED off CACHE BOOL "no shared") + set(SDLSOUND_BUILD_TEST off CACHE BOOL "no tests") + set(SDLSOUND_BUILD_STATIC on CACHE BOOL "static") + file(COPY CMake/SDL_Sound/CMakeLists.txt DESTINATION ${sdlsound_content_SOURCE_DIR}) + add_subdirectory(${sdlsound_content_SOURCE_DIR} ${sdlsound_content_BINARY_DIR} EXCLUDE_FROM_ALL) + include_directories(${sdlsound_content_SOURCE_DIR}/src/) + add_library(sdl2_sound-interface INTERFACE) + target_link_libraries(sdl2_sound-interface INTERFACE SDL2_sound-static) + add_library(SDL2_sound::SDL2_sound ALIAS sdl2_sound-interface) +endif() diff --git a/CMake/FindLocalAllegro.cmake b/CMake/FindLocalAllegro.cmake new file mode 100644 index 00000000000..d22699acb06 --- /dev/null +++ b/CMake/FindLocalAllegro.cmake @@ -0,0 +1,10 @@ +add_subdirectory(libsrc/allegro EXCLUDE_FROM_ALL) +target_compile_definitions (allegro +INTERFACE + ALLEGRO_STATICLINK + ALLEGRO_NO_COMPATIBILITY + ALLEGRO_NO_FIX_ALIASES + ALLEGRO_NO_FIX_CLASS + ALLEGRO_NO_KEY_DEFINES +) +add_library(Allegro::Allegro ALIAS allegro) diff --git a/CMake/FindLocalOpenAL.cmake b/CMake/FindLocalOpenAL.cmake new file mode 100644 index 00000000000..a16d4146eb8 --- /dev/null +++ b/CMake/FindLocalOpenAL.cmake @@ -0,0 +1,16 @@ +# Grab system openAL or use embedded mojoAL + +find_package(OpenAL) + +if (OPENAL_FOUND) + add_library(openal-interface INTERFACE) + target_link_libraries(openal-interface INTERFACE ${OPENAL_LIBRARY}) + target_include_directories(openal-interface INTERFACE ${OPENAL_INCLUDE_DIR}) + add_library(External::OpenAL ALIAS openal-interface) +else() + add_subdirectory(libsrc/mojoAL EXCLUDE_FROM_ALL) + + add_library(openal-interface INTERFACE) + target_link_libraries(openal-interface INTERFACE MojoAL::MojoAL) + add_library(External::OpenAL ALIAS openal-interface) +endif() diff --git a/CMake/SDL_Sound/CMakeLists.txt b/CMake/SDL_Sound/CMakeLists.txt new file mode 100644 index 00000000000..5b773f3c964 --- /dev/null +++ b/CMake/SDL_Sound/CMakeLists.txt @@ -0,0 +1,239 @@ +# SDL_sound; An abstract sound format decoding API. +# +# Please see the file LICENSE.txt in the source's root directory. + +cmake_minimum_required(VERSION 2.8.4) + +project(SDL_sound) +set(SDLSOUND_VERSION 1.9.0) + +# Increment this if/when we break backwards compatibility. +set(SDLSOUND_SOVERSION 1) + +# I hate that they define "WIN32" ... we're about to move to Win64...I hope! +if(WIN32 AND NOT WINDOWS) + set(WINDOWS TRUE) +endif() + +include_directories(src) + +if(CMAKE_COMPILER_IS_GNUCC) + # Don't use -rpath. + set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE) +endif() + +if(CMAKE_C_COMPILER_ID STREQUAL "SunPro") + add_definitions(-erroff=E_EMPTY_TRANSLATION_UNIT) + add_definitions(-xldscope=hidden) +endif() + +find_package(SDL2 REQUIRED) +include_directories(${SDL2_INCLUDE_DIRS}) + + +# Decoders ... +# These are (mostly) on by default now, so these options are only useful for +# disabling them. + +macro(sdlsound_decoder_option _VAR _NAME _EXTS) + option(SDLSOUND_DECODER_${_VAR} "Enable ${_NAME} support (${_EXTS})" TRUE) + if(NOT SDLSOUND_DECODER_${_VAR}) + add_definitions("-DSOUND_SUPPORTS_${_VAR}=0") + endif() +endmacro() + +sdlsound_decoder_option(WAV "Wave" ".WAV") +sdlsound_decoder_option(AIFF "Audio Interchange" ".AIFF") +sdlsound_decoder_option(AU "Sun/NeXT audio" ".AU") +sdlsound_decoder_option(VOC "Creative Labs voice" ".VOC") +sdlsound_decoder_option(FLAC "Free Lossless Audio Codec" ".FLAC") +sdlsound_decoder_option(VORBIS "Ogg Vorbis" ".OGG") +sdlsound_decoder_option(RAW "raw PCM audio" ".RAW") +sdlsound_decoder_option(SHN "Shorten" ".SHN") +sdlsound_decoder_option(MODPLUG "ModPlug" "various tracker formats") +sdlsound_decoder_option(MP3 "MPEG-1 Layers I-III" ".MP3, .MP2, .MP1") + +if(APPLE) + sdlsound_decoder_option(COREAUDIO "CoreAudio" "various audio formats") + if(SDLSOUND_DECODER_COREAUDIO) + set(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} "-framework AudioToolbox") + endif() +endif() + +if(SDLSOUND_DECODER_MODPLUG) + set(LIBMODPLUG_SRCS + src/libmodplug/fastmix.c + src/libmodplug/load_669.c + src/libmodplug/load_abc.c + src/libmodplug/load_amf.c + src/libmodplug/load_ams.c + src/libmodplug/load_dbm.c + src/libmodplug/load_dmf.c + src/libmodplug/load_dsm.c + src/libmodplug/load_far.c + src/libmodplug/load_it.c + src/libmodplug/load_mdl.c + src/libmodplug/load_med.c + src/libmodplug/load_mid.c + src/libmodplug/load_mod.c + src/libmodplug/load_mt2.c + src/libmodplug/load_mtm.c + src/libmodplug/load_okt.c + src/libmodplug/load_pat.c + src/libmodplug/load_psm.c + src/libmodplug/load_ptm.c + src/libmodplug/load_s3m.c + src/libmodplug/load_stm.c + src/libmodplug/load_ult.c + src/libmodplug/load_umx.c + src/libmodplug/load_xm.c + src/libmodplug/mmcmp.c + src/libmodplug/modplug.c + src/libmodplug/snd_dsp.c + src/libmodplug/snd_flt.c + src/libmodplug/snd_fx.c + src/libmodplug/sndfile.c + src/libmodplug/sndmix.c + ) +endif() + +# Almost everything is "compiled" here, but things that don't apply to the +# build are #ifdef'd out. This is to make it easy to embed SDL_sound into +# another project or bring up a new build system: just compile all the source +# code and #define the things you want. +set(SDLSOUND_SRCS + src/SDL_sound.c + src/SDL_sound_aiff.c + src/SDL_sound_au.c + src/SDL_sound_coreaudio.c + src/SDL_sound_flac.c + src/SDL_sound_modplug.c + src/SDL_sound_mp3.c + src/SDL_sound_raw.c + src/SDL_sound_shn.c + src/SDL_sound_voc.c + src/SDL_sound_vorbis.c + src/SDL_sound_wav.c + ${LIBMODPLUG_SRCS} + ) + +option(SDLSOUND_BUILD_STATIC "Build static library" TRUE) +if(SDLSOUND_BUILD_STATIC) + add_library(SDL2_sound-static STATIC ${SDLSOUND_SRCS}) + # Don't rename this on Windows, since DLLs will also produce an import + # library named "SDL2_sound.lib" which would conflict; Unix tend to like + # the same library name with a different extension for static libs, but + # Windows can just have a separate name. + if(NOT MSVC) + set_target_properties(SDL2_sound-static PROPERTIES OUTPUT_NAME "SDL2_sound") + endif() + set(SDLSOUND_LIB_TARGET SDL2_sound-static) + set(SDLSOUND_INSTALL_TARGETS ${SDLSOUND_INSTALL_TARGETS} ";SDL2_sound-static") +endif() + +option(SDLSOUND_BUILD_SHARED "Build shared library" TRUE) +if(SDLSOUND_BUILD_SHARED) + add_library(SDL2_sound SHARED ${SDLSOUND_SRCS}) + set_target_properties(SDL2_sound PROPERTIES MACOSX_RPATH 1) + set_target_properties(SDL2_sound PROPERTIES VERSION ${SDLSOUND_VERSION}) + set_target_properties(SDL2_sound PROPERTIES SOVERSION ${SDLSOUND_SOVERSION}) + target_link_libraries(SDL2_sound ${SDL2_LIBRARIES} ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS}) + set(SDLSOUND_LIB_TARGET SDL2_sound) + set(SDLSOUND_INSTALL_TARGETS ${SDLSOUND_INSTALL_TARGETS} ";SDL2_sound") +endif() + +if(NOT SDLSOUND_BUILD_SHARED AND NOT SDLSOUND_BUILD_STATIC) + message(FATAL "Both shared and static libraries are disabled!") +endif() + +# CMake FAQ says I need this... +if(SDLSOUND_BUILD_SHARED AND SDLSOUND_BUILD_STATIC AND NOT WINDOWS) + set_target_properties(SDL2_sound PROPERTIES CLEAN_DIRECT_OUTPUT 1) + set_target_properties(SDL2_sound-static PROPERTIES CLEAN_DIRECT_OUTPUT 1) +endif() + +option(SDLSOUND_BUILD_TEST "Build stdio test program." TRUE) +mark_as_advanced(SDLSOUND_BUILD_TEST) +if(SDLSOUND_BUILD_TEST) + add_executable(playsound playsound/playsound.c) + target_link_libraries(playsound ${SDLSOUND_LIB_TARGET} ${OTHER_LDFLAGS}) + set(SDLSOUND_INSTALL_TARGETS ${SDLSOUND_INSTALL_TARGETS} ";playsound") + add_executable(playsound_simple playsound/playsound_simple.c) + target_link_libraries(playsound_simple ${SDLSOUND_LIB_TARGET} ${OTHER_LDFLAGS}) + #set(SDLSOUND_INSTALL_TARGETS ${SDLSOUND_INSTALL_TARGETS} ";playsound_simple") + if(NOT SDLSOUND_BUILD_SHARED) + target_link_libraries(playsound ${SDL2_LIBRARIES} ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS}) + target_link_libraries(playsound_simple ${SDL2_LIBRARIES} ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS}) + endif() +endif() + +install(TARGETS ${SDLSOUND_INSTALL_TARGETS} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +install(FILES SDL_sound.h DESTINATION include) + +find_package(Doxygen) +if(DOXYGEN_FOUND) + set(SDLSOUND_OUTPUT_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile" + "${SDLSOUND_OUTPUT_DOXYFILE}" + COPYONLY + ) + file(APPEND "${SDLSOUND_OUTPUT_DOXYFILE}" "\n\n# Below auto-generated by cmake...\n\n") + file(APPEND "${SDLSOUND_OUTPUT_DOXYFILE}" "PROJECT_NUMBER = \"${SDLSOUND_VERSION}\"\n") + file(APPEND "${SDLSOUND_OUTPUT_DOXYFILE}" "OUTPUT_DIRECTORY = \"${CMAKE_CURRENT_BINARY_DIR}/docs\"\n") + file(APPEND "${SDLSOUND_OUTPUT_DOXYFILE}" "\n# End auto-generated section.\n\n") + + add_custom_target( + docs + ${DOXYGEN_EXECUTABLE} "${SDLSOUND_OUTPUT_DOXYFILE}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building documentation..." + ) +else() + message(STATUS "Doxygen not found. You won't be able to build documentation.") +endif() + +if(UNIX) + set(SDLSOUND_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../SDL_sound-${SDLSOUND_VERSION}.tar.bz2") + add_custom_target( + SDL_Sound_dist + hg archive -t tbz2 "${SDLSOUND_TARBALL}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building source tarball '${SDLSOUND_TARBALL}'..." + ) + add_custom_target( + SDL_Sound_uninstall + "${CMAKE_CURRENT_SOURCE_DIR}/docs/uninstall.sh" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + COMMENT "Uninstall the project..." + ) +endif() + +macro(message_bool_option _NAME _VALUE) + if(${_VALUE}) + message(STATUS " ${_NAME}: enabled") + else() + message(STATUS " ${_NAME}: disabled") + endif() +endmacro() + +message(STATUS "SDL_sound will build with the following options:") +message_bool_option("WAV support" SDLSOUND_DECODER_WAV) +message_bool_option("AIFF support" SDLSOUND_DECODER_AIFF) +message_bool_option("AU support" SDLSOUND_DECODER_AU) +message_bool_option("VOC support" SDLSOUND_DECODER_VOC) +message_bool_option("FLAC support" SDLSOUND_DECODER_FLAC) +message_bool_option("VORBIS support" SDLSOUND_DECODER_VORBIS) +message_bool_option("RAW support" SDLSOUND_DECODER_RAW) +message_bool_option("SHN support" SDLSOUND_DECODER_SHN) +message_bool_option("MODPLUG support" SDLSOUND_DECODER_MODPLUG) +message_bool_option("MP3 support" SDLSOUND_DECODER_MP3) +message_bool_option("COREAUDIO support" SDLSOUND_DECODER_COREAUDIO) +message_bool_option("Build static library" SDLSOUND_BUILD_STATIC) +message_bool_option("Build shared library" SDLSOUND_BUILD_SHARED) +message_bool_option("Build stdio test program" SDLSOUND_BUILD_TEST) + +# end of CMakeLists.txt ... diff --git a/CMakeLists.txt b/CMakeLists.txt index 674ff77f49a..0735ccbce29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,16 @@ option(AGS_NO_VIDEO_PLAYER "Disable Video" OFF) option(AGS_BUILTIN_PLUGINS "Built in plugins" OFF) set(AGS_BUILD_STR "" CACHE STRING "Engine Build Information") +# Tools like ninja don't have a pseudo-terminal so compilers assume no coloured output +option (AGS_FORCE_COLOURED_OUTPUT "Always produce ANSI-coloured output (GNU/Clang only)." OFF) +if (${AGS_FORCE_COLOURED_OUTPUT}) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + add_compile_options (-fdiagnostics-color=always) + elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + add_compile_options (-fcolor-diagnostics) + endif () +endif () + include(FetchContent) set(FETCHCONTENT_UPDATES_DISCONNECTED on) @@ -28,10 +38,25 @@ else() message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}") endif () +message( "CMAKE_SYSTEM_NAME:" ${CMAKE_SYSTEM_NAME} ) +message( "WIN32:" ${WIN32} ) +message( "LINUX:" ${LINUX} ) +message( "MACOS:" ${MACOS} ) + if (WIN32 AND NOT CMAKE_SIZEOF_VOID_P EQUAL 4) message(FATAL_ERROR "Windows builds only support 32bit for now") endif() +if(LINUX) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0) + # without no-pie we can't double-click run ags in Nautilus + # this should only be needed in newer gcc versions + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-pie -no-pie") + endif () + endif () +endif (LINUX) + include(CheckIPOSupported) check_ipo_supported(RESULT ipo_supported OUTPUT ipo_not_supported_reason) @@ -111,7 +136,12 @@ elseif (LINUX) find_package(X11) endif() -include(FetchAllegro) +include(FetchSDL2) +include(FetchSDL_Sound) + +include(FindLocalOpenAL) +include(FindLocalAllegro) + include(FetchOgg) include(FetchVorbis) include(FetchTheora) @@ -121,12 +151,8 @@ add_subdirectory(Common/libsrc/alfont-2.0.9 EXCLUDE_FROM_ALL) add_subdirectory(Common/libsrc/freetype-2.1.3 EXCLUDE_FROM_ALL) add_subdirectory(Common EXCLUDE_FROM_ALL) -add_subdirectory(Engine/libsrc/almp3-2.0.5 EXCLUDE_FROM_ALL) -add_subdirectory(Engine/libsrc/alogg EXCLUDE_FROM_ALL) add_subdirectory(Engine/libsrc/apeg-1.2.1 EXCLUDE_FROM_ALL) -add_subdirectory(Engine/libsrc/dumb-0.9.2 EXCLUDE_FROM_ALL) add_subdirectory(Engine/libsrc/glad EXCLUDE_FROM_ALL) -add_subdirectory(Engine/libsrc/hq2x EXCLUDE_FROM_ALL) add_subdirectory(Engine/libsrc/libcda-0.5 EXCLUDE_FROM_ALL) add_subdirectory(Engine) diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt index 19e2c84a231..bcc34e87b76 100644 --- a/Common/CMakeLists.txt +++ b/Common/CMakeLists.txt @@ -33,6 +33,8 @@ target_sources(common ac/interfaceelement.h ac/inventoryiteminfo.cpp ac/inventoryiteminfo.h + ac/keycode.cpp + ac/keycode.h ac/mousecursor.cpp ac/mousecursor.h ac/oldgamesetupstruct.h @@ -162,7 +164,7 @@ target_sources(common util/string_compat.h ) -target_link_libraries(common PUBLIC Allegro::Allegro AlFont::AlFont AAStr::AAStr) +target_link_libraries(common PUBLIC SDL2::SDL2 Allegro::Allegro AlFont::AlFont AAStr::AAStr) # NOTE: You can optionally create case sensitive filesystems on Macos and Windows now. if (LINUX) diff --git a/Common/libsrc/freetype-2.1.3/CMakeLists.txt b/Common/libsrc/freetype-2.1.3/CMakeLists.txt index 2c57a43278c..7cefd7f27ee 100644 --- a/Common/libsrc/freetype-2.1.3/CMakeLists.txt +++ b/Common/libsrc/freetype-2.1.3/CMakeLists.txt @@ -46,7 +46,8 @@ if (WIN32) src/base/ftsystem.c builds/win32/ftdebug.c ) -elseif (MACOS OR LINUX) +else() + # Currently assume all non-windows platforms are unix-y target_sources(freetype PRIVATE builds/unix/ftsystem.c src/base/ftdebug.c diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index 0a8c3049028..c3368c77a87 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -1,7 +1,12 @@ # Engine # ----------------------------------------------------------------------------- -add_library(engine) +if (NOT ANDROID) +add_library(engine STATIC) +else () +add_library(engine SHARED) +endif () + set_target_properties(engine PROPERTIES CXX_STANDARD 11 @@ -57,6 +62,7 @@ target_sources(engine ac/dynobj/cc_dialog.h ac/dynobj/cc_dynamicarray.cpp ac/dynobj/cc_dynamicarray.h + ac/dynobj/cc_dynamicobject_addr_and_manager.h ac/dynobj/cc_dynamicobject.cpp ac/dynobj/cc_dynamicobject.h ac/dynobj/cc_gui.cpp @@ -78,11 +84,14 @@ target_sources(engine ac/dynobj/scriptaudiochannel.h ac/dynobj/scriptcamera.cpp ac/dynobj/scriptcamera.h + ac/dynobj/scriptcontainers.h ac/dynobj/scriptdatetime.cpp ac/dynobj/scriptdatetime.h ac/dynobj/scriptdialog.h ac/dynobj/scriptdialogoptionsrendering.cpp ac/dynobj/scriptdialogoptionsrendering.h + ac/dynobj/scriptdict.cpp + ac/dynobj/scriptdict.h ac/dynobj/scriptdrawingsurface.cpp ac/dynobj/scriptdrawingsurface.h ac/dynobj/scriptdynamicsprite.cpp @@ -97,6 +106,8 @@ target_sources(engine ac/dynobj/scriptoverlay.cpp ac/dynobj/scriptoverlay.h ac/dynobj/scriptregion.h + ac/dynobj/scriptset.cpp + ac/dynobj/scriptset.h ac/dynobj/scriptstring.cpp ac/dynobj/scriptstring.h ac/dynobj/scriptsystem.h @@ -203,8 +214,6 @@ target_sources(engine ac/inventoryitem.h ac/invwindow.cpp ac/invwindow.h - ac/keycode.cpp - ac/keycode.h ac/label.cpp ac/label.h ac/lipsync.h @@ -242,11 +251,13 @@ target_sources(engine ac/route_finder_impl.h ac/route_finder_impl_legacy.cpp ac/route_finder_impl_legacy.h + ac/route_finder_jps.inl ac/runtime_defines.h ac/screen.cpp ac/screen.h ac/screenoverlay.cpp ac/screenoverlay.h + ac/scriptcontainers.cpp ac/slider.cpp ac/slider.h ac/speech.cpp @@ -329,16 +340,14 @@ target_sources(engine gfx/gfxfilter_aad3d.h gfx/gfxfilter_aaogl.cpp gfx/gfxfilter_aaogl.h - gfx/gfxfilter_allegro.cpp - gfx/gfxfilter_allegro.h gfx/gfxfilter_d3d.cpp gfx/gfxfilter_d3d.h - gfx/gfxfilter_hqx.cpp - gfx/gfxfilter_hqx.h gfx/gfxfilter_ogl.cpp gfx/gfxfilter_ogl.h gfx/gfxfilter_scaling.cpp gfx/gfxfilter_scaling.h + gfx/gfxfilter_sdl_renderer.cpp + gfx/gfxfilter_sdl_renderer.h gfx/gfxmodelist.h gfx/graphicsdriver.h gfx/ogl_headers.h @@ -378,7 +387,6 @@ target_sources(engine main/graphics_mode.h main/main.cpp main/main.h - main/main_allegro.h main/maindefines_ex.h main/mainheader.h main/quit.cpp @@ -387,40 +395,31 @@ target_sources(engine main/update.h media/audio/ambientsound.cpp media/audio/ambientsound.h + media/audio/audio_core.cpp + media/audio/audio_core_defs.h + media/audio/audio_core.h media/audio/audio.cpp media/audio/audio.h media/audio/audio_system.h media/audio/audiodefines.h media/audio/audiointernaldefs.h - media/audio/clip_mydumbmod.cpp - media/audio/clip_mydumbmod.h - media/audio/clip_myjgmod.cpp - media/audio/clip_myjgmod.h - media/audio/clip_mymidi.cpp - media/audio/clip_mymidi.h - media/audio/clip_mymp3.cpp - media/audio/clip_mymp3.h - media/audio/clip_myogg.cpp - media/audio/clip_myogg.h - media/audio/clip_mystaticmp3.cpp - media/audio/clip_mystaticmp3.h - media/audio/clip_mystaticogg.cpp - media/audio/clip_mystaticogg.h - media/audio/clip_mywave.cpp - media/audio/clip_mywave.h + media/audio/clip_openal.cpp + media/audio/clip_openal.h + media/audio/openaldecoder.cpp + media/audio/openaldecoder.h + media/audio/openal.h media/audio/queuedaudioitem.cpp media/audio/queuedaudioitem.h media/audio/sound.cpp media/audio/sound.h - media/audio/soundcache.cpp - media/audio/soundcache.h media/audio/soundclip.cpp media/audio/soundclip.h - media/video/VMR9Graph.h media/video/video.cpp media/video/video.h platform/base/agsplatformdriver.cpp platform/base/agsplatformdriver.h + platform/base/sys_main.cpp + platform/base/sys_main.h platform/util/libc.c platform/util/pe.c platform/util/pe.h @@ -473,19 +472,13 @@ target_sources(engine util/thread.h util/thread_pthread.h util/thread_std.h - ac/scriptcontainers.cpp - ac/dynobj/scriptcontainers.h - ac/dynobj/scriptdict.cpp - ac/dynobj/scriptdict.h - ac/dynobj/scriptset.cpp - ac/dynobj/scriptset.h platform/windows/acplwin.cpp platform/windows/debug/namedpipesagsdebugger.cpp platform/windows/gfx/ali3dd3d.cpp - platform/windows/media/video/acwavi.cpp - platform/windows/media/video/acwavi3d.cpp platform/windows/setup/winsetup.cpp + platform/windows/minidump.cpp + platform/windows/win_ex_handling.cpp platform/linux/acpllnx.cpp @@ -561,14 +554,13 @@ endif() target_link_libraries(engine PUBLIC AGS::Common ${CMAKE_DL_LIBS} - Glad::Glad Threads::Threads Allegro::Allegro - AlDumb::AlDumb - AlMp3::AlMp3 - AlOgg::AlOgg - HQ2X::hq2x Cda::Cda + SDL2_sound::SDL2_sound + External::OpenAL + SDL2::SDL2 + Glad::Glad ) # common has a circular dependency on engine @@ -615,10 +607,10 @@ target_include_directories(ags PRIVATE .) target_sources(ags PRIVATE - main/main_allegro.cpp + main/main_sdl2.cpp ) -target_link_libraries(ags PRIVATE engine) +target_link_libraries(ags PRIVATE engine SDL2::SDL2main) if (LINUX) # We may override `allegro_icon` and `load_midi_pf` depending on the version @@ -664,11 +656,11 @@ if (MACOS) target_sources(ags-app PRIVATE - main/main_allegro.cpp + main/main_sdl2.cpp ${RESOURCE_FILES} ) - target_link_libraries(ags-app PRIVATE engine) + target_link_libraries(ags-app PRIVATE engine SDL2::SDL2main) set_target_properties(ags-app PROPERTIES RUNTIME_OUTPUT_NAME AGS diff --git a/Engine/libsrc/apeg-1.2.1/CMakeLists.txt b/Engine/libsrc/apeg-1.2.1/CMakeLists.txt index d56d81f0171..456c01096e9 100644 --- a/Engine/libsrc/apeg-1.2.1/CMakeLists.txt +++ b/Engine/libsrc/apeg-1.2.1/CMakeLists.txt @@ -38,6 +38,6 @@ target_sources(apeg target_compile_definitions(apeg PRIVATE DISABLE_MPEG_AUDIO) -target_link_libraries(apeg PUBLIC Allegro::Allegro Ogg::Ogg Vorbis::Vorbis Vorbis::VorbisFile Theora::TheoraDecoder External::OpenAL) +target_link_libraries(apeg PUBLIC SDL2::SDL2 Allegro::Allegro Ogg::Ogg Vorbis::Vorbis Vorbis::VorbisFile Theora::TheoraDecoder External::OpenAL) add_library(Apeg::Apeg ALIAS apeg) diff --git a/libsrc/allegro/CMakeLists.txt b/libsrc/allegro/CMakeLists.txt new file mode 100644 index 00000000000..951ea4c4167 --- /dev/null +++ b/libsrc/allegro/CMakeLists.txt @@ -0,0 +1,285 @@ + +#-----------------------------------------------------------------------------# +# +# CMake setup +# + +# Refer to https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Life-Cycle-Considerations +cmake_minimum_required(VERSION 3.7.2 FATAL_ERROR) + + +#-----------------------------------------------------------------------------# +# +# Build options +# + +# Set the project name. +project(ALLEGRO C CXX) + +if(WIN32) + enable_language(RC OPTIONAL) +endif(WIN32) + +set(ALLEGRO_VERSION 4.4.3) + +# Search in the `cmake' directory for additional CMake modules. +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + +# Put libraries into `lib'. +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) + +# Lists of all the source files. +include(FileList) + + +#-----------------------------------------------------------------------------# +# +# Unix platform checks +# + +include(CheckIncludeFiles) +include(CheckFunctionExists) +include(CheckCSourceCompiles) +include(CheckCSourceRuns) +include(FindPkgConfig) +include(TestBigEndian) + +test_big_endian(ALLEGRO_BIG_ENDIAN) +if(NOT ALLEGRO_BIG_ENDIAN) + set(ALLEGRO_LITTLE_ENDIAN 1) +endif(NOT ALLEGRO_BIG_ENDIAN) + +if(UNIX) + + check_include_files(dirent.h ALLEGRO_HAVE_DIRENT_H) + check_include_files(inttypes.h ALLEGRO_HAVE_INTTYPES_H) + check_include_files(stdint.h ALLEGRO_HAVE_STDINT_H) + check_include_files(sys/io.h ALLEGRO_HAVE_SYS_IO_H) + check_include_files(sys/stat.h ALLEGRO_HAVE_SYS_STAT_H) + check_include_files(sys/time.h ALLEGRO_HAVE_SYS_TIME_H) + check_include_files(sys/utsname.h ALLEGRO_HAVE_SYS_UTSNAME_H) + + check_function_exists(getexecname ALLEGRO_HAVE_GETEXECNAME) + check_function_exists(memcmp ALLEGRO_HAVE_MEMCMP) + check_function_exists(mkstemp ALLEGRO_HAVE_MKSTEMP) + check_function_exists(mmap ALLEGRO_HAVE_MMAP) + check_function_exists(mprotect ALLEGRO_HAVE_MPROTECT) + check_function_exists(sched_yield ALLEGRO_HAVE_SCHED_YIELD) + check_function_exists(stricmp ALLEGRO_HAVE_STRICMP) + check_function_exists(strlwr ALLEGRO_HAVE_STRLWR) + check_function_exists(strupr ALLEGRO_HAVE_STRUPR) + check_function_exists(sysconf ALLEGRO_HAVE_SYSCONF) + + check_c_source_compiles(" + #include + #include + int main(void) { + struct prpsinfo psinfo; + ioctl(0, PIOCPSINFO, &psinfo); + return 0; + }" + ALLEGRO_HAVE_SV_PROCFS_H + ) + check_c_source_compiles(" + #include + int main(void) { + struct prpsinfo psinfo; + psinfo.pr_argc = 0; + return 0; + }" + ALLEGRO_HAVE_PROCFS_ARGCV + ) + + check_c_source_compiles(" + #include + #include + int main(void) { + void *x = MAP_FAILED; + }" + MAP_FAILED_DEFINED) + if(NOT MAP_FAILED_DEFINED) + set(MAP_FAILED "((void *) -1)") + endif() + + set(ALLEGRO_WITH_MAGIC_MAIN 0) + + # XXX const + # XXX inline + # XXX size_t +endif(UNIX) + +if(UNIX AND NOT ANDROID) + check_c_source_runs(" + static int notsupported = 1; + void test_ctor (void) __attribute__((constructor)); + void test_ctor (void) { notsupported = 0; } + int main(void) { return (notsupported); } + " + ALLEGRO_USE_CONSTRUCTOR) + + find_library(RT_LIBRARY rt) + check_c_source_compiles(" + #include + int main(void) { + struct timespec new_time_ns; + clock_gettime(CLOCK_MONOTONIC, &new_time_ns); + return 0; + }" + ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK + ) +endif() + + +if(ANDROID) + set(ALLEGRO_USE_CONSTRUCTOR true) + set(ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK true) +endif() + +#-----------------------------------------------------------------------------# +# +# Compiler and platform setup +# + +option(STRICT_WARN "Halt at warnings" off) + +if(CMAKE_COMPILER_IS_GNUCC) + set(COMPILER_GCC 1) + set(ALLEGRO_GCC 1) + set(WFLAGS "-W -Wall -Wno-unused-parameter") + set(WFLAGS_C_ONLY "-Wdeclaration-after-statement") + if(STRICT_WARN) + set(WFLAGS "${WFLAGS} -Werror -Wpointer-arith") + set(WFLAGS_C_ONLY "${WFLAGS_C_ONLY} -Wmissing-declarations") + set(WFLAGS_C_ONLY "${WFLAGS_C_ONLY} -Wstrict-prototypes") + endif(STRICT_WARN) +endif(CMAKE_COMPILER_IS_GNUCC) + +if(MSVC) + set(COMPILER_MSVC 1) + set(ALLEGRO_MSVC 1) + set(WFLAGS "/W3 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE") +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + # WIN32 is set by CMake for any Windows platform +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(ALLEGRO_UNIX TRUE) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Android") + set(ALLEGRO_ANDROID TRUE) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") + set(ALLEGRO_UNIX TRUE) +elseif (IOS) + set(ALLEGRO_IOS TRUE) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(ALLEGRO_MACOSX TRUE) +else () + message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}") +endif () + +message( "CMAKE_SYSTEM_NAME:" ${CMAKE_SYSTEM_NAME} ) +message( "ALLEGRO_MSVC:" ${ALLEGRO_MSVC} ) +message( "ALLEGRO_UNIX:" ${ALLEGRO_UNIX} ) +message( "ALLEGRO_ANDROID:" ${ALLEGRO_ANDROID} ) +message( "ALLEGRO_IOS:" ${ALLEGRO_IOS} ) +message( "ALLEGRO_MACOSX:" ${ALLEGRO_MACOSX} ) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WFLAGS} ${WFLAGS_C_ONLY}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WFLAGS} ${WFLAGS_CXX_ONLY}") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DALLEGRO_STATICLINK") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DALLEGRO_STATICLINK") + +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUGMODE=1") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUGMODE=1") + +list(APPEND CMAKE_BUILD_TYPES Profile) +mark_as_advanced( + CMAKE_C_FLAGS_PROFILE + CMAKE_CXX_FLAGS_PROFILE + CMAKE_EXE_LINKER_FLAGS_PROFILE + ) +if(COMPILER_GCC) + set(CMAKE_C_FLAGS_PROFILE "-pg" + CACHE STRING "profiling flags") + set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE}" + CACHE STRING "profiling flags") + set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-pg" + CACHE STRING "profiling flags") + set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "-pg" + CACHE STRING "profiling flags") +endif(COMPILER_GCC) +if(COMPILER_MSVC) + set(CMAKE_C_FLAGS_PROFILE "-Gd -Ox" + CACHE STRING "profiling flags") + set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE}" + CACHE STRING "profiling flags") + set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-profile" + CACHE STRING "profiling flags") +endif(COMPILER_MSVC) + +#-----------------------------------------------------------------------------# + +# Not sure if we want to support disabling these any more. +set(ALLEGRO_COLOR8 1) +set(ALLEGRO_COLOR16 1) +set(ALLEGRO_COLOR24 1) +set(ALLEGRO_COLOR32 1) + +set(ALLEGRO_NO_ASM 1) + + + +#-----------------------------------------------------------------------------# +# +# Platform drivers +# + +set(PLATFORM_SOURCES) + +if(ALLEGRO_MSVC) + list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_WIN_FILES}) +elseif(ALLEGRO_UNIX) + list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_UNIX_FILES}) +endif() + + + +#-----------------------------------------------------------------------------# +# +# Main library +# + +add_library(allegro + ${ALLEGRO_SRC_FILES} + ${ALLEGRO_SRC_C_FILES} + ${PLATFORM_SOURCES} + ${ALLEGRO_PUBLIC_HEADERS} +) + +set_target_properties(allegro + PROPERTIES + DEBUG_POSTFIX -debug + PROFILE_POSTFIX -profile +) + +set(allegro_OUTPUT_NAME alleg) + +set_target_properties(allegro + PROPERTIES + COMPILE_FLAGS "-DALLEGRO_SRC" + LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" + OUTPUT_NAME ${allegro_OUTPUT_NAME} + VERSION ${ALLEGRO_VERSION} + ) + +# Search for C header files in these directories. + +message("${ALLEGRO_PUBLIC_HEADERS}") +target_include_directories(allegro + PRIVATE ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include + PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/include +) + + +#-----------------------------------------------------------------------------# +# vim: set sts=4 sw=4 et: diff --git a/libsrc/allegro/cmake/FileList.cmake b/libsrc/allegro/cmake/FileList.cmake new file mode 100644 index 00000000000..391e09e93f6 --- /dev/null +++ b/libsrc/allegro/cmake/FileList.cmake @@ -0,0 +1,94 @@ +set(ALLEGRO_SRC_FILES + src/allegro.c + src/blit.c + src/bmp.c + src/colblend.c + src/color.c + src/dataregi.c + src/dither.c + src/file.c + src/fli.c + src/flood.c + src/gfx.c + src/graphics.c + src/inline.c + src/libc.c + src/math.c + src/pcx.c + src/polygon.c + src/quantize.c + src/readbmp.c + src/rotate.c + src/unicode.c + src/vtable15.c + src/vtable16.c + src/vtable24.c + src/vtable32.c + src/vtable8.c + src/vtable.c + ) + +set(ALLEGRO_SRC_C_FILES + src/c/cblit8.c + src/c/cblit16.c + src/c/cblit24.c + src/c/cblit32.c + src/c/cgfx8.c + src/c/cgfx15.c + src/c/cgfx16.c + src/c/cgfx24.c + src/c/cgfx32.c + src/c/cmisc.c + src/c/cspr8.c + src/c/cspr15.c + src/c/cspr16.c + src/c/cspr24.c + src/c/cspr32.c + src/c/cstretch.c + ) + +set(ALLEGRO_SRC_UNIX_FILES + src/unix/ufile.c + ) + +set(ALLEGRO_SRC_WIN_FILES + src/win/gdi.c + src/win/wfile.c + ) + +set(ALLEGRO_INCLUDE_ALLEGRO_FILES + include/allegro/base.h + include/allegro/color.h + include/allegro/datafile.h + include/allegro/debug.h + include/allegro/draw.h + include/allegro/file.h + include/allegro/fixed.h + include/allegro/fli.h + include/allegro/fmaths.h + include/allegro/gfx.h + include/allegro/palette.h + include/allegro/system.h + include/allegro/unicode.h + ) + +set(ALLEGRO_INCLUDE_ALLEGRO_INLINE_FILES + include/allegro/inline/color.inl + include/allegro/inline/draw.inl + include/allegro/inline/fix.inl + include/allegro/inline/fmaths.inl + include/allegro/inline/gfx.inl + ) + +set(ALLEGRO_INCLUDE_ALLEGRO_INTERNAL_FILES + include/allegro/internal/aintern.h + include/allegro/internal/alconfig.h + ) + +set(ALLEGRO_INCLUDE_ALLEGRO_PLATFORM_FILES + include/allegro/platform/astdint.h + include/allegro/platform/alucfg.h + ) + +#-----------------------------------------------------------------------------# +# vim: set sts=4 sw=4 et: diff --git a/libsrc/mojoAL/CMakeLists.txt b/libsrc/mojoAL/CMakeLists.txt new file mode 100644 index 00000000000..3fe158fdbcd --- /dev/null +++ b/libsrc/mojoAL/CMakeLists.txt @@ -0,0 +1,26 @@ +add_library(mojoal) + +set_target_properties(mojoal PROPERTIES + C_STANDARD 11 + C_EXTENSIONS NO + ) + +target_include_directories(mojoal PUBLIC . ) + +target_sources(mojoal + PRIVATE + mojoal.c + AL/al.h + AL/alc.h + ) + +if(NOT EMSCRIPTEN) + target_link_libraries(mojoal PUBLIC SDL2::SDL2) +else() + target_link_libraries(mojoal PUBLIC ${SDL2_LIBRARIES}) +endif() + + +target_compile_definitions(mojoal PUBLIC AL_LIBTYPE_STATIC) + +add_library(MojoAL::MojoAL ALIAS mojoal) \ No newline at end of file