Update to SDL key mappings and to mouse click-the-same-spot-mode radius

This commit is contained in:
pelya
2011-09-14 18:50:11 +03:00
parent 8e16ec9f33
commit c1ae5a0fc6
876 changed files with 2032 additions and 216330 deletions

View File

@@ -216,7 +216,7 @@ fi
if [ -z "$ForceRelativeMouseMode" -o -z "$AUTO" ]; then
echo
echo -n "Force relative (laptop) mouse movement mode, if both on-screen keyboard and mouse are needed (y) or (n) ($ForceRelativeMouseMode): "
echo -n "Force relative (laptop) mouse movement mode, useful when both on-screen keyboard and mouse are needed (y) or (n) ($ForceRelativeMouseMode): "
read var
if [ -n "$var" ] ; then
ForceRelativeMouseMode="$var"
@@ -308,7 +308,7 @@ echo "Redefine common keys to SDL keysyms"
echo "MENU and BACK hardware keys and TOUCHSCREEN virtual 'key' are available on all devices, other keys may be absent"
echo "SEARCH and CALL by default return same keycode as DPAD_CENTER - one of those keys is available on most devices"
echo "Use word NO_REMAP if you want to preserve native functionality for certain key "
echo "TOUCHSCREEN DPAD_CENTER VOLUMEUP VOLUMEDOWN MENU BACK CAMERA ENTER DEL SEARCH CALL - Java keycodes"
echo "TOUCHSCREEN DPAD_CENTER/SEARCH VOLUMEUP VOLUMEDOWN MENU BACK CAMERA - Java keycodes"
echo "$RedefinedKeys - current SDL keycodes"
echo -n ": "
read var

View File

@@ -16,19 +16,10 @@ Requested features
- Split Settings.java into several files
- Option to skip startup config screen entirely, or to skip it on first run,
separate option to hide each SDL config menu entry
- Possibility to redefine initial SDL config in Settings.java
- Show/hide screen controls with longpress on Text Edit button.
- There's no double-buffered SW mode, only single-buffered
- Support of libjnigraphics (it will disable on-screen keyboard, only SW SDL screen surface supported)
- Update screen keyboard text input API
- Floating on-screen joystick - initially invisible, it appears when you touch the screen,
centered on your finger, then it slides with your finger if you bump the joystick edge.
@@ -36,8 +27,6 @@ Requested features
- Control screen brightness with SDL_SetGamma()
- Adjust Android media volume with some SDL keycode, so it can be mapped to Volume keys
- Zoom in-out whole screen in SW mode with some SDL key -
much like the "On-screen magnifying glass" feature (lazy porter's golden hammer)
@@ -56,6 +45,3 @@ Requested features
plus VideoView will contain some buffer to ensure the playback is smooth,
so the data on your TV will lag halfsecond behind the data on the device screen.
- Somehow make this port into main libSDL repository - that's rather impossible,
because the original sources are modified badly, plus Java code does not fit anywhere.

View File

@@ -6,7 +6,8 @@ NDKBUILDPATH=$PATH
export `grep "AppFullName=" AndroidAppSettings.cfg`
if ( grep "package $AppFullName;" project/src/Globals.java > /dev/null && \
[ "`readlink AndroidAppSettings.cfg`" -ot "project/src/Globals.java" ] && \
[ -z "`find project/java/* -cnewer project/src/Globals.java`" ] ) ; then true ; else
[ -z "`find project/java/* -cnewer project/src/Globals.java`" ] && \
[ -z "`find project/jni/application/src/AndroidData/* -cnewer project/src/Globals.java`" ] ) ; then true ; else
./ChangeAppSettings.sh -a
sleep 1
touch project/src/Globals.java
@@ -32,6 +33,6 @@ cd project && env PATH=$NDKBUILDPATH nice -n19 ndk-build -j4 V=1 && \
cp jni/application/src/libapplication.so libs/armeabi && \
`which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi/libapplication.so \
|| true ; } && \
ant debug && \
test -z "$1" && cd bin && adb uninstall `grep AppFullName ../../AndroidAppSettings.cfg | sed 's/.*=//'` && \
adb install -r DemoActivity-debug.apk
ant debug # && \
# test -z "$1" && cd bin && adb uninstall `grep AppFullName ../../AndroidAppSettings.cfg | sed 's/.*=//'` && \
# adb install -r DemoActivity-debug.apk

View File

@@ -10,7 +10,7 @@ VideoDepthBpp=16
NeedDepthBuffer=n
NeedStencilBuffer=n
NeedGles2=n
SwVideoMode=y
SwVideoMode=n
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
CompatibilityHacks=n

View File

@@ -19,7 +19,51 @@
#include "SDL.h"
#include "SDL_image.h"
#include "ballfield.h"
/*----------------------------------------------------------
Definitions...
----------------------------------------------------------*/
#define BALLS 3000
#define COLORS 2
typedef struct
{
Sint32 x, y, z; /* Position */
Uint32 c; /* Color */
} point_t;
/*
* Ballfield
*/
typedef struct
{
point_t points[BALLS];
SDL_Rect *frames;
SDL_Surface *gfx[COLORS];
int use_alpha;
} ballfield_t;
/*
* Size of the screen in pixels
*/
#define SCREEN_W 800
#define SCREEN_H 480
/*
* Size of the biggest ball image in pixels
*
* Balls are scaled down and *packed*, one pixel
* smaller for each frame down to 1x1. The actual
* image width is (obviously...) the same as the
* width of the first frame.
*/
#define BALL_W 32
#define BALL_H 32
@@ -318,6 +362,7 @@ void ballfield_render(ballfield_t *bf, SDL_Surface *screen)
*/
void tiled_back(SDL_Surface *back, SDL_Surface *screen, int xo, int yo)
{
/*
int x, y;
SDL_Rect r;
if(xo < 0)
@@ -333,6 +378,15 @@ void tiled_back(SDL_Surface *back, SDL_Surface *screen, int xo, int yo)
r.y = y;
SDL_BlitSurface(back, NULL, screen, &r);
}
*/
SDL_Rect r;
xo %= back->w/8;
yo %= back->h/8;
r.x = xo - back->w/2 + screen->w/2;
r.y = yo - back->h/2 + screen->h/2;
r.w = back->w;
r.h = back->h;
SDL_BlitSurface(back, NULL, screen, &r);
}
@@ -349,7 +403,7 @@ int main(int argc, char* argv[])
SDL_Surface *back, *logo, *font;
SDL_Event event;
int bpp = 16,
flags = SDL_DOUBLEBUF | SDL_SWSURFACE,
flags = SDL_DOUBLEBUF | SDL_HWSURFACE,
alpha = 1;
int x_offs = 0, y_offs = 0;
long tick,
@@ -384,7 +438,7 @@ int main(int argc, char* argv[])
bpp = atoi(&argv[i][1]);
}
screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, bpp, 0 /*flags*/);
screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, bpp, flags);
if(!screen)
{
fprintf(stderr, "Failed to open screen!\n");
@@ -417,7 +471,7 @@ int main(int argc, char* argv[])
/*
* Load background image
*/
temp_image = IMG_Load("redbluestars.png");
temp_image = IMG_Load("sun.gif");
if(!temp_image)
{
fprintf(stderr, "Could not load background!\n");
@@ -435,7 +489,7 @@ int main(int argc, char* argv[])
fprintf(stderr, "Could not load logo!\n");
exit(-1);
}
SDL_SetColorKey(temp_image, SDL_SRCCOLORKEY|SDL_RLEACCEL,
SDL_SetColorKey(temp_image, SDL_SRCCOLORKEY,
SDL_MapRGB(temp_image->format, 255, 0, 255));
logo = SDL_DisplayFormat(temp_image);
SDL_FreeSurface(temp_image);
@@ -449,7 +503,7 @@ int main(int argc, char* argv[])
fprintf(stderr, "Could not load font!\n");
exit(-1);
}
SDL_SetColorKey(temp_image, SDL_SRCCOLORKEY|SDL_RLEACCEL,
SDL_SetColorKey(temp_image, SDL_SRCCOLORKEY,
SDL_MapRGB(temp_image->format, 255, 0, 255));
font = SDL_DisplayFormat(temp_image);
SDL_FreeSurface(temp_image);

View File

@@ -1,61 +0,0 @@
/*
* "Ballfield"
*
* (C) David Olofson <david@olofson.net>, 2002
*
* This software is released under the terms of the GPL.
*
* Contact author for permission if you want to use this
* software, or work derived from it, under other terms.
*/
#ifndef _BALLFIELD_H_
#define _BALLFIELD_H_
#include "SDL.h"
/*----------------------------------------------------------
Definitions...
----------------------------------------------------------*/
#define BALLS 200
#define COLORS 2
typedef struct
{
Sint32 x, y, z; /* Position */
Uint32 c; /* Color */
} point_t;
/*
* Ballfield
*/
typedef struct
{
point_t points[BALLS];
SDL_Rect *frames;
SDL_Surface *gfx[COLORS];
int use_alpha;
} ballfield_t;
/*
* Size of the screen in pixels
*/
#define SCREEN_W 320
#define SCREEN_H 240
/*
* Size of the biggest ball image in pixels
*
* Balls are scaled down and *packed*, one pixel
* smaller for each frame down to 1x1. The actual
* image width is (obviously...) the same as the
* width of the first frame.
*/
#define BALL_W 32
#define BALL_H 32
#endif /* _BALLFIELD_H_ */

View File

@@ -31,8 +31,8 @@ StartupMenuButtonTimeout=3000
HiddenMenuOptions='KeyboardConfigMainMenu ScreenKeyboardThemeConfig ScreenKeyboardTransparencyConfig'
FirstStartMenuOptions=''
MultiABI=n
AppVersionCode=250517
AppVersionName="2505.17"
AppVersionCode=252517
AppVersionName="2525.17"
CompiledLibraries="sdl_net sdl_mixer sdl_image sdl_ttf png intl"
CustomBuildScript=n
AppCflags='-finline-functions -O2 -DWITH_ZLIB -DWITH_MIXER -DWITH_XML -DWITH_IMAGE -DWITH_TTF -DWITH_AI=simple -DWITH_NET'

View File

@@ -1,16 +1,22 @@
# The application settings for Android libSDL port
AppSettingVersion=16
AppSettingVersion=17
LibSdlVersion=1.2
AppName="Ur-Quan Masters"
AppFullName=com.sourceforge.sc2
ScreenOrientation=h
InhibitSuspend=n
AppDataDownloadUrl="Game data is 14 Mb|https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/sc2-data-3.zip/download^3DO remixed music (19 Mb) - enable it in Setup->Sound Options->3DO Remixes|:addons/3domusic/3domusic.zip:https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3domusic.zip/download^UQM music remix pack (150 Mb) - enable it in Setup->Sound Options->UQM Remixes|:addons/remix/remix.zip:https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/remix.zip/download^3DO voice (115 Mb) - go to Setup->Sound Options and increase Voice volume from zero|:addons/3dovoice/3dovoice.zip:https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovoice.zip/download^Russian translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/russian.zip/download^Deutsch translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/deutsch.zip/download^Spanish translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/spanish.zip/download^Slovak translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/slovak.zip/download^Finnish translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/finnish.zip/download^3DO video support - after installing this pack copy all files from|https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^your 3DO Star Control II game CD from 'duckart' dir to the SD card to dir|https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^'app-data/com.sourceforge.sc2/addons/3dovideo', to extract files from 3DO disk use|https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^'3DO Commander' or 'uncd-rom' apps from http://madroms.free.fr/3do/|https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^Then from the game change 'Setup->PC/3DO compat->Cutscenes' to Movies, and restart game|https://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download"
AppDataDownloadUrl="Game data (15 Mb)|http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/sc2-data-5.zip/download^3DO remixed music (19 Mb) - enable it in Setup->Sound Options->3DO Remixes|:addons/3domusic/3domusic.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3domusic.zip/download^UQM music remix pack (150 Mb) - enable it in Setup->Sound Options->UQM Remixes|:addons/remix/remix.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/remix.zip/download^3DO voice (115 Mb) - go to Setup->Sound Options and increase Voice volume from zero|:addons/3dovoice/3dovoice.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovoice.zip/download^Russian translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/russian.zip/download^Deutsch translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/deutsch.zip/download^Spanish translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/spanish.zip/download^Slovak translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/slovak.zip/download^Finnish translation|:addons/lang/shadow-content/lang.zip:http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/translations/2/finnish.zip/download^3DO video support - after installing this pack copy all files from|http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^your 3DO Star Control II game CD from 'duckart' dir to the SD card to dir|http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^'app-data/com.sourceforge.sc2/addons/3dovideo', to extract files from 3DO disk use|http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^'3DO Commander' or 'uncd-rom' apps from http://madroms.free.fr/3do/|http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download^Then from the game change 'Setup->PC/3DO compat->Cutscenes' to Movies, and restart game|http://sourceforge.net/projects/libsdl-android/files/Ur-Quan%20Masters/3dovideo.zip/download"
VideoDepthBpp=16
NeedDepthBuffer=n
NeedStencilBuffer=n
NeedGles2=n
SwVideoMode=y
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
NeedDepthBuffer=n
CompatibilityHacks=n
AppUsesMouse=n
AppNeedsTwoButtonMouse=n
ForceRelativeMouseMode=n
AppNeedsArrowKeys=y
AppNeedsTextInput=y
AppUsesJoystick=y
@@ -21,14 +27,16 @@ RedefinedKeys="RETURN RSHIFT KP_PLUS KP_MINUS RCTRL F10"
AppTouchscreenKeyboardKeysAmount=2
AppTouchscreenKeyboardKeysAmountAutoFire=0
RedefinedKeysScreenKb="RETURN RSHIFT KP_PLUS KP_MINUS RCTRL F10"
StartupMenuButtonTimeout=3000
HiddenMenuOptions=''
FirstStartMenuOptions=''
MultiABI=n
AppVersionCode=06920
AppVersionName="0.6.9.20"
AppVersionCode=07020
AppVersionName="0.7.0.20"
CompiledLibraries="sdl_image tremor ogg"
CustomBuildScript=n
AppCflags='-O3 -DTHREADLIB_SDL=1 -DTIMELIB=SDL -DOVCODEC_TREMOR=1 -DNETPLAY=1 -DHAVE_REGEX=1 -DHAVE_GETOPT_LONG=1 -DHAVE_ZIP=1 -DHAVE_JOYSTICK=1'
AppCflags='-O3 -DTHREADLIB_SDL=1 -DTIMELIB=SDL -DOVCODEC_TREMOR=1 -DNETPLAY=1 -DHAVE_GETOPT_LONG=1 -DHAVE_ZIP=1 -DHAVE_JOYSTICK=1'
AppLdflags=''
AppSubdirsBuild=''
AppUseCrystaXToolchain=n
AppSubdirsBuild='src src/regex src/libs/* src/uqm/*'
AppCmdline='uqm --addon lang'
ReadmeText='^You may press "Home" now - the data will be downloaded in background'

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
../../../../../sc2/sc2/src/

View File

@@ -1,20 +0,0 @@
uqm_SUBDIRS="libs res uqm"
if [ "$uqm_HAVE_GETOPT_LONG" = 0 ]; then
uqm_SUBDIRS="$uqm_SUBDIRS getopt"
fi
case "$HOST_SYSTEM" in
Darwin)
uqm_SUBDIRS="$uqm_SUBDIRS darwin"
;;
esac
if [ "$uqm_HAVE_REGEX" = 0 ]; then
uqm_SUBDIRS="$uqm_SUBDIRS regex"
fi
uqm_CFILES="options.c port.c uqm.c"
test_CFILES=test.c

View File

@@ -1,21 +0,0 @@
/* This file contains some compile-time configuration options.
*/
#ifdef _MSC_VER
/* In this case, build.sh is not run to generate a config file, so
* we use a default file config_vc6.h instead.
* If you want anything else than the defaults, you'll have to edit
* that file manually. */
# include "config_vc6.h"
#elif defined(__SYMBIAN32__)
# include "symbian/config.h"
#elif defined (__MINGW32__) || defined (__CYGWIN__)
/* If we're compiling on MS Windows using build.sh, use
* config_win.h, generated from src/config_win.h.in. */
# include "config_win.h"
#else
/* If we're compiling in unix, use config_unix.h, generated from
* src/config_unix.h.in by build.sh. */
# include "config_unix.h"
#endif

View File

@@ -1,67 +0,0 @@
/* This file contains some compile-time configuration options for *nix
* systems.
* config_unix.h is generated from config_unix.h.in by build.sh
* When building on MS Windows using build.sh (MinGW, Cygwin),
* config_win.h is generated from src/config_win.h.in.
* When using MSVC on MS Windows, you'll have to edit src/msvc++/config.h
* manually if you want anything else than the defaults.
*/
#ifndef _CONFIG_UNIX_H
#define _CONFIG_UNIX_H
/* Directory where the UQM game data is located */
#define CONTENTDIR ""
/* Directory where game data will be stored */
#define USERDIR "config/"
/* Directory where config files will be stored */
#define CONFIGDIR USERDIR
/* Directory where supermelee teams will be stored */
#define MELEEDIR "teams/"
/* Directory where save games will be stored */
#define SAVEDIR "save/"
/* Defined if words are stored with the most significant byte first */
#ifdef __ARMEL__
#undef WORDS_BIGENDIAN
#endif
/* Defined if your system has readdir_r of its own */
#define HAVE_READDIR_R 1
/* Defined if your system has setenv of its own */
#ifndef HAVE_SETENV
#define HAVE_SETENV 1
#endif
/* Defined if your system has strupr of its own */
#undef HAVE_STRUPR
/* Defined if your system has strcasecmp of its own */
#define HAVE_STRCASECMP_UQM 1
// Not using "HAVE_STRCASECMP" as that conflicts with SDL.
/* Defined if your system has stricmp of its own */
#undef HAVE_STRICMP
/* Defined if your system has getopt_long */
#define HAVE_GETOPT_LONG 1
/* Defined if your system has iswgraph of its own*/
#define HAVE_ISWGRAPH 1
/* Defined if your system has wchar_t of its own */
#define HAVE_WCHAR_T 1
/* Defined if your system has wint_t of its own */
#define HAVE_WINT_T 1
/* Defined if your system has _Bool of its own */
#define HAVE__BOOL 1
#endif /* _CONFIG_UNIX_H */

View File

@@ -1,63 +0,0 @@
/* This file contains some compile-time configuration options for *nix
* systems.
* config_unix.h is generated from config_unix.h.in by build.sh
* When building on MS Windows using build.sh (MinGW, Cygwin),
* config_win.h is generated from src/config_win.h.in.
* When using MSVC on MS Windows, you'll have to edit src/msvc++/config.h
* manually if you want anything else than the defaults.
*/
#ifndef _CONFIG_UNIX_H
#define _CONFIG_UNIX_H
/* Directory where the UQM game data is located */
#define CONTENTDIR "@CONTENTDIR@"
/* Directory where game data will be stored */
#define USERDIR "~/.uqm/"
/* Directory where config files will be stored */
#define CONFIGDIR USERDIR
/* Directory where supermelee teams will be stored */
#define MELEEDIR "${UQM_CONFIG_DIR}/teams/"
/* Directory where save games will be stored */
#define SAVEDIR "${UQM_CONFIG_DIR}/save/"
/* Defined if words are stored with the most significant byte first */
@WORDS_BIGENDIAN@
/* Defined if your system has readdir_r of its own */
@HAVE_READDIR_R@
/* Defined if your system has setenv of its own */
@HAVE_SETENV@
/* Defined if your system has strupr of its own */
@HAVE_STRUPR@
/* Defined if your system has strcasecmp of its own */
@HAVE_STRCASECMP_UQM@
// Not using "HAVE_STRCASECMP" as that conflicts with SDL.
/* Defined if your system has stricmp of its own */
@HAVE_STRICMP@
/* Defined if your system has getopt_long */
@HAVE_GETOPT_LONG@
/* Defined if your system has iswgraph of its own*/
@HAVE_ISWGRAPH@
/* Defined if your system has wchar_t of its own */
@HAVE_WCHAR_T@
/* Defined if your system has wint_t of its own */
@HAVE_WINT_T@
/* Defined if your system has _Bool of its own */
@HAVE__BOOL@
#endif /* _CONFIG_UNIX_H */

View File

@@ -1,61 +0,0 @@
/* This file contains some compile-time configuration options for MS Windows
* systems when building using MSVC.
* Change the values below if you want anything other than the defaults.
* For *nix systems, config_unix.h is used, which is generated by build.sh
* from src/config_unix.h.in.
* When building on MS Windows using build.sh (MinGW, Cygwin),
* config_win.h is generated from src/config_win.h.in.
*/
#ifndef _CONFIG_H
#define _CONFIG_H
/* Directory where the UQM game data is located */
#define CONTENTDIR "../content/"
/* Directory where game data will be stored */
//#define USERDIR "../userdata/"
#define USERDIR "%APPDATA%/uqm/"
/* Directory where config files will be stored */
#define CONFIGDIR USERDIR
/* Directory where supermelee teams will be stored */
#define MELEEDIR "%UQM_CONFIG_DIR%/teams/"
/* Directory where save games will be stored */
#define SAVEDIR "%UQM_CONFIG_DIR%/save/"
/* Define if words are stored with the most significant byte first */
#undef WORDS_BIGENDIAN
/* Defined if your system has readdir_r of its own */
#undef HAVE_READDIR_R
/* Defined if your system has setenv of its own */
#undef HAVE_SETENV
/* Defined if your system has strupr of its own */
#define HAVE_STRUPR
/* Defined if your system has strcasecmp of its own */
#undef HAVE_STRCASECMP_UQM
// Not using "HAVE_STRCASECMP" as that conflicts with SDL.
/* Defined if your system has stricmp of its own */
#define HAVE_STRICMP
/* Defined if your system has getopt_long */
#undef HAVE_GETOPT_LONG
/* Defined if your system has iswgraph of its own*/
#define HAVE_ISWGRAPH
/* Defined if your system has wchar_t of its own */
#define HAVE_WCHAR_T
/* Defined if your system has wint_t of its own */
#define HAVE_WINT_T
#endif /* _CONFIG_H */

View File

@@ -1,65 +0,0 @@
/* This file contains some compile-time configuration options for MS Windows
* systems when building using build.sh (MinGW, Cygwin).
* config_win.h is generated from src/config_win.h.in by build.sh
* For building using MSVC, you'll have to edit src/msvc++/config.h manually
* if you want anything else than the defaults.
* For *nix systems, config_unix.h is used, which is generated by build.sh
* from src/config_unix.h.in.
*/
#ifndef _CONFIG_WIN_H
#define _CONFIG_WIN_H
/* Directory where the UQM game data is located */
#define CONTENTDIR "../content/"
/* Directory where game data will be stored */
//#define USERDIR "../userdata/"
#define USERDIR "%APPDATA%/uqm/"
/* Directory where config files will be stored */
#define CONFIGDIR USERDIR
/* Directory where supermelee teams will be stored */
#define MELEEDIR "%UQM_CONFIG_DIR%/teams/"
/* Directory where save games will be stored */
#define SAVEDIR "%UQM_CONFIG_DIR%/save/"
/* Defined if words are stored with the most significant byte first */
@WORDS_BIGENDIAN@
/* Defined if your system has readdir_r of its own */
@HAVE_READDIR_R@
/* Defined if your system has setenv of its own */
@HAVE_SETENV@
/* Defined if your system has strupr of its own */
@HAVE_STRUPR@
/* Defined if your system has strcasecmp of its own */
@HAVE_STRCASECMP_UQM@
// Not using "HAVE_STRCASECMP" as that conflicts with SDL.
/* Defined if your system has stricmp of its own */
@HAVE_STRICMP@
/* Defined if your system has getopt_long */
@HAVE_GETOPT_LONG@
/* Defined if your system has iswgraph of its own*/
@HAVE_ISWGRAPH@
/* Defined if your system has wchar_t of its own */
@HAVE_WCHAR_T@
/* Defined if your system has wint_t of its own */
@HAVE_WINT_T@
/* Defined if your system has _Bool of its own */
@HAVE__BOOL@
#endif /* _CONFIG_WIN_H */

View File

@@ -1,127 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
/*
* Endian swapping, taken from SDL-1.2.5 sources and modified
* Original copyright (C) Sam Lantinga
*/
#ifndef _ENDIAN_UQM_H
#define _ENDIAN_UQM_H
#include "config.h"
#include "types.h"
#if defined (__APPLE__) && defined (__GNUC__)
// When using the MacOS gcc compiler to build universal binaries,
// each file will be compiled once for each platform.
// This means that checking endianness beforehand from build.sh will not do,
// but fortunately, gcc defines __BIG_ENDIAN__ or __LITTLE_ENDIAN__ on
// this platform.
# if defined(__BIG_ENDIAN__)
# undef WORDS_BIGENDIAN
# define WORDS_BIGENDIAN
# elif defined(__LITTLE_ENDIAN__)
# undef WORDS_BIGENDIAN
# else
// Neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__ is defined.
// Fallback to using the build.sh defined value.
# endif
#endif /* __APPLE__ */
#if defined(_MSC_VER) || defined(__BORLANDC__) || \
defined(__DMC__) || defined(__SC__) || \
defined(__WATCOMC__) || defined(__LCC__)
#ifndef __inline__
#define __inline__ __inline
#endif
#endif
/* The macros used to swap values */
/* Try to use superfast macros on systems that support them */
#ifdef linux
#include <endian.h>
#ifdef __arch__swab16
#define UQM_Swap16 __arch__swab16
#endif
#ifdef __arch__swab32
#define UQM_Swap32 __arch__swab32
#endif
#endif /* linux */
/* Use inline functions for compilers that support them, and static
functions for those that do not. Because these functions become
static for compilers that do not support inline functions, this
header should only be included in files that actually use them.
*/
#ifndef UQM_Swap16
static __inline__ uint16 UQM_Swap16(uint16 D)
{
return((D<<8)|(D>>8));
}
#endif
#ifndef UQM_Swap32
static __inline__ uint32 UQM_Swap32(uint32 D)
{
return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
}
#endif
#ifdef UQM_INT64
#ifndef UQM_Swap64
static __inline__ uint64 UQM_Swap64(uint64 val)
{
uint32 hi, lo;
/* Separate into high and low 32-bit values and swap them */
lo = (uint32)(val&0xFFFFFFFF);
val >>= 32;
hi = (uint32)(val&0xFFFFFFFF);
val = UQM_Swap32(lo);
val <<= 32;
val |= UQM_Swap32(hi);
return(val);
}
#endif
#else
#ifndef UQM_Swap64
/* This is mainly to keep compilers from complaining in SDL code.
If there is no real 64-bit datatype, then compilers will complain about
the fake 64-bit datatype that SDL provides when it compiles user code.
*/
#define UQM_Swap64(X) (X)
#endif
#endif /* UQM_INT64 */
/* Byteswap item from the specified endianness to the native endianness
* or vice versa.
*/
#ifndef WORDS_BIGENDIAN
#define UQM_SwapLE16(X) (X)
#define UQM_SwapLE32(X) (X)
#define UQM_SwapLE64(X) (X)
#define UQM_SwapBE16(X) UQM_Swap16(X)
#define UQM_SwapBE32(X) UQM_Swap32(X)
#define UQM_SwapBE64(X) UQM_Swap64(X)
#else
#define UQM_SwapLE16(X) UQM_Swap16(X)
#define UQM_SwapLE32(X) UQM_Swap32(X)
#define UQM_SwapLE64(X) UQM_Swap64(X)
#define UQM_SwapBE16(X) (X)
#define UQM_SwapBE32(X) (X)
#define UQM_SwapBE64(X) (X)
#endif
#endif /* _ENDIAN_H */

View File

@@ -1,14 +0,0 @@
uqm_SUBDIRS="callback decomp file graphics heap input list math memory
resource sound strings task threads time uio video log"
if [ -n "$uqm_USE_INTERNAL_MIKMOD" ]; then
uqm_SUBDIRS="$uqm_SUBDIRS mikmod"
fi
if [ -n "$uqm_NETPLAY" ]; then
uqm_SUBDIRS="$uqm_SUBDIRS network"
fi
#if [ "$DEBUG" = 1 ]; then
# uqm_SUBDIRS="$UQM_SUBDIRS debug"
#fi

View File

@@ -1,2 +0,0 @@
#include "callback/alarm.h"

View File

@@ -1,2 +0,0 @@
#include "callback/callback.h"

View File

@@ -1,2 +0,0 @@
uqm_CFILES="alarm.c callback.c"

View File

@@ -1,134 +0,0 @@
/*
* Copyright 2006 Serge van den Boom <svdb@stack.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "alarm.h"
#include "libs/heap.h"
#include <assert.h>
#include <stdlib.h>
Heap *alarmHeap;
static inline Alarm *
Alarm_alloc(void) {
return malloc(sizeof (Alarm));
}
static inline void
Alarm_free(Alarm *alarm) {
free(alarm);
}
static inline int
AlarmTime_compare(const AlarmTime t1, const AlarmTime t2) {
if (t1 < t2)
return -1;
if (t2 > t2)
return 1;
return 0;
}
static int
Alarm_compare(const Alarm *a1, const Alarm *a2) {
return AlarmTime_compare(a1->time, a2->time);
}
void
Alarm_init(void) {
assert(alarmHeap == NULL);
alarmHeap = Heap_new((HeapValue_Comparator) Alarm_compare,
4, 4, 0.8);
}
void
Alarm_uninit(void) {
assert(alarmHeap != NULL);
while (Heap_hasMore(alarmHeap)) {
Alarm *alarm = (Alarm *) Heap_pop(alarmHeap);
Alarm_free(alarm);
}
Heap_delete(alarmHeap);
alarmHeap = NULL;
}
static inline AlarmTime
AlarmTime_nowMS(void) {
return SDL_GetTicks();
}
Alarm *
Alarm_addRelativeMs(Uint32 ms, AlarmCallback callback,
AlarmCallbackArg arg) {
Alarm *alarm;
assert(alarmHeap != NULL);
alarm = Alarm_alloc();
alarm->time = AlarmTime_nowMS() + ms;
alarm->callback = callback;
alarm->arg = arg;
Heap_add(alarmHeap, (HeapValue *) alarm);
return alarm;
}
void
Alarm_remove(Alarm *alarm) {
assert(alarmHeap != NULL);
Heap_remove(alarmHeap, (HeapValue *) alarm);
Alarm_free(alarm);
}
// It is safe to call this function again from inside a callback function
// that it called. It should not be called from multiple threads at once.
void
Alarm_process(void) {
AlarmTime now;
assert(alarmHeap != NULL);
now = AlarmTime_nowMS();
while (Heap_hasMore(alarmHeap)) {
Alarm *alarm = (Alarm *) Heap_first(alarmHeap);
if (now < alarm->time)
break;
Heap_pop(alarmHeap);
alarm->callback(alarm->arg);
Alarm_free(alarm);
}
}
Uint32
Alarm_timeBeforeNextMs(void) {
Alarm *alarm;
if (!Heap_hasMore(alarmHeap))
return UINT32_MAX;
alarm = (Alarm *) Heap_first(alarmHeap);
return alarmTimeToMsUint32(alarm->time);
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2006 Serge van den Boom <svdb@stack.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*/
#ifndef _ALARM_H
#define _ALARM_H
#include "port.h"
#include "types.h"
#include SDL_INCLUDE(SDL.h)
typedef Uint32 AlarmTime;
static inline Uint32
alarmTimeToMsUint32(AlarmTime time) {
return (Uint32) time;
}
typedef struct Alarm Alarm;
typedef void *AlarmCallbackArg;
typedef void (*AlarmCallback)(AlarmCallbackArg arg);
struct Alarm {
size_t index;
// For the HeapValue 'base struct'.
AlarmTime time;
AlarmCallback callback;
AlarmCallbackArg arg;
};
void Alarm_init(void);
void Alarm_uninit(void);
Alarm *Alarm_addRelativeMs(Uint32 ms, AlarmCallback callback,
AlarmCallbackArg arg);
void Alarm_remove(Alarm *alarm);
void Alarm_process(void);
Uint32 Alarm_timeBeforeNextMs(void);
#endif /* _ALARM_H */

View File

@@ -1,173 +0,0 @@
/*
* Copyright 2006 Serge van den Boom <svdb@stack.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "types.h"
#include <assert.h>
#include <stdlib.h>
#include <sys/types.h>
typedef struct CallbackLink CallbackLink;
#define CALLBACK_INTERNAL
#include "callback.h"
struct CallbackLink {
CallbackLink *next;
CallbackFunction callback;
CallbackArg arg;
};
static CallbackLink *callbacks;
static CallbackLink **callbacksEnd;
static CallbackLink *const *callbacksProcessEnd;
static inline void
CallbackList_lock(void) {
// TODO
// Necessary for reentrant operation
}
static inline void
CallbackList_unlock(void) {
// TODO
// Necessary for reentrant operation
}
#if 0
static inline bool
CallbackList_isLocked(void) {
// TODO
}
#endif
void
Callback_init(void) {
callbacks = NULL;
callbacksEnd = &callbacks;
callbacksProcessEnd = &callbacks;
}
// Callbacks are guaranteed to be called in the order that they are queued.
CallbackID
Callback_add(CallbackFunction callback, CallbackArg arg) {
CallbackLink *link = malloc(sizeof (CallbackLink));
link->callback = callback;
link->arg = arg;
link->next = NULL;
CallbackList_lock();
*callbacksEnd = link;
callbacksEnd = &link->next;
CallbackList_unlock();
return (CallbackID) link;
}
static void
CallbackLink_delete(CallbackLink *link) {
free(link);
}
// Pre: CallbackList is locked.
static CallbackLink **
CallbackLink_find(CallbackLink *link) {
CallbackLink **ptr;
//assert(CallbackList_isLocked());
for (ptr = &callbacks; *ptr != NULL; ptr = &(*ptr)->next) {
if (*ptr == link)
return ptr;
}
return NULL;
}
bool
Callback_remove(CallbackID id) {
CallbackLink *link = (CallbackLink *) id;
CallbackLink **linkPtr;
CallbackList_lock();
linkPtr = CallbackLink_find(link);
if (linkPtr == NULL) {
CallbackList_unlock();
return false;
}
if (callbacksEnd == &(*linkPtr)->next)
callbacksEnd = linkPtr;
if (callbacksProcessEnd == &(*linkPtr)->next)
callbacksProcessEnd = linkPtr;
*linkPtr = (*linkPtr)->next;
CallbackList_unlock();
CallbackLink_delete(link);
return true;
}
static inline void
CallbackLink_doCallback(CallbackLink *link) {
(link->callback)(link->arg);
}
// Call all queued callbacks currently in the queue. Callbacks queued
// from inside the called functions will not be processed until the next
// call of Callback_process().
// It is allowed to remove callbacks from inside the called functions.
// NB: Callback_process() must never be called from more than one thread
// at the same time. It's the only sensible way to ensure that the
// callbacks are called in the order in which they were queued.
// It is however allowed to call Callback_process() from inside the
// callback function called by Callback_process() itself.
void
Callback_process(void) {
CallbackLink *link;
// We set 'callbacksProcessEnd' to callbacksEnd. Callbacks added
// from inside a callback function will be placed after
// callbacksProcessEnd, and will hence not be processed this
// call of Callback_process().
CallbackList_lock();
callbacksProcessEnd = callbacksEnd;
CallbackList_unlock();
for (;;) {
CallbackList_lock();
if (callbacksProcessEnd == &callbacks) {
CallbackList_unlock();
break;
}
assert(callbacks != NULL);
// If callbacks == NULL, then callbacksProcessEnd == &callbacks
link = callbacks;
callbacks = link->next;
if (callbacksEnd == &link->next)
callbacksEnd = &callbacks;
if (callbacksProcessEnd == &link->next)
callbacksProcessEnd = &callbacks;
CallbackList_unlock();
CallbackLink_doCallback(link);
CallbackLink_delete(link);
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2006 Serge van den Boom <svdb@stack.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*/
#ifndef _CALLBACK_H
#define _CALLBACK_H
#include "types.h"
#ifdef CALLBACK_INTERNAL
typedef CallbackLink *CallbackID;
#else
typedef void *CallbackID;
// Uniquely identifies a queued callback.
#endif
#define CallbackID_invalid ((CallbackID ) NULL)
typedef void *CallbackArg;
typedef void (*CallbackFunction)(CallbackArg arg);
void Callback_init(void);
CallbackID Callback_add(CallbackFunction callback, CallbackArg arg);
bool Callback_remove(CallbackID id);
void Callback_process(void);
#endif /* _CALLBACK_H */

View File

@@ -1,24 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
* Nota bene: later versions of the GNU General Public License do not apply
* to this program.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*
*/
#ifndef _CDPLIB_H
#define _CDPLIB_H
#include "cdp/cdp.h"
#endif /* _CDPLIB_H */

View File

@@ -1,89 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _COMPILER_H
#define _COMPILER_H
#include "types.h"
typedef uint8 BYTE;
typedef uint8 UBYTE;
typedef sint8 SBYTE;
typedef uint16 UWORD;
typedef sint16 SWORD;
typedef uint32 DWORD;
typedef sint32 SDWORD;
typedef UWORD COUNT;
typedef SWORD SIZE;
typedef char UNICODE;
typedef enum
{
FALSE = 0,
TRUE
} BOOLEAN;
typedef void (*PVOIDFUNC) (void);
typedef BOOLEAN (*PBOOLFUNC) (void);
typedef BYTE (*PBYTEFUNC) (void);
typedef UWORD (*PUWORDFUNC) (void);
typedef SWORD (*PSWORDFUNC) (void);
typedef DWORD (*PDWORDFUNC) (void);
#define MAKE_BYTE(lo, hi) ((BYTE) (((BYTE) (hi) << (BYTE) 4) | (BYTE) (lo)))
#define LONIBBLE(x) ((BYTE) ((BYTE) (x) & (BYTE) 0x0F))
#define HINIBBLE(x) ((BYTE) ((BYTE) (x) >> (BYTE) 4))
#define MAKE_WORD(lo, hi) ((UWORD) ((BYTE) (hi) << 8) | (BYTE) (lo))
#define LOBYTE(x) ((BYTE) ((UWORD) (x)))
#define HIBYTE(x) ((BYTE) ((UWORD) (x) >> 8))
#define MAKE_DWORD(lo, hi) (((DWORD) (hi) << 16) | (UWORD) (lo))
#define LOWORD(x) ((UWORD) ((DWORD) (x)))
#define HIWORD(x) ((UWORD) ((DWORD) (x) >> 16))
// To be moved to port.h:
// _ALIGNED_ANY specifies an alignment suitable for any type
// _ALIGNED_ON specifies a caller-supplied alignment (should be a power of 2)
#if defined(__GNUC__)
# define _PACKED __attribute__((packed))
# define _ALIGNED_ANY __attribute__((aligned))
# define _ALIGNED_ON(bytes) __attribute__((aligned(bytes)))
#elif defined(_MSC_VER)
# define _ALIGNED_ANY
//# define _ALIGNED_ON(bytes) __declspec(align(bytes))
// __declspec(align(bytes)) expects a constant. 'sizeof (type)'
// will not do. This is something that needs some attention,
// once we find someone with a 64 bits Windows machine.
// Leaving it alone for now.
# define _PACKED
# define _ALIGNED_ON(bytes)
#elif defined(__ARMCC__)
# define _PACKED __attribute__((packed))
# define _ALIGNED_ANY __attribute__((aligned))
# define _ALIGNED_ON(bytes) __attribute__((aligned(bytes)))
#elif defined(__WINSCW__)
# define _PACKED
# define _ALIGNED_ANY
# define _ALIGNED_ON(bytes)
#endif
#endif /* _COMPILER_H */

View File

@@ -1,48 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _DECLIB_H
#define _DECLIB_H
#include "libs/compiler.h"
typedef struct _LZHCODE_DESC* DECODE_REF;
enum
{
FILE_STREAM = 0,
MEMORY_STREAM
};
typedef BYTE STREAM_TYPE;
enum
{
STREAM_READ = 0,
STREAM_WRITE
};
typedef BYTE STREAM_MODE;
extern DECODE_REF copen (void *InStream, STREAM_TYPE SType,
STREAM_MODE SMode);
extern DWORD cclose (DECODE_REF DecodeRef);
extern void cfilelength (DECODE_REF DecodeRef, DWORD *pfilelen);
extern COUNT cread (void *pStr, COUNT size, COUNT count,
DECODE_REF DecodeRef);
extern COUNT cwrite (const void *pStr, COUNT size, COUNT count,
DECODE_REF DecodeRef);
#endif /* _DECLIB_H */

View File

@@ -1 +0,0 @@
uqm_CFILES="lzdecode.c lzencode.c update.c"

View File

@@ -1,415 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
/*
* LZHUF.C English version 1.0
* Based on Japanese version 29-NOV-1988
* LZSS coded by Haruhiko OKUMURA
* Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
* Edited and translated to English by Kenji RIKITAKE
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lzh.h"
#include "libs/reslib.h"
PLZHCODE_DESC _lpCurCodeDesc;
STREAM_TYPE _StreamType;
BYTE* _Stream;
UWORD _workbuf;
BYTE _workbuflen;
/* get one bit */
static SWORD
GetBit (void)
{
SWORD i;
while (_workbuflen <= 8)
{
if ((i = InChar ()) < 0)
i = 0;
_workbuf |= i << (8 - _workbuflen);
_workbuflen += 8;
}
i = (_workbuf & 0xFFFF) >> (16 - 1);
_workbuf = (_workbuf << 1) & 0xFFFF;
_workbuflen--;
return (i);
}
static UWORD
GetBits (BYTE num_bits)
{
SWORD i;
while (_workbuflen <= 8)
{
if ((i = InChar ()) < 0)
i = 0;
_workbuf |= i << (8 - _workbuflen);
_workbuflen += 8;
}
i = (_workbuf & 0xFFFF) >> (16 - num_bits);
_workbuf = (_workbuf << num_bits) & 0xFFFF;
_workbuflen -= num_bits;
return (i);
}
/* initialize freq tree */
void
StartHuff (void)
{
COUNT i, j;
for (i = 0; i < N_CHAR; i++)
{
_lpCurCodeDesc->freq[i] = 1;
_lpCurCodeDesc->son[i] = i + T;
_lpCurCodeDesc->prnt[i + T] = i;
}
i = 0; j = N_CHAR;
while (j <= R)
{
_lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[i + 1];
_lpCurCodeDesc->son[j] = i;
_lpCurCodeDesc->prnt[i] = _lpCurCodeDesc->prnt[i + 1] = j;
i += 2; j++;
}
_lpCurCodeDesc->freq[T] = 0xffff;
_lpCurCodeDesc->prnt[R] = 0;
}
DECODE_REF
copen (void *InStream, STREAM_TYPE SType, STREAM_MODE SMode)
{
DWORD StreamLength;
_StreamType = SType;
_Stream = InStream;
if (SMode == STREAM_WRITE) /* writing */
{
OutChar (0); /* skip future StreamLength */
OutChar (0);
OutChar (0);
OutChar (0);
StreamLength = 0;
}
else /* reading */
{
BYTE lobyte, hibyte;
UWORD loword, hiword;
lobyte = (BYTE)InChar ();
hibyte = (BYTE)InChar ();
loword = MAKE_WORD (lobyte, hibyte);
lobyte = (BYTE)InChar ();
hibyte = (BYTE)InChar ();
hiword = MAKE_WORD (lobyte, hibyte);
StreamLength = MAKE_DWORD (loword, hiword);
}
if (StreamLength == 0xFFFFFFFF
|| (_lpCurCodeDesc = AllocCodeDesc ()) == NULL)
{
FreeCodeDesc (_lpCurCodeDesc);
_lpCurCodeDesc = NULL;
}
else
{
_lpCurCodeDesc->Stream = _Stream;
_lpCurCodeDesc->StreamType = _StreamType;
_lpCurCodeDesc->StreamMode = SMode;
_lpCurCodeDesc->StreamLength = StreamLength;
_lpCurCodeDesc->buf_index = N - F;
memset (&_lpCurCodeDesc->text_buf[0], ' ', N - F);
StartHuff ();
}
return ((DECODE_REF)_lpCurCodeDesc);
}
DWORD
cclose (PLZHCODE_DESC lpCodeDesc)
{
_lpCurCodeDesc = lpCodeDesc;
if (_lpCurCodeDesc)
{
DWORD StreamIndex;
if (_lpCurCodeDesc->CleanupFunc)
(*_lpCurCodeDesc->CleanupFunc) ();
StreamIndex = lpCodeDesc->StreamIndex;
FreeCodeDesc (lpCodeDesc);
_lpCurCodeDesc = NULL;
return (StreamIndex);
}
return (0);
}
void
cfilelength (PLZHCODE_DESC lpCodeDesc, DWORD *pfilelen)
{
if (lpCodeDesc == 0)
*pfilelen = 0;
else
*pfilelen = lpCodeDesc->StreamLength;
}
/* decoder table */
static const BYTE d_code[256] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};
static const BYTE d_len[256] =
{
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
};
/* decode upper 6 bits from given table */
#define DecodePosition(p) \
{ \
while (_workbuflen <= 8) \
{ \
*(p) = InChar (); \
_workbuf |= *(p) << (8 - _workbuflen); \
_workbuflen += 8; \
} \
*(p) = HIBYTE (_workbuf); \
_workbuf = (_workbuf << 8) & 0xFFFF; \
_workbuflen -= 8; \
\
/* input lower 6 bits directly */ \
j = d_len[*(p)]; \
*(p) = ((UWORD)d_code[*(p)] << 6) \
| (((*(p) << j) | GetBits (j)) & 0x3f); \
}
/* start searching tree from the root to leaves.
* choose node #(son[]) if input bit == 0
* else choose #(son[]+1) (input bit == 1)
*/
#define DecodeChar(c) \
{ \
for (*(c) = lpCodeDesc->son[R]; \
*(c) < T; \
*(c) = lpCodeDesc->son[*(c) + GetBit ()]) \
; \
_update (*(c)); \
*(c) -= T; \
}
COUNT
cread (void *buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc)
{
COUNT r, j, i;
BYTE *lpStr;
if ((_lpCurCodeDesc = lpCodeDesc) == 0)
return (0);
size *= count;
if (lpCodeDesc->StreamIndex + size > lpCodeDesc->StreamLength)
{
size /= count;
count = (COUNT)((lpCodeDesc->StreamLength
- lpCodeDesc->StreamIndex) / size);
size *= count;
}
if (size == 0)
return (0);
lpStr = (BYTE*)buf;
_StreamType = lpCodeDesc->StreamType;
_Stream = lpCodeDesc->Stream;
_workbuf = lpCodeDesc->workbuf;
_workbuflen = lpCodeDesc->workbuflen;
lpCodeDesc->StreamIndex += size;
r = lpCodeDesc->buf_index;
j = lpCodeDesc->bytes_left;
if (j)
{
lpCodeDesc->bytes_left = 0;
i = lpCodeDesc->restart_index;
goto ReenterRun;
}
do
{
COUNT c;
DecodeChar (&c);
if (c < 256)
{
size--;
*lpStr++ = lpCodeDesc->text_buf[r++ & (N - 1)] = (BYTE)c;
}
else
{
COUNT copy_size;
//i is a COUNT;
DecodePosition(&i);
i = r - i - 1;
j = c - 255 + THRESHOLD;
ReenterRun:
if (j > size)
{
lpCodeDesc->bytes_left = j - size;
lpCodeDesc->restart_index = i + size;
j = size;
}
size -= j;
do
{
COUNT loc_size;
i &= (N - 1);
r &= (N - 1);
if ((i < r && i + j > r) || (i > r && i + j > r + N))
copy_size = (r - i) & (N - 1);
else if ((copy_size = j) > N)
copy_size = N;
loc_size = copy_size;
if (i + loc_size > N)
{
COUNT k;
k = N - i;
memcpy (lpStr, &lpCodeDesc->text_buf[i], k);
lpStr += k;
loc_size -= k;
i = 0;
}
memcpy (lpStr, &lpCodeDesc->text_buf[i], loc_size);
lpStr += loc_size;
i += loc_size;
lpStr -= copy_size;
loc_size = copy_size;
if (r + loc_size > N)
{
COUNT k;
k = N - r;
memcpy (&lpCodeDesc->text_buf[r], lpStr, k);
lpStr += k;
loc_size -= k;
r = 0;
}
memcpy (&lpCodeDesc->text_buf[r], lpStr, loc_size);
lpStr += loc_size;
r += loc_size;
} while (j -= copy_size);
}
} while (size);
lpCodeDesc->buf_index = r;
lpCodeDesc->Stream = _Stream;
lpCodeDesc->workbuf = _workbuf;
lpCodeDesc->workbuflen = _workbuflen;
return (count);
}

View File

@@ -1,468 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
/*
* LZHUF.C English version 1.0
* Based on Japanese version 29-NOV-1988
* LZSS coded by Haruhiko OKUMURA
* Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
* Edited and translated to English by Kenji RIKITAKE
*/
#include <stdio.h>
#include "lzh.h"
#include "libs/reslib.h"
static UWORD match_position, match_length;
static SWORD *lson;
static SWORD *rson;
static SWORD *dad;
static SWORD *encode_arrays;
#define AllocEncodeArrays() \
HCalloc ( \
(((N + 1) + (N + 257) + (N + 1)) \
* sizeof (lson[0])))
#define FreeCodeArrays HFree
static BOOLEAN
InitTree (void)
{
if ((encode_arrays = AllocEncodeArrays ()) == NULL)
{
FreeCodeArrays (encode_arrays);
encode_arrays = NULL;
return (FALSE);
}
else
{
SWORD i;
lson = encode_arrays;
rson = lson + (N + 1);
dad = rson + (N + 257);
for (i = N + 1; i <= N + 256; i++)
rson[i] = NIL; /* root */
for (i = 0; i < N; i++)
dad[i] = NIL; /* node */
return (TRUE);
}
}
static void
InsertNode (SWORD r)
{
SWORD p, cmp;
BYTE *lpBuf;
cmp = 1;
lpBuf = _lpCurCodeDesc->text_buf;
p = N + 1 + lpBuf[r];
rson[r] = lson[r] = NIL;
match_length = 0;
for (;;)
{
UWORD i;
if (cmp >= 0)
{
if (rson[p] != NIL)
p = rson[p];
else
{
rson[p] = r;
dad[r] = p;
return;
}
}
else
{
if (lson[p] != NIL)
p = lson[p];
else
{
lson[p] = r;
dad[r] = p;
return;
}
}
i = F;
{
SWORD _r, _p;
_r = r;
_p = p;
while (--i && (cmp = lpBuf[++_r] - lpBuf[++_p]) == 0)
;
}
if ((i = F - i) > THRESHOLD)
{
if (i > match_length)
{
match_position = ((r - p) & (N - 1)) - 1;
if ((match_length = i) >= F)
break;
}
else if (i == match_length)
{
if ((i = ((r - p) & (N - 1)) - 1) < match_position)
{
match_position = i;
}
}
}
}
dad[r] = dad[p];
lson[r] = lson[p];
rson[r] = rson[p];
dad[lson[p]] = r;
dad[rson[p]] = r;
if (rson[dad[p]] == p)
rson[dad[p]] = r;
else
lson[dad[p]] = r;
dad[p] = NIL; /* remove p */
}
static void
DeleteNode (SWORD p)
{
SWORD q;
if (dad[p] == NIL)
return; /* unregistered */
if (rson[p] == NIL)
q = lson[p];
else if (lson[p] == NIL)
q = rson[p];
else
{
q = lson[p];
if (rson[q] != NIL)
{
do
{
q = rson[q];
} while (rson[q] != NIL);
rson[dad[q]] = lson[q];
dad[lson[q]] = dad[q];
lson[q] = lson[p];
dad[lson[p]] = q;
}
rson[q] = rson[p];
dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p)
rson[dad[p]] = q;
else
lson[dad[p]] = q;
dad[p] = NIL;
}
static void
Putcode (SWORD l, UWORD c)
{
_workbuf |= c >> _workbuflen;
if ((_workbuflen += l) >= 8)
{
OutChar ((BYTE)(_workbuf >> 8));
++_lpCurCodeDesc->StreamIndex;
if ((_workbuflen -= 8) >= 8)
{
OutChar ((BYTE)(_workbuf));
++_lpCurCodeDesc->StreamIndex;
_workbuflen -= 8;
_workbuf = c << (l - _workbuflen);
}
else
{
_workbuf <<= 8;
}
_workbuf &= 0xFFFF;
}
}
static void
EncodeChar (UWORD c)
{
UWORD i;
SWORD j, k;
i = 0;
j = 0;
k = _lpCurCodeDesc->prnt[c + T];
/* search connections from leaf node to the root */
do
{
i >>= 1;
/*
if node's address is odd, output 1
else output 0
*/
if (k & 1)
i += 0x8000;
j++;
} while ((k = _lpCurCodeDesc->prnt[k]) != R);
Putcode (j, i);
_update (c + T);
}
static void
EncodePosition (UWORD c)
{
UWORD i;
/*
* Tables for encoding/decoding upper 6 bits of
* sliding dictionary pointer
*/
/* encoder table */
static const BYTE p_len[64] =
{
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
static const BYTE p_code[64] =
{
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
/* output upper 6 bits with encoding */
i = c >> 6;
Putcode (p_len[i], (UWORD)p_code[i] << 8);
/* output lower 6 bits directly */
Putcode (6, (c & 0x3f) << 10);
}
static void
UninitTree (void)
{
if (_workbuflen)
{
OutChar ((BYTE)(_workbuf >> 8));
++_lpCurCodeDesc->StreamIndex;
}
FreeCodeArrays (encode_arrays);
encode_arrays = NULL;
lson = NULL;
rson = NULL;
dad = NULL;
}
static void
_encode_cleanup (void)
{
UWORD r, s, last_match_length, len;
_StreamType = _lpCurCodeDesc->StreamType;
_Stream = _lpCurCodeDesc->Stream;
_workbuf = _lpCurCodeDesc->workbuf;
_workbuflen = _lpCurCodeDesc->workbuflen;
r = _lpCurCodeDesc->buf_index;
s = _lpCurCodeDesc->restart_index;
last_match_length = _lpCurCodeDesc->bytes_left;
if (_lpCurCodeDesc->StreamLength >= F)
len = F;
else
{
UWORD i;
for (i = 1; i <= F; i++)
InsertNode (r - i);
InsertNode (r);
len = (UWORD)_lpCurCodeDesc->StreamLength;
}
while (1)
{
while (last_match_length--)
{
DeleteNode (s);
if (--len == 0)
{
BYTE lobyte, hibyte;
UWORD loword, hiword;
UninitTree ();
_lpCurCodeDesc->StreamIndex += 4;
/* rewind */
if (_lpCurCodeDesc->StreamType == FILE_STREAM)
SeekResFile ((uio_Stream *)_Stream,
-(int)_lpCurCodeDesc->StreamIndex, SEEK_CUR);
else /* _lpCurCodeDesc->StreamType == MEMORY_STREAM */
_Stream = (BYTE*)_Stream - _lpCurCodeDesc->StreamIndex;
loword = LOWORD (_lpCurCodeDesc->StreamLength);
lobyte = LOBYTE (loword);
hibyte = HIBYTE (loword);
OutChar (lobyte);
OutChar (hibyte);
hiword = HIWORD (_lpCurCodeDesc->StreamLength);
lobyte = LOBYTE (hiword);
hibyte = HIBYTE (hiword);
OutChar (lobyte);
OutChar (hibyte);
return;
}
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode (r);
}
if (match_length > len)
match_length = len;
if (match_length <= THRESHOLD)
{
match_length = 1;
EncodeChar (_lpCurCodeDesc->text_buf[r]);
}
else
{
EncodeChar (255 - THRESHOLD + match_length);
EncodePosition (match_position);
}
last_match_length = match_length;
}
}
COUNT
cwrite (const void *buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc)
{
UWORD r, s, last_match_length;
BYTE *lpBuf;
const BYTE *lpStr;
if ((_lpCurCodeDesc = lpCodeDesc) == 0
|| (size *= count) == 0)
return (0);
_StreamType = lpCodeDesc->StreamType;
_Stream = lpCodeDesc->Stream;
_workbuf = lpCodeDesc->workbuf;
_workbuflen = lpCodeDesc->workbuflen;
lpStr = (const BYTE *) buf;
lpBuf = lpCodeDesc->text_buf;
r = lpCodeDesc->buf_index;
s = lpCodeDesc->restart_index;
last_match_length = lpCodeDesc->bytes_left;
if (last_match_length)
{
lpCodeDesc->StreamLength += size;
goto EncodeRestart;
}
else if (lpCodeDesc->StreamLength < F)
{
UWORD i;
if ((i = (UWORD)lpCodeDesc->StreamLength) == 0)
{
if (!InitTree ())
return (0);
_lpCurCodeDesc->StreamIndex = 0;
lpCodeDesc->CleanupFunc = _encode_cleanup;
}
lpCodeDesc->StreamLength += size;
for (; i < F && size; ++i, --size)
lpBuf[r + i] = *lpStr++;
if (i < F)
goto EncodeExit;
for (i = 1; i <= F; i++)
InsertNode (r - i);
InsertNode (r);
if (size == 0)
goto EncodeExit;
}
else
lpCodeDesc->StreamLength += size;
do
{
if (match_length > F)
match_length = F;
if (match_length <= THRESHOLD)
{
match_length = 1;
EncodeChar (lpBuf[r]);
}
else
{
EncodeChar (255 - THRESHOLD + match_length);
EncodePosition (match_position);
}
last_match_length = match_length;
EncodeRestart:
while (last_match_length && size)
{
BYTE c;
--size;
--last_match_length;
DeleteNode (s);
c = *lpStr++;
lpBuf[s] = c;
if (s < F - 1)
lpBuf[s + N] = c;
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode (r);
}
} while (last_match_length == 0);
EncodeExit:
lpCodeDesc->buf_index = r;
lpCodeDesc->restart_index = s;
lpCodeDesc->bytes_left = last_match_length;
lpCodeDesc->Stream = _Stream;
lpCodeDesc->workbuf = _workbuf;
lpCodeDesc->workbuflen = _workbuflen;
return (count);
}

View File

@@ -1,91 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _LZH_H
#define _LZH_H
#include "libs/declib.h"
#include "libs/memlib.h"
/* LZSS Parameters */
#define N 4096 /* Size of string buffer */
#define F 16 /* Size of look-ahead buffer */
//#define F 60 /* Size of look-ahead buffer */
#define THRESHOLD 2
#define NIL N /* End of tree's node */
/* Huffman coding parameters */
#define N_CHAR (256 - THRESHOLD + F)
/* character code (= 0..N_CHAR-1) */
#define T (N_CHAR * 2 - 1) /* Size of table */
#define R (T - 1) /* root position */
#define MAX_FREQ 0x8000
/* update when cumulative frequency */
struct _LZHCODE_DESC
{
COUNT buf_index, restart_index, bytes_left;
BYTE text_buf[N + F - 1];
/* reconstruct freq tree */
COUNT freq[T + 1]; /* cumulative freq table */
/*
* pointing parent nodes.
* area [T..(T + N_CHAR - 1)] are pointers for leaves
*/
COUNT prnt[T + N_CHAR];
/* pointing children nodes (son[], son[] + 1)*/
COUNT son[T];
UWORD workbuf;
BYTE workbuflen;
STREAM_TYPE StreamType;
void *Stream;
DWORD StreamIndex, StreamLength;
STREAM_MODE StreamMode;
PVOIDFUNC CleanupFunc;
};
typedef struct _LZHCODE_DESC LZHCODE_DESC;
typedef LZHCODE_DESC *PLZHCODE_DESC;
#define InChar() (_StreamType == FILE_STREAM ? \
GetResFileChar ((uio_Stream *)_Stream) : \
(int)*_Stream++)
#define OutChar(c) (_StreamType == FILE_STREAM ? \
PutResFileChar ((c), (uio_Stream *)_Stream) : \
(*_Stream++ = (BYTE)(c)))
#define AllocCodeDesc() HCalloc (sizeof (LZHCODE_DESC))
#define FreeCodeDesc HFree
extern void _update (COUNT c);
extern void StartHuff (void);
extern PLZHCODE_DESC _lpCurCodeDesc;
extern STREAM_TYPE _StreamType;
extern BYTE* _Stream;
extern UWORD _workbuf;
extern BYTE _workbuflen;
#endif /* _LZH_H */

View File

@@ -1,115 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 <string.h>
#include "lzh.h"
static void
reconst (void)
{
COUNT i, j;
/* halven cumulative freq for leaf nodes */
j = 0;
for (i = 0; i < T; i++)
{
if (_lpCurCodeDesc->son[i] >= T)
{
_lpCurCodeDesc->freq[j] = (_lpCurCodeDesc->freq[i] + 1) >> 1;
_lpCurCodeDesc->son[j] = _lpCurCodeDesc->son[i];
j++;
}
}
/* make a tree : first, connect children nodes */
for (i = 0, j = N_CHAR; j < T; i += 2, j++)
{
SWORD k;
UWORD f, l;
k = i + 1;
f = _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[k];
for (k = j - 1; f < _lpCurCodeDesc->freq[k]; k--)
;
k++;
l = (j - k);
memmove (_lpCurCodeDesc->freq + k + 1, _lpCurCodeDesc->freq + k,
sizeof(_lpCurCodeDesc->freq[0]) * l);
_lpCurCodeDesc->freq[k] = f;
memmove (_lpCurCodeDesc->son + k + 1, _lpCurCodeDesc->son + k,
sizeof(_lpCurCodeDesc->son[0]) * l);
_lpCurCodeDesc->son[k] = i;
}
/* connect parent nodes */
for (i = 0; i < T; i++)
{
if ((j = _lpCurCodeDesc->son[i]) >= T)
_lpCurCodeDesc->prnt[j] = i;
else
_lpCurCodeDesc->prnt[j] = _lpCurCodeDesc->prnt[j + 1] = i;
}
}
/* update freq tree */
void
_update (COUNT c)
{
PLZHCODE_DESC lpCD;
if ((lpCD = _lpCurCodeDesc)->freq[R] == MAX_FREQ)
reconst ();
c = lpCD->prnt[c];
do
{
COUNT i, l;
i = ++lpCD->freq[c];
/* swap nodes to keep the tree freq-ordered */
if (i > lpCD->freq[l = c + 1])
{
COUNT j;
while (i > lpCD->freq[++l])
;
l--;
lpCD->freq[c] = lpCD->freq[l];
lpCD->freq[l] = i;
i = lpCD->son[c];
j = lpCD->son[l];
lpCD->son[l] = i;
lpCD->son[c] = j;
lpCD->prnt[i] = l;
if (i < T)
lpCD->prnt[i + 1] = l;
lpCD->prnt[j] = c;
if (j < T)
lpCD->prnt[j + 1] = c;
c = l;
}
} while ((c = lpCD->prnt[c]) != 0); /* do it until reaching the root */
}

View File

@@ -1,87 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Contains file handling code
#ifndef _FILE_H
#define _FILE_H
#include "port.h"
#include "libs/uio.h"
// for bool
#include "types.h"
#if 0
// from temp.h
void initTempDir (void);
void unInitTempDir (void);
char *tempFilePath (const char *filename);
extern uio_DirHandle *tempDir;
#endif
// from dirs.h
int mkdirhier (const char *path);
const char *getHomeDir (void);
int createDirectory (const char *dir, int mode);
int expandPath (char *dest, size_t len, const char *src, int what);
// values for 'what':
#define EP_HOME 1
// Expand '~' for home dirs.
#define EP_ABSOLUTE 2
// Make paths absolute
#define EP_ENVVARS 4
// Expand environment variables.
#define EP_DOTS 8
// Process ".." and "."
#define EP_SLASHES 16
// Consider backslashes as path component separators.
// They will be replaced by slashes. Windows UNC paths will always
// start with "\\server\share", with backslashes.
#define EP_SINGLESEP 32
// Replace multiple consecutive path separators by a single one.
#define EP_ALL (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | EP_SLASHES \
EP_SINGLESEP)
// Everything
// Everything except Windows style backslashes on Unix Systems:
#ifdef WIN32
# define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | \
EP_SLASHES | EP_SINGLESEP)
#else
# define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | \
EP_SINGLESEP)
#endif
// from files.h
int copyFile (uio_DirHandle *srcDir, const char *srcName,
uio_DirHandle *dstDir, const char *newName);
bool fileExists (const char *name);
bool fileExists2(uio_DirHandle *dir, const char *fileName);
#ifdef HAVE_UNC_PATHS
size_t skipUNCServerShare(const char *inPath);
#endif /* HAVE_UNC_PATHS */
#ifdef HAVE_DRIVE_LETTERS
static inline int isDriveLetter(int c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
#endif /* HAVE_DRIVE_LETTERS */
#endif /* _FILE_H */

View File

@@ -1 +0,0 @@
uqm_CFILES="dirs.c files.c"

View File

@@ -1,826 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Contains code handling directories
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "port.h"
#include "config.h"
#include "filintrn.h"
#include "libs/compiler.h"
#include "libs/memlib.h"
#include "libs/misc.h"
#include "libs/log.h"
#ifdef HAVE_DRIVE_LETTERS
# include <ctype.h>
// For tolower()
#endif /* HAVE_DRIVE_LETTERS */
#ifdef WIN32
# include <direct.h>
// For _getdcwd()
#else
# include <pwd.h>
// For getpwuid()
#endif
/* Try to find a suitable value for %APPDATA% if it isn't defined on
* Windows.
*/
#define APPDATA_FALLBACK
static char *expandPathAbsolute (char *dest, size_t destLen, const char *src,
size_t *skipSrc, int what);
static char *strrchr2(const char *start, int c, const char *end);
int
createDirectory(const char *dir, int mode)
{
return MKDIR(dir, mode);
}
// make all components of the path if they don't exist already
// returns 0 on success, -1 on failure.
// on failure, some parts may still have been created.
int
mkdirhier (const char *path)
{
char *buf; // buffer
char *ptr; // end of the string in buf
const char *pathstart; // start of a component of path
const char *pathend; // first char past the end of a component of path
size_t len;
struct stat statbuf;
len = strlen (path);
buf = HMalloc (len + 2); // one extra for possibly added '/'
ptr = buf;
pathstart = path;
#ifdef HAVE_DRIVE_LETTERS
if (isDriveLetter(pathstart[0]) && pathstart[1] == ':')
{
// Driveletter + semicolon on Windows.
// Copy as is; don't try to create directories for it.
*(ptr++) = *(pathstart++);
*(ptr++) = *(pathstart++);
ptr[0] = '/';
ptr[1] = '\0';
if (stat (buf, &statbuf) == -1)
{
log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno));
goto err;
}
}
else
#endif /* HAVE_DRIVE_LETTERS */
#ifdef HAVE_UNC_PATHS
if (pathstart[0] == '\\' && pathstart[1] == '\\')
{
// Universal Naming Convention path. (\\server\share\...)
// Copy the server part as is; don't try to create directories for
// it, or stat it. Don't create a dir for the share either.
*(ptr++) = *(pathstart++);
*(ptr++) = *(pathstart++);
// Copy the server part
while (*pathstart != '\0' && *pathstart != '\\' && *pathstart != '/')
*(ptr++) = *(pathstart++);
if (*pathstart == '\0')
{
log_add (log_Error, "Incomplete UNC path \"%s\"", pathstart);
goto err;
}
// Copy the path seperator.
*(ptr++) = *(pathstart++);
// Copy the share part
while (*pathstart != '\0' && *pathstart != '\\' && *pathstart != '/')
*(ptr++) = *(pathstart++);
ptr[0] = '/';
ptr[1] = '\0';
if (stat (buf, &statbuf) == -1)
{
log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno));
goto err;
}
}
#else
{
// Making sure that there is an 'else' case if HAVE_DRIVE_LETTERS is
// defined.
}
#endif /* HAVE_UNC_PATHS */
if (*pathstart == '/')
*(ptr++) = *(pathstart++);
if (*pathstart == '\0') {
// path exists completely, nothing more to do
return 0;
}
// walk through the path as long as the components exist
while (1)
{
pathend = strchr (pathstart, '/');
if (pathend == NULL)
pathend = path + len;
memcpy(ptr, pathstart, pathend - pathstart);
ptr += pathend - pathstart;
*ptr = '\0';
if (stat (buf, &statbuf) == -1)
{
if (errno == ENOENT)
break;
#ifdef __SYMBIAN32__
// XXX: HACK: If we don't have access to a directory, we can
// still have access to the underlying entries. We don't
// actually know whether the entry is a directory, but I know of
// no way to find out. We just pretend that it is; if we were
// wrong, an error will occur when we try to do something with
// the directory. That /should/ not be a problem, as any such
// action should have its own error checking.
if (errno != EACCES)
#endif
{
log_add (log_Error, "Can't stat \"%s\": %s", buf,
strerror (errno));
goto err;
}
}
if (*pathend == '\0')
return 0;
*ptr = '/';
ptr++;
pathstart = pathend + 1;
while (*pathstart == '/')
pathstart++;
// pathstart is the next non-slash character
if (*pathstart == '\0')
return 0;
}
// create all components left
while (1)
{
if (createDirectory (buf, 0777) == -1)
{
log_add (log_Error, "Error: Can't create %s: %s", buf,
strerror (errno));
goto err;
}
if (*pathend == '\0')
break;
*ptr = '/';
ptr++;
pathstart = pathend + 1;
while (*pathstart == '/')
pathstart++;
// pathstart is the next non-slash character
if (*pathstart == '\0')
break;
pathend = strchr (pathstart, '/');
if (pathend == NULL)
pathend = path + len;
memcpy (ptr, pathstart, pathend - pathstart);
ptr += pathend - pathstart;
*ptr = '\0';
}
return 0;
err:
{
int savedErrno = errno;
HFree (buf);
errno = savedErrno;
}
return -1;
}
// Get the user's home dir
// returns a pointer to a static buffer from either getenv() or getpwuid().
const char *
getHomeDir (void)
{
#ifdef WIN32
return getenv ("HOME");
#else
const char *home;
struct passwd *pw;
home = getenv ("HOME");
if (home != NULL)
return home;
pw = getpwuid (getuid ());
if (pw == NULL)
return NULL;
// NB: pw points to a static buffer.
return pw->pw_dir;
#endif
}
// Performs various types of string expansions on a path.
// 'what' is an OR'd compination of the folowing flags, which
// specify what type of exmansions will be performed.
// EP_HOME - Expand '~' for home dirs.
// EP_ABSOLUTE - Make relative paths absolute
// EP_ENVVARS - Expand environment variables
// EP_DOTS - Process ".." and "."
// EP_SLASHES - Consider backslashes as path component separators.
// They will be replaced by slashes.
// EP_SINGLESEP - Replace multiple consecutive path seperators (which POSIX
// considers equivalent to a single one) by a single one.
// Additionally, there's EP_ALL, which indicates all of the above,
// and EP_ALL_SYSTEM, which does the same as EP_ALL, with the exception
// of EP_SLASHES, which will only be included if the operating system
// accepts backslashes as path terminators.
// Returns 0 on success.
// Returns -1 on failure, setting errno.
int
expandPath (char *dest, size_t len, const char *src, int what)
{
char *destptr, *destend;
char *buf = NULL;
char *bufptr, *bufend;
const char *srcend;
#define CHECKLEN(bufname, n) \
if (bufname##ptr + (n) >= bufname##end) \
{ \
errno = ENAMETOOLONG; \
goto err; \
} \
else \
(void) 0
destptr = dest;
destend = dest + len;
if (what & EP_ENVVARS)
{
buf = HMalloc (len);
bufptr = buf;
bufend = buf + len;
while (*src != '\0')
{
switch (*src)
{
#ifdef WIN32
case '%':
{
/* Environment variable substitution in Windows */
const char *end; // end of env var name in src
const char *envVar;
char *envName;
size_t envNameLen, envVarLen;
src++;
end = strchr (src, '%');
if (end == NULL)
{
errno = EINVAL;
goto err;
}
envNameLen = end - src;
envName = HMalloc (envNameLen + 1);
memcpy (envName, src, envNameLen + 1);
envName[envNameLen] = '\0';
envVar = getenv (envName);
HFree (envName);
if (envVar == NULL)
{
#ifdef APPDATA_FALLBACK
if (strncmp (src, "APPDATA", envNameLen) != 0)
{
// Substitute an empty string
src = end + 1;
break;
}
// fallback for when the APPDATA env var is not set
// Using SHGetFolderPath or SHGetSpecialFolderPath
// is problematic (not everywhere available).
log_add (log_Warning, "Warning: %%APPDATA%% is not set. "
"Falling back to \"%%USERPROFILE%%\\Application "
"Data\"");
envVar = getenv ("USERPROFILE");
if (envVar != NULL)
{
#define APPDATA_STRING "\\Application Data"
envVarLen = strlen (envVar);
CHECKLEN (buf,
envVarLen + sizeof (APPDATA_STRING) - 1);
strcpy (bufptr, envVar);
bufptr += envVarLen;
strcpy (bufptr, APPDATA_STRING);
bufptr += sizeof (APPDATA_STRING) - 1;
src = end + 1;
break;
}
// fallback to "./userdata"
#define APPDATA_FALLBACK_STRING ".\\userdata"
log_add (log_Warning,
"Warning: %%USERPROFILE%% is not set. "
"Falling back to \"%s\" for %%APPDATA%%",
APPDATA_FALLBACK_STRING);
CHECKLEN (buf, sizeof (APPDATA_FALLBACK_STRING) - 1);
strcpy (bufptr, APPDATA_FALLBACK_STRING);
bufptr += sizeof (APPDATA_FALLBACK_STRING) - 1;
src = end + 1;
break;
#else /* !defined (APPDATA_FALLBACK) */
// Substitute an empty string
src = end + 1;
break;
#endif /* APPDATA_FALLBACK */
}
envVarLen = strlen (envVar);
CHECKLEN (buf, envVarLen);
strcpy (bufptr, envVar);
bufptr += envVarLen;
src = end + 1;
break;
}
#endif
#ifndef WIN32
case '$':
{
const char *end;
char *envName;
size_t envNameLen;
const char *envVar;
size_t envVarLen;
src++;
if (*src == '{')
{
src++;
end = strchr(src, '}');
if (end == NULL)
{
errno = EINVAL;
goto err;
}
envNameLen = end - src;
end++; // Skip the '}'
}
else
{
end = src;
while ((*end >= 'A' && *end <= 'Z') ||
(*end >= 'a' && *end <= 'z') ||
(*end >= '0' && *end <= '9') ||
*end == '_')
end++;
envNameLen = end - src;
}
envName = HMalloc (envNameLen + 1);
memcpy (envName, src, envNameLen + 1);
envName[envNameLen] = '\0';
envVar = getenv (envName);
HFree (envName);
if (envVar != NULL)
{
envVarLen = strlen (envVar);
CHECKLEN (buf, envVarLen);
memcpy (bufptr, envVar, envVarLen);
bufptr += envVarLen;
}
src = end;
break;
}
#endif
default:
CHECKLEN(buf, 1);
*(bufptr++) = *(src++);
break;
} // switch
} // while
*bufptr = '\0';
src = buf;
srcend = bufptr;
} // if (what & EP_ENVVARS)
else
srcend = src + strlen (src);
if (what & EP_HOME)
{
if (src[0] == '~')
{
const char *home;
size_t homelen;
if (src[1] != '/')
{
errno = EINVAL;
goto err;
}
home = getHomeDir ();
if (home == NULL)
{
errno = ENOENT;
goto err;
}
homelen = strlen (home);
if (what & EP_ABSOLUTE) {
size_t skip;
destptr = expandPathAbsolute (dest, destend - dest,
home, &skip, what);
if (destptr == NULL)
{
// errno is set
goto err;
}
home += skip;
what &= ~EP_ABSOLUTE;
// The part after the '~' should not be seen
// as absolute.
}
CHECKLEN (dest, homelen);
memcpy (destptr, home, homelen);
destptr += homelen;
src++; /* skip the ~ */
}
}
if (what & EP_ABSOLUTE)
{
size_t skip;
destptr = expandPathAbsolute (destptr, destend - destptr, src,
&skip, what);
if (destptr == NULL)
{
// errno is set
goto err;
}
src += skip;
}
CHECKLEN (dest, srcend - src);
memcpy (destptr, src, srcend - src + 1);
// The +1 is for the '\0'. It is already taken into account by
// CHECKLEN.
if (what & EP_SLASHES)
{
/* Replacing backslashes in path by slashes. */
destptr = dest;
#ifdef HAVE_UNC_PATHS
{
// A UNC path should always start with two backslashes
// and have a backslash in between the server and share part.
size_t skip = skipUNCServerShare (destptr);
if (skip != 0)
{
char *slash = (char *) memchr (destptr + 2, '/', skip - 2);
if (slash)
*slash = '\\';
destptr += skip;
}
}
#endif /* HAVE_UNC_PATHS */
while (*destptr != '\0')
{
if (*destptr == '\\')
*destptr = '/';
destptr++;
}
}
if (what & EP_DOTS) {
// At this point backslashes are already replaced by slashes if they
// are specified to be path seperators.
// Note that the path can only get smaller, so no size checks
// need to be done.
char *pathStart;
// Start of the first path component, after any
// leading slashes or drive letters.
char *startPart;
char *endPart;
pathStart = dest;
#ifdef HAVE_DRIVE_LETTERS
if (isDriveLetter(pathStart[0]) && (pathStart[1] == ':'))
{
pathStart += 2;
}
else
#endif /* HAVE_DRIVE_LETTERS */
#ifdef HAVE_UNC_PATHS
{
// Test for a Universal Naming Convention path.
pathStart += skipUNCServerShare(pathStart);
}
#else
{
// Making sure that there is an 'else' case if HAVE_DRIVE_LETTERS is
// defined.
}
#endif /* HAVE_UNC_PATHS */
if (pathStart[0] == '/')
pathStart++;
startPart = pathStart;
destptr = pathStart;
for (;;)
{
endPart = strchr(startPart, '/');
if (endPart == NULL)
endPart = startPart + strlen(startPart);
if (endPart - startPart == 1 && startPart[0] == '.')
{
// Found "." as path component. Ignore this component.
}
else if (endPart - startPart == 2 &&
startPart[0] == '.' && startPart[1] == '.')
{
// Found ".." as path component. Remove the previous
// component, and ignore this one.
char *lastSlash;
lastSlash = strrchr2(pathStart, '/', destptr - 1);
if (lastSlash == NULL)
{
if (destptr == pathStart)
{
// We ran out of path components to back out of.
errno = EINVAL;
goto err;
}
destptr = pathStart;
}
else
{
destptr = lastSlash;
if (*endPart == '/')
destptr++;
}
}
else
{
// A normal path component; copy it.
// Using memmove as source and destination may overlap.
memmove(destptr, startPart, endPart - startPart);
destptr += (endPart - startPart);
if (*endPart == '/')
{
*destptr = '/';
destptr++;
}
}
if (*endPart == '\0')
break;
startPart = endPart + 1;
}
*destptr = '\0';
}
if (what & EP_SINGLESEP)
{
char *srcptr;
srcptr = dest;
destptr = dest;
while (*srcptr != '\0')
{
char ch = *srcptr;
*(destptr++) = *(srcptr++);
if (ch == '/')
{
while (*srcptr == '/')
srcptr++;
}
}
*destptr = '\0';
}
return 0;
err:
if (buf != NULL) {
int savedErrno = errno;
HFree (buf);
errno = savedErrno;
}
return -1;
}
#if defined(HAVE_DRIVE_LETTERS) && defined(HAVE_CWD_PER_DRIVE)
// This code is only needed if we have a current working directory
// per drive.
// letter is 0 based: 0 = A, 1 = B, ...
bool
driveLetterExists(int letter)
{
unsigned long drives;
drives = _getdrives ();
return ((drives >> letter) & 1) != 0;
}
#endif /* if defined(HAVE_DRIVE_LETTERS) && defined(HAVE_CWD_PER_DRIVE) */
// helper for expandPath, expanding an absolute path
// returns a pointer to the end of the filled in part of dest.
static char *
expandPathAbsolute (char *dest, size_t destLen, const char *src,
size_t *skipSrc, int what)
{
const char *orgSrc;
if (src[0] == '/' || ((what & EP_SLASHES) && src[0] == '\\'))
{
// Path is already absolute; nothing to do
*skipSrc = 0;
return dest;
}
orgSrc = src;
#ifdef HAVE_DRIVE_LETTERS
if (isDriveLetter(src[0]) && (src[1] == ':'))
{
int letter;
if (src[2] == '/' || src[2] == '\\')
{
// Path is already absolute (of the form "d:/"); nothing to do
*skipSrc = 0;
return dest;
}
// Path is of the form "d:path", without a (back)slash after the
// semicolon.
#ifdef REJECT_DRIVE_PATH_WITHOUT_SLASH
// We reject paths of the form "d:foo/bar".
errno = EINVAL;
return NULL;
#elif defined(HAVE_CWD_PER_DRIVE)
// Paths of the form "d:foo/bar" are treated as "foo/bar" relative
// to the working directory of d:.
letter = tolower(src[0]) - 'a';
// _getdcwd() should only be called on drives that exist.
// This is weird though, because it means a race condition
// in between the existance check and the call to _getdcwd()
// cannot be avoided, unless a drive still exists for Windows
// when the physical drive is removed.
if (!driveLetterExists (letter))
{
errno = ENOENT;
return NULL;
}
// Get the working directory for a specific drive.
if (_getdcwd (letter + 1, dest, destLen) == NULL)
{
// errno is set
return NULL;
}
src += 2;
#else /* if !defined(HAVE_CWD_PER_DRIVE) */
// We treat paths of the form "d:foo/bar" as "d:/foo/bar".
if (destLen < 3) {
errno = ERANGE;
return NULL;
}
dest[0] = src[0];
dest[1] = ':';
dest[2] = '/';
*skipSrc = 2;
dest += 3;
return dest;
#endif /* HAVE_CWD_PER_DRIVE */
}
else
#endif /* HAVE_DRIVE_LETTERS */
{
// Relative dir
if (getcwd (dest, destLen) == NULL)
{
// errno is set
return NULL;
}
}
{
size_t tempLen;
tempLen = strlen (dest);
if (tempLen == 0)
{
// getcwd() or _getdcwd() returned a 0-length string.
errno = ENOENT;
return NULL;
}
dest += tempLen;
destLen -= tempLen;
}
if (dest[-1] != '/'
#ifdef BACKSLASH_IS_PATH_SEPARATOR
&& dest[-1] != '\\'
#endif /* BACKSLASH_IS_PATH_SEPARATOR */
)
{
// Need to add a slash.
// There's always space, as we overwrite the '\0' that getcwd()
// always returns.
dest[0] = '/';
dest++;
destLen--;
}
*skipSrc = (size_t) (src - orgSrc);
return dest;
}
// As strrchr, but starts searching from the indicated end of the string.
static char *
strrchr2(const char *start, int c, const char *end) {
for (;;) {
end--;
if (end < start)
return (char *) NULL;
if (*end == c)
return (char *) unconst(end);
}
}
#ifdef HAVE_UNC_PATHS
// returns 0 if the path is not a valid UNC path.
// Does not skip trailing slashes.
size_t
skipUNCServerShare(const char *inPath) {
const char *path = inPath;
// Skip the initial two backslashes.
if (path[0] != '\\' || path[1] != '\\')
return (size_t) 0;
path += 2;
// Skip the server part.
while (*path != '\\' && *path != '/') {
if (*path == '\0')
return (size_t) 0;
path++;
}
// Skip the seperator.
path++;
// Skip the share part.
while (*path != '\0' && *path != '\\' && *path != '/')
path++;
return (size_t) (path - inPath);
}
#endif /* HAVE_UNC_PATHS */

View File

@@ -1,165 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Contains code handling files
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "port.h"
#include "libs/uio.h"
#include "config.h"
#include "types.h"
#include "filintrn.h"
#include "libs/memlib.h"
#include "libs/log.h"
static int copyError(uio_Handle *srcHandle, uio_Handle *dstHandle,
uio_DirHandle *unlinkHandle, const char *unlinkPath, uint8 *buf);
bool
fileExists (const char *name)
{
return access (name, F_OK) == 0;
}
bool
fileExists2(uio_DirHandle *dir, const char *fileName)
{
uio_Stream *stream;
stream = uio_fopen (dir, fileName, "rb");
if (stream == NULL)
return 0;
uio_fclose (stream);
return 1;
}
/*
* Copy a file with path srcName to a file with name newName.
* If the destination already exists, the operation fails.
* Links are followed.
* Special files (fifos, char devices, block devices, etc) will be
* read as long as there is data available and the destination will be
* a regular file with that data.
* The new file will have the same permissions as the old.
* If an error occurs during copying, an attempt will be made to
* remove the copy.
*/
int
copyFile (uio_DirHandle *srcDir, const char *srcName,
uio_DirHandle *dstDir, const char *newName)
{
uio_Handle *src, *dst;
struct stat sb;
#define BUFSIZE 65536
uint8 *buf, *bufPtr;
ssize_t numInBuf, numWritten;
src = uio_open (srcDir, srcName, O_RDONLY
#ifdef WIN32
| O_BINARY
#endif
, 0);
if (src == NULL)
return -1;
if (uio_fstat (src, &sb) == -1)
return copyError (src, NULL, NULL, NULL, NULL);
dst = uio_open (dstDir, newName, O_WRONLY | O_CREAT | O_EXCL
#ifdef WIN32
| O_BINARY
#endif
, sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
if (dst == NULL)
return copyError (src, NULL, NULL, NULL, NULL);
buf = HMalloc(BUFSIZE);
// This was originally a statically allocated buffer,
// but as this function might be run from a thread with
// a small Stack, this is better.
while (1)
{
numInBuf = uio_read (src, buf, BUFSIZE);
if (numInBuf == -1)
{
if (errno == EINTR)
continue;
return copyError (src, dst, dstDir, newName, buf);
}
if (numInBuf == 0)
break;
bufPtr = buf;
do
{
numWritten = uio_write (dst, bufPtr, numInBuf);
if (numWritten == -1)
{
if (errno == EINTR)
continue;
return copyError (src, dst, dstDir, newName, buf);
}
numInBuf -= numWritten;
bufPtr += numWritten;
} while (numInBuf > 0);
}
HFree (buf);
uio_close (src);
uio_close (dst);
errno = 0;
return 0;
}
/*
* Closes srcHandle if it's not -1.
* Closes dstHandle if it's not -1.
* Removes unlinkpath from the unlinkHandle dir if it's not NULL.
* Frees 'buf' if not NULL.
* Always returns -1.
* errno is what was before the call.
*/
static int
copyError(uio_Handle *srcHandle, uio_Handle *dstHandle,
uio_DirHandle *unlinkHandle, const char *unlinkPath, uint8 *buf)
{
int savedErrno;
savedErrno = errno;
log_add (log_Debug, "Error while copying: %s", strerror (errno));
if (srcHandle != NULL)
uio_close (srcHandle);
if (dstHandle != NULL)
uio_close (dstHandle);
if (unlinkPath != NULL)
uio_unlink (unlinkHandle, unlinkPath);
if (buf != NULL)
HFree(buf);
errno = savedErrno;
return -1;
}

View File

@@ -1,24 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Contains code handling temporary files and dirs
#ifndef _FILEINTRN_H
#include "../file.h"
#endif /* _FILEINTRN_H */

View File

@@ -1,199 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Contains code handling temporary files and dirs
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifdef WIN32
# include <io.h>
#endif
#include <string.h>
#include <time.h>
#include "filintrn.h"
#include "libs/timelib.h"
#include "port.h"
#include "libs/compiler.h"
#include "libs/log.h"
#include "libs/memlib.h"
static char *tempDirName;
uio_DirHandle *tempDir;
static void
removeTempDir (void)
{
rmdir (tempDirName);
}
// Try if the null-terminated path 'dir' to a directory is valid
// as temp path.
// On success, 'buf' will be filled with the path, with a trailing /,
// null-terminated, and 0 is returned.
// On failure, EINVAL, ENAMETOOLONG, or one of the errors access() can return
// is returned, and the contents of buf is unspecified.
static int
tryTempDir (char *buf, size_t buflen, const char *dir)
{
size_t len;
int haveSlash;
if (dir == NULL)
return EINVAL;
if (dir[0] == '\0')
return EINVAL;
len = strlen (dir);
haveSlash = (dir[len - 1] == '/'
#ifdef WIN32
|| dir[len - 1] == '\\'
#endif
);
if ((haveSlash ? len : len + 1) >= buflen)
return ENAMETOOLONG;
strcpy (buf, dir);
#if 0
//def WIN32
{
char *bufPtr;
for (bufPtr = buf; *bufPtr != '\0'; bufPtr++)
{
if (*bufPtr == '\\')
*bufPtr = '/';
}
}
#endif
if (!haveSlash)
{
buf[len] = '/';
len++;
buf[len] = '\0';
}
if (access (buf, R_OK | W_OK) == -1)
return errno;
return 0;
}
static void
getTempDir (char *buf, size_t buflen) {
char cwd[PATH_MAX];
if (tryTempDir (buf, buflen, getenv("TMP")) &&
tryTempDir (buf, buflen, getenv("TEMP")) &&
#if !defined(WIN32) || defined (__CYGWIN__)
tryTempDir (buf, buflen, "/tmp/") &&
tryTempDir (buf, buflen, "/var/tmp/") &&
#endif
tryTempDir (buf, buflen, getcwd (cwd, sizeof cwd)))
{
log_add (log_Fatal, "Fatal Error: Cannot find a suitable location "
"to store temporary files.");
exit (EXIT_FAILURE);
}
}
// Sets the global var 'tempDir'
static int
mountTempDir(const char *name) {
static uio_AutoMount *autoMount[] = { NULL };
uio_MountHandle *tempHandle;
extern uio_Repository *repository;
tempHandle = uio_mountDir (repository, "/tmp/",
uio_FSTYPE_STDIO, NULL, NULL, name, autoMount,
uio_MOUNT_TOP, NULL);
if (tempHandle == NULL) {
int saveErrno = errno;
log_add (log_Fatal, "Fatal error: Couldn't mount temp dir '%s': "
"%s", name, strerror (errno));
errno = saveErrno;
return -1;
}
tempDir = uio_openDir (repository, "/tmp", 0);
if (tempDir == NULL) {
int saveErrno = errno;
log_add (log_Fatal, "Fatal error: Could not open temp dir: %s",
strerror (errno));
errno = saveErrno;
return -1;
}
return 0;
}
#define NUM_TEMP_RETRIES 16
// Number of files to try to open before giving up.
void
initTempDir (void) {
size_t len;
DWORD num;
int i;
char *tempPtr;
// Pointer to the location in the tempDirName string where the
// path to the temp dir ends and the dir starts.
tempDirName = HMalloc (PATH_MAX);
getTempDir (tempDirName, PATH_MAX - 21);
// reserve 8 chars for dirname, 1 for slash, and 12 for filename
len = strlen(tempDirName);
num = ((DWORD) time (NULL));
// num = GetTimeCounter () % 0xffffffff;
tempPtr = tempDirName + len;
for (i = 0; i < NUM_TEMP_RETRIES; i++)
{
sprintf (tempPtr, "%08x", num + i);
if (createDirectory (tempDirName, 0700) == -1)
continue;
// Success, we've got a temp dir.
tempDirName = HRealloc (tempDirName, len + 9);
atexit (removeTempDir);
if (mountTempDir (tempDirName) == -1)
exit (EXIT_FAILURE);
return;
}
// Failure, could not make a temporary directory.
log_add (log_Fatal, "Fatal error: Cannot get a name for a temporary "
"directory.");
exit (EXIT_FAILURE);
}
void
unInitTempDir (void) {
uio_closeDir(tempDir);
// the removing of the dir is handled via atexit
}
// return the path to a file in the temp dir with the specified filename.
// returns a pointer to a static buffer.
char *
tempFilePath (const char *filename) {
static char file[PATH_MAX];
if (snprintf (file, PATH_MAX, "%s/%s", tempDirName, filename) == -1) {
log_add (log_Fatal, "Path to temp file too long.");
exit (EXIT_FAILURE);
}
return file;
}

View File

@@ -1,457 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _GFXLIB_H
#define _GFXLIB_H
#include "port.h"
#include "libs/compiler.h"
typedef struct Color Color;
struct Color {
BYTE r;
BYTE g;
BYTE b;
BYTE a;
};
#include "libs/reslib.h"
typedef struct context_desc CONTEXT_DESC;
typedef struct frame_desc FRAME_DESC;
typedef struct font_desc FONT_DESC;
typedef struct drawable_desc DRAWABLE_DESC;
typedef CONTEXT_DESC *CONTEXT;
typedef FRAME_DESC *FRAME;
typedef FONT_DESC *FONT;
typedef DRAWABLE_DESC *DRAWABLE;
typedef UWORD TIME_VALUE;
#define TIME_SHIFT 8
#define MAX_TIME_VALUE ((1 << TIME_SHIFT) + 1)
typedef SWORD COORD;
static inline bool
sameColor(Color c1, Color c2)
{
return c1.r == c2.r &&
c1.g == c2.g &&
c1.b == c2.b &&
c1.a == c2.a;
}
// Transform a 5-bits color component to an 8-bits color component.
// Form 1, calculates '(r5 / 31.0) * 255.0, highest value is 0xff:
#define CC5TO8(c) (((c) << 3) | ((c) >> 2))
// Form 2, calculates '(r5 / 32.0) * 256.0, highest value is 0xf8:
//#define CC5TO8(c) ((c) << 3)
#define BUILD_COLOR(col, c256) col
// BUILD_COLOR used to combine a 15-bit RGB color tripple with a
// destination VGA palette index into a 32-bit value.
// Now, it is an empty wrapper which returns the first argument,
// which is of type Color, and ignores the second argument,
// the palette index.
//
// It is a remnant of 8bpp hardware paletted display (VGA).
// The palette index would be overwritten with the RGB value
// and the drawing op would use this index on screen.
// The palette indices 0-15, as used in DOS SC2, are unchanged
// from the standard VGA palette and are identical to 16-color EGA.
// Various frames, borders, menus, etc. frequently refer to these
// first 16 colors and normally do not change the RGB values from
// the standard ones (see colors.h; most likely unchanged from SC1)
// The palette index is meaningless in UQM for the most part.
// New code should just use index 0.
// Turn a 15 bits color into a 24-bits color.
// r, g, and b are each 5-bits color components.
static inline Color
colorFromRgb15 (BYTE r, BYTE g, BYTE b)
{
Color c;
c.r = CC5TO8 (r);
c.g = CC5TO8 (g);
c.b = CC5TO8 (b);
c.a = 0xff;
return c;
}
#define MAKE_RGB15(r, g, b) colorFromRgb15 ((r), (g), (b))
#ifdef NOTYET /* Need C'99 support */
#define MAKE_RGB15(r, g, b) (Color) { \
.r = CC5TO8 (r), \
.g = CC5TO8 (g), \
.b = CC5TO8 (b), \
.a = 0xff \
}
#endif
// Temporary, until we can use C'99 features. Then MAKE_RGB15 will be usable
// anywhere.
// This define is intended for global initialisations, where the
// expression must be constant.
#define MAKE_RGB15_INIT(r, g, b) { \
CC5TO8 (r), \
CC5TO8 (g), \
CC5TO8 (b), \
0xff \
}
static inline Color
buildColorRgba (BYTE r, BYTE g, BYTE b, BYTE a)
{
Color c;
c.r = r;
c.g = g;
c.b = b;
c.a = a;
return c;
}
#define BUILD_COLOR_RGBA(r, g, b, a) \
buildColorRgba ((r), (g), (b), (a))
typedef BYTE CREATE_FLAGS;
// WANT_MASK is deprecated (and non-functional). It used to generate a bitmap
// of changed pixels for a target DRAWABLE, so that DRAW_SUBTRACTIVE could
// paint background pixels over them, i.e. a revert draw. The backgrounds
// are fully erased now instead.
#define WANT_MASK (CREATE_FLAGS)(1 << 0)
#define WANT_PIXMAP (CREATE_FLAGS)(1 << 1)
// MAPPED_TO_DISPLAY is deprecated but still checked by LoadDisplayPixmap().
// Its former use was to indicate a pre-scaled graphic for the display.
#define MAPPED_TO_DISPLAY (CREATE_FLAGS)(1 << 2)
#define WANT_ALPHA (CREATE_FLAGS)(1 << 3)
typedef struct extent
{
COORD width, height;
} EXTENT;
typedef struct point
{
COORD x, y;
} POINT;
typedef struct stamp
{
POINT origin;
FRAME frame;
} STAMP;
typedef struct rect
{
POINT corner;
EXTENT extent;
} RECT;
typedef struct line
{
POINT first, second;
} LINE;
static inline POINT
MAKE_POINT (COORD x, COORD y)
{
POINT pt = {x, y};
return pt;
}
static inline bool
pointsEqual (POINT p1, POINT p2)
{
return p1.x == p2.x && p1.y == p2.y;
}
static inline bool
extentsEqual (EXTENT e1, EXTENT e2)
{
return e1.width == e2.width && e1.height == e2.height;
}
static inline bool
rectsEqual (RECT r1, RECT r2)
{
return pointsEqual (r1.corner, r2.corner)
&& extentsEqual (r1.extent, r2.extent);
}
static inline bool
pointWithinRect (RECT r, POINT p)
{
return p.x >= r.corner.x && p.y >= r.corner.y
&& p.x < r.corner.x + r.extent.width
&& p.y < r.corner.y + r.extent.height;
}
typedef enum
{
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT
} TEXT_ALIGN;
typedef enum
{
VALIGN_TOP,
VALIGN_MIDDLE,
VALIGN_BOTTOM
} TEXT_VALIGN;
typedef struct text
{
POINT baseline;
const UNICODE *pStr;
TEXT_ALIGN align;
COUNT CharCount;
} TEXT;
#include "libs/strlib.h"
typedef STRING_TABLE COLORMAP_REF;
typedef STRING COLORMAP;
// COLORMAPPTR is really a pointer to colortable entry structure
// which is documented in doc/devel/strtab, .ct files section
typedef void *COLORMAPPTR;
#include "graphics/prim.h"
typedef BYTE BATCH_FLAGS;
// This flag is currently unused but it might make sense to restore it
#define BATCH_BUILD_PAGE (BATCH_FLAGS)(1 << 0)
typedef struct
{
TIME_VALUE last_time_val;
POINT EndPoint;
STAMP IntersectStamp;
} INTERSECT_CONTROL;
typedef BYTE INTERSECT_CODE;
#define INTERSECT_LEFT (INTERSECT_CODE)(1 << 0)
#define INTERSECT_TOP (INTERSECT_CODE)(1 << 1)
#define INTERSECT_RIGHT (INTERSECT_CODE)(1 << 2)
#define INTERSECT_BOTTOM (INTERSECT_CODE)(1 << 3)
#define INTERSECT_NOCLIP (INTERSECT_CODE)(1 << 7)
#define INTERSECT_ALL_SIDES (INTERSECT_CODE)(INTERSECT_LEFT | \
INTERSECT_TOP | \
INTERSECT_RIGHT | \
INTERSECT_BOTTOM)
typedef POINT HOT_SPOT;
extern HOT_SPOT MAKE_HOT_SPOT (COORD, COORD);
extern INTERSECT_CODE BoxIntersect (RECT *pr1, RECT *pr2, RECT *printer);
extern void BoxUnion (RECT *pr1, RECT *pr2, RECT *punion);
typedef enum
{
FadeAllToWhite = 250,
FadeSomeToWhite,
FadeAllToBlack,
FadeAllToColor,
FadeSomeToBlack,
FadeSomeToColor
} ScreenFadeType;
typedef enum
{
DRAW_REPLACE = 0,
// Pixels in the target FRAME are replaced entirely.
// Non-stamp primitives with Color.a < 255 to RGB targets are
// equivalent to DRAW_ALPHA with (DrawMode.factor = Color.a),
// except the Text primitives.
// DrawMode.factor: ignored
// Text: supported (except DRAW_ALPHA via Color.a)
// RGBA sources (WANT_ALPHA): per-pixel alpha blending performed
// RGBA targets (WANT_ALPHA): replace directly supported
DRAW_ADDITIVE,
// Pixel channels of the source FRAME or Color channels of
// a primitive are modulated by (DrawMode.factor / 255) and added
// to the pixel channels of the target FRAME.
// DrawMode.factor range: -32767..32767 (negative values make
// draw subtractive); 255 = 1:1 ratio
// Text: not yet supported
// RGBA sources (WANT_ALPHA): alpha channel ignored
// RGBA targets (WANT_ALPHA): not yet supported
DRAW_ALPHA,
// Pixel channels of the source FRAME or Color channels of
// a primitive are modulated by (DrawMode.factor / 255) and added
// to the pixel channels of the target FRAME, modulated by
// (1 - DrawMode.factor / 255)
// DrawMode.factor range: 0..255; 255 = fully opaque
// Text: supported
// RGBA sources (WANT_ALPHA): alpha channel ignored
// RGBA targets (WANT_ALPHA): not yet supported
DRAW_DEFAULT = DRAW_REPLACE,
} DrawKind;
typedef struct
{
BYTE kind;
SWORD factor;
} DrawMode;
#define DRAW_REPLACE_MODE MAKE_DRAW_MODE (DRAW_REPLACE, 0)
#define DRAW_FACTOR_1 0xff
static inline DrawMode
MAKE_DRAW_MODE (DrawKind kind, SWORD factor)
{
DrawMode mode;
mode.kind = kind;
mode.factor = factor;
return mode;
}
extern CONTEXT SetContext (CONTEXT Context);
extern Color SetContextForeGroundColor (Color Color);
extern Color GetContextForeGroundColor (void);
extern Color SetContextBackGroundColor (Color Color);
extern Color GetContextBackGroundColor (void);
extern FRAME SetContextFGFrame (FRAME Frame);
extern FRAME GetContextFGFrame (void);
// Context cliprect defines the drawing bounds. Additionally, all
// drawing positions (x,y) are relative to the cliprect corner.
extern BOOLEAN SetContextClipRect (RECT *pRect);
// The returned rect is always filled in. If the context cliprect
// is undefined, the returned rect has foreground frame dimensions.
extern BOOLEAN GetContextClipRect (RECT *pRect);
// The actual origin will be orgOffset + context ClipRect.corner
extern POINT SetContextOrigin (POINT orgOffset);
extern DrawMode SetContextDrawMode (DrawMode);
extern DrawMode GetContextDrawMode (void);
// 'area' may be NULL to copy the entire CONTEXT cliprect
// 'area' is relative to the CONTEXT cliprect
extern DRAWABLE CopyContextRect (const RECT* area);
extern TIME_VALUE DrawablesIntersect (INTERSECT_CONTROL *pControl0,
INTERSECT_CONTROL *pControl1, TIME_VALUE max_time_val);
extern void DrawStamp (STAMP *pStamp);
extern void DrawFilledStamp (STAMP *pStamp);
extern void DrawPoint (POINT *pPoint);
extern void DrawRectangle (RECT *pRect);
extern void DrawFilledRectangle (RECT *pRect);
extern void DrawLine (LINE *pLine);
extern void font_DrawText (TEXT *pText);
extern void font_DrawTracedText (TEXT *pText, Color text, Color trace);
extern void DrawBatch (PRIMITIVE *pBasePrim, PRIM_LINKS PrimLinks,
BATCH_FLAGS BatchFlags);
extern void BatchGraphics (void);
extern void UnbatchGraphics (void);
extern void FlushGraphics (void);
extern void ClearDrawable (void);
#ifdef DEBUG
extern CONTEXT CreateContextAux (const char *name);
#define CreateContext(name) CreateContextAux((name))
#else /* if !defined(DEBUG) */
extern CONTEXT CreateContextAux (void);
#define CreateContext(name) CreateContextAux()
#endif /* !defined(DEBUG) */
extern BOOLEAN DestroyContext (CONTEXT ContextRef);
extern DRAWABLE CreateDisplay (CREATE_FLAGS CreateFlags, SIZE *pwidth,
SIZE *pheight);
extern DRAWABLE CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width,
SIZE height, COUNT num_frames);
extern BOOLEAN DestroyDrawable (DRAWABLE Drawable);
extern BOOLEAN GetFrameRect (FRAME Frame, RECT *pRect);
#ifdef DEBUG
extern const char *GetContextName (CONTEXT context);
extern CONTEXT GetFirstContext (void);
extern CONTEXT GetNextContext (CONTEXT context);
extern size_t GetContextCount (void);
#endif /* DEBUG */
extern HOT_SPOT SetFrameHot (FRAME Frame, HOT_SPOT HotSpot);
extern HOT_SPOT GetFrameHot (FRAME Frame);
extern BOOLEAN InstallGraphicResTypes (void);
extern DRAWABLE LoadGraphicFile (const char *pStr);
extern FONT LoadFontFile (const char *pStr);
extern void *LoadGraphicInstance (RESOURCE res);
extern DRAWABLE LoadDisplayPixmap (const RECT *area, FRAME frame);
extern FRAME SetContextFontEffect (FRAME EffectFrame);
extern FONT SetContextFont (FONT Font);
extern BOOLEAN DestroyFont (FONT FontRef);
// The returned pRect is relative to the context drawing origin
extern BOOLEAN TextRect (TEXT *pText, RECT *pRect, BYTE *pdelta);
extern BOOLEAN GetContextFontLeading (SIZE *pheight);
extern BOOLEAN GetContextFontLeadingWidth (SIZE *pwidth);
extern COUNT GetFrameCount (FRAME Frame);
extern COUNT GetFrameIndex (FRAME Frame);
extern FRAME SetAbsFrameIndex (FRAME Frame, COUNT FrameIndex);
extern FRAME SetRelFrameIndex (FRAME Frame, SIZE FrameOffs);
extern FRAME SetEquFrameIndex (FRAME DstFrame, FRAME SrcFrame);
extern FRAME IncFrameIndex (FRAME Frame);
extern FRAME DecFrameIndex (FRAME Frame);
extern DRAWABLE CopyFrameRect (FRAME Frame, const RECT *area);
extern DRAWABLE CloneFrame (FRAME Frame);
extern DRAWABLE RotateFrame (FRAME Frame, int angle_deg);
extern DRAWABLE RescaleFrame (FRAME, int width, int height);
// This pair works for both paletted and trucolor frames
extern BOOLEAN ReadFramePixelColors (FRAME frame, Color *pixels,
int width, int height);
extern BOOLEAN WriteFramePixelColors (FRAME frame, const Color *pixels,
int width, int height);
// This pair only works for paletted frames
extern BOOLEAN ReadFramePixelIndexes (FRAME frame, BYTE *pixels,
int width, int height);
extern BOOLEAN WriteFramePixelIndexes (FRAME frame, const BYTE *pixels,
int width, int height);
extern void SetFrameTransparentColor (FRAME, Color);
// If the frame is an active SCREEN_DRAWABLE, this call must be
// preceeded by FlushGraphics() for draw commands to have taken effect
extern Color GetFramePixel (FRAME, POINT pixelPt);
extern FRAME CaptureDrawable (DRAWABLE Drawable);
extern DRAWABLE ReleaseDrawable (FRAME Frame);
extern DRAWABLE GetFrameParentDrawable (FRAME Frame);
extern BOOLEAN SetColorMap (COLORMAPPTR ColorMapPtr);
extern DWORD XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval);
extern DWORD FadeScreen (ScreenFadeType fadeType, SIZE TimeInterval);
extern void FlushColorXForms (void);
#define InitColorMapResources InitStringTableResources
#define LoadColorMapFile LoadStringTableFile
#define LoadColorMapInstance LoadStringTableInstance
#define CaptureColorMap CaptureStringTable
#define ReleaseColorMap ReleaseStringTable
#define DestroyColorMap DestroyStringTable
#define GetColorMapRef GetStringTable
#define GetColorMapCount GetStringTableCount
#define GetColorMapIndex GetStringTableIndex
#define SetAbsColorMapIndex SetAbsStringTableIndex
#define SetRelColorMapIndex SetRelStringTableIndex
#define GetColorMapLength GetStringLengthBin
extern COLORMAPPTR GetColorMapAddress (COLORMAP);
void SetSystemRect (const RECT *pRect);
void ClearSystemRect (void);
#endif /* _GFXLIB_H */

View File

@@ -1,9 +0,0 @@
if [ "$uqm_GFXMODULE" = "sdl" ]; then
uqm_SUBDIRS="sdl"
fi
uqm_CFILES="boxint.c clipline.c cmap.c context.c drawable.c filegfx.c
bbox.c dcqueue.c gfxload.c
font.c frame.c gfx_common.c intersec.c loaddisp.c
pixmap.c resgfx.c tfb_draw.c tfb_prim.c widgets.c"

View File

@@ -1,133 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "libs/graphics/bbox.h"
TFB_BoundingBox TFB_BBox;
int maxWidth;
int maxHeight;
void
TFB_BBox_Init (int width, int height)
{
maxWidth = width;
maxHeight = height;
TFB_BBox.clip.extent.width = width;
TFB_BBox.clip.extent.height = height;
}
void
TFB_BBox_Reset (void)
{
TFB_BBox.valid = 0;
}
void
TFB_BBox_SetClipRect (const RECT *r)
{
if (!r)
{ /* No clipping -- full rect */
TFB_BBox.clip.corner.x = 0;
TFB_BBox.clip.corner.y = 0;
TFB_BBox.clip.extent.width = maxWidth;
TFB_BBox.clip.extent.height = maxHeight;
return;
}
TFB_BBox.clip = *r;
/* Make sure the cliprect is sane */
if (TFB_BBox.clip.corner.x < 0)
TFB_BBox.clip.corner.x = 0;
if (TFB_BBox.clip.corner.y < 0)
TFB_BBox.clip.corner.y = 0;
if (TFB_BBox.clip.corner.x + TFB_BBox.clip.extent.width > maxWidth)
TFB_BBox.clip.extent.width = maxWidth - TFB_BBox.clip.corner.x;
if (TFB_BBox.clip.corner.y + TFB_BBox.clip.extent.height > maxHeight)
TFB_BBox.clip.extent.height = maxHeight - TFB_BBox.clip.corner.y;
}
void
TFB_BBox_RegisterPoint (int x, int y)
{
int x1 = TFB_BBox.clip.corner.x;
int y1 = TFB_BBox.clip.corner.y;
int x2 = TFB_BBox.clip.corner.x + TFB_BBox.clip.extent.width - 1;
int y2 = TFB_BBox.clip.corner.y + TFB_BBox.clip.extent.height - 1;
/* Constrain coordinates */
if (x < x1) x = x1;
if (x >= x2) x = x2;
if (y < y1) y = y1;
if (y >= y2) y = y2;
/* Is this the first point? If so, set a pixel-region and return. */
if (!TFB_BBox.valid)
{
TFB_BBox.valid = 1;
TFB_BBox.region.corner.x = x;
TFB_BBox.region.corner.y = y;
TFB_BBox.region.extent.width = 1;
TFB_BBox.region.extent.height = 1;
return;
}
/* Otherwise expand the rectangle if necessary. */
x1 = TFB_BBox.region.corner.x;
y1 = TFB_BBox.region.corner.y;
x2 = TFB_BBox.region.corner.x + TFB_BBox.region.extent.width - 1;
y2 = TFB_BBox.region.corner.y + TFB_BBox.region.extent.height - 1;
if (x < x1) {
TFB_BBox.region.corner.x = x;
TFB_BBox.region.extent.width += x1 - x;
}
if (y < y1) {
TFB_BBox.region.corner.y = y;
TFB_BBox.region.extent.height += y1 - y;
}
if (x > x2) {
TFB_BBox.region.extent.width += x - x2;
}
if (y > y2) {
TFB_BBox.region.extent.height += y - y2;
}
}
void
TFB_BBox_RegisterRect (const RECT *r)
{
/* RECT will still register as a corner point of the cliprect even
* if it does not intersect with the cliprect at all. This is not
* a problem, as more is not less. */
TFB_BBox_RegisterPoint (r->corner.x, r->corner.y);
TFB_BBox_RegisterPoint (r->corner.x + r->extent.width - 1,
r->corner.y + r->extent.height - 1);
}
void
TFB_BBox_RegisterCanvas (TFB_Canvas c, int x, int y)
{
RECT r;
r.corner.x = x;
r.corner.y = y;
TFB_DrawCanvas_GetExtent (c, &r.extent);
TFB_BBox_RegisterRect (&r);
}

View File

@@ -1,46 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef BBOX_H_INCL__
#define BBOX_H_INCL__
#include "libs/gfxlib.h"
#include "libs/graphics/tfb_draw.h"
/* Bounding Box operations. These operations are NOT synchronized.
* However, they should only be accessed by TFB_FlushGraphics and
* TFB_SwapBuffers, or the routines that they exclusively call -- all
* of which are only callable by the thread that is permitted to touch
* the screen. No explicit locks should therefore be required. */
typedef struct {
int valid; // If zero, the next point registered becomes the region
RECT region; // The actual modified rectangle
RECT clip; // Points outside of this rectangle are pushed to
// the closest border point
} TFB_BoundingBox;
extern TFB_BoundingBox TFB_BBox;
void TFB_BBox_RegisterPoint (int x, int y);
void TFB_BBox_RegisterRect (const RECT *r);
void TFB_BBox_RegisterCanvas (TFB_Canvas c, int x, int y);
void TFB_BBox_Init (int width, int height);
void TFB_BBox_Reset (void);
void TFB_BBox_SetClipRect (const RECT *r);
#endif /* BBOX_H_INCL__ */

View File

@@ -1,183 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
#undef MIN
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
#undef MAX
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
INTERSECT_CODE
BoxIntersect (RECT *pr1, RECT *pr2, RECT *pinter)
{
INTERSECT_CODE intersect_code;
COORD x1;
SIZE w1, w2, delta;
intersect_code = INTERSECT_NOCLIP;
x1 = pr1->corner.x - pr2->corner.x;
w1 = pr1->extent.width;
w2 = pr2->extent.width;
if ((delta = w2 - x1) <= w1)
{
if (delta != w1)
{
w1 = delta;
intersect_code &= ~INTERSECT_NOCLIP;
}
intersect_code |= INTERSECT_RIGHT;
}
if (x1 <= 0)
{
if (x1 < 0)
{
w1 += x1;
x1 = 0;
intersect_code &= ~INTERSECT_NOCLIP;
}
intersect_code |= INTERSECT_LEFT;
}
if (w1 > 0)
{
#define h2 w2
COORD y1;
SIZE h1;
y1 = pr1->corner.y - pr2->corner.y;
h1 = pr1->extent.height;
h2 = pr2->extent.height;
if ((delta = h2 - y1) <= h1)
{
if (delta != h1)
{
h1 = delta;
intersect_code &= ~INTERSECT_NOCLIP;
}
intersect_code |= INTERSECT_BOTTOM;
}
if (y1 <= 0)
{
if (y1 < 0)
{
h1 += y1;
y1 = 0;
intersect_code &= ~INTERSECT_NOCLIP;
}
intersect_code |= INTERSECT_TOP;
}
if (h1 > 0)
{
pinter->corner.x = x1 + pr2->corner.x;
pinter->corner.y = y1 + pr2->corner.y;
pinter->extent.width = w1;
pinter->extent.height = h1;
return (intersect_code);
}
#undef h2
}
return ((INTERSECT_CODE)0);
}
void
BoxUnion (RECT *pr1, RECT *pr2, RECT *punion)
{
#if NEVER // Part of lower FIXME.
COORD x2, y2, w2, h2;
#endif // NEVER
// Union is A AND B, put together, correct? Returns a bigger box that
// encompasses the two.
punion->corner.x = MIN(pr1->corner.x, pr2->corner.x);
punion->corner.y = MIN(pr1->corner.y, pr2->corner.y);
punion->extent.width = MAX(pr1->corner.x + pr1->extent.width,
pr2->corner.x + pr2->extent.width) - punion->corner.x;
punion->extent.height = MAX(pr1->corner.y + pr1->extent.height,
pr2->corner.y + pr2->extent.height) - punion->corner.y;
#if NEVER // FIXME - I think this is broken, but keeping it around for reference
// FIXME - just in case.
#if 1 /* alter based on 0 widths */
x2 =
(pr1->corner.x < pr2->corner.x)? pr1->corner.x : pr2->corner.x;
y2 =
(pr1->corner.y < pr2->corner.y)? pr1->corner.y : pr2->corner.y;
w2 = (
((pr1->corner.x + pr1->extent.width) > (pr2->corner.x + pr2->extent.width))?
(pr1->corner.x + pr1->extent.width) : (pr2->corner.x + pr2->extent.width)
) - punion->corner.x;
h2 = (
((pr1->corner.y + pr1->extent.height) > (pr2->corner.y + pr2->extent.height))?
(pr1->corner.y + pr1->extent.height) : (pr2->corner.y + pr2->extent.height)
) - punion->corner.y;
#else
SIZE delta;
COORD x1, y1, w1, h1;
x1 = pr1->corner.x;
w1 = pr1->extent.width;
x2 = pr2->corner.x;
w2 = pr2->extent.width;
if ((delta = x1 - x2) >= 0)
w1 += delta;
else
{
w2 -= delta;
x2 += delta;
}
y1 = pr1->corner.y;
h1 = pr1->extent.height;
y2 = pr2->corner.y;
h2 = pr2->extent.height;
if ((delta = y1 - y2) >= 0)
h1 += delta;
else
{
h2 -= delta;
y2 += delta;
}
if ((delta = w1 - w2) > 0)
w2 += delta;
if ((delta = h1 - h2) > 0)
h2 += delta;
#endif
punion->corner.x = x2;
punion->corner.y = y2;
punion->extent.width = w2;
punion->extent.height = h2;
#endif // NEVER
}

View File

@@ -1,241 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
INTERSECT_CODE
_clip_line (const RECT *pClipRect, BRESENHAM_LINE *pLine)
{
COORD p;
COORD x0, y0, xmin, ymin, xmax, ymax;
SIZE abs_delta_x, abs_delta_y;
INTERSECT_CODE intersect_code;
xmin = pClipRect->corner.x;
ymin = pClipRect->corner.y;
xmax = pClipRect->corner.x + pClipRect->extent.width - 1;
ymax = pClipRect->corner.y + pClipRect->extent.height - 1;
if (pLine->first.x <= pLine->second.x)
pLine->end_points_exchanged = FALSE;
else
{
p = pLine->first.x;
pLine->first.x = pLine->second.x;
pLine->second.x = p;
p = pLine->first.y;
pLine->first.y = pLine->second.y;
pLine->second.y = p;
pLine->end_points_exchanged = TRUE;
}
if (pLine->first.x > xmax || pLine->second.x < xmin ||
(pLine->first.y > ymax && pLine->second.y > ymax) ||
(pLine->first.y < ymin && pLine->second.y < ymin))
return ((INTERSECT_CODE)0);
intersect_code = INTERSECT_NOCLIP;
x0 = y0 = 0;
abs_delta_x = (pLine->second.x - pLine->first.x) << 1;
abs_delta_y = (pLine->second.y - pLine->first.y) << 1;
pLine->abs_delta_x = abs_delta_x;
pLine->abs_delta_y = abs_delta_y;
if (abs_delta_y == 0)
{
if (pLine->first.x < xmin)
{
pLine->first.x = xmin;
intersect_code |= INTERSECT_LEFT;
}
if (pLine->second.x > xmax)
{
pLine->second.x = xmax;
intersect_code |= INTERSECT_RIGHT;
}
}
else if (abs_delta_x == 0)
{
if (abs_delta_y < 0)
{
p = pLine->first.y;
pLine->first.y = pLine->second.y;
pLine->second.y = p;
pLine->abs_delta_y =
abs_delta_y = -abs_delta_y;
}
if (pLine->first.y < ymin)
{
pLine->first.y = ymin;
intersect_code |= INTERSECT_TOP;
}
if (pLine->second.y > ymax)
{
pLine->second.y = ymax;
intersect_code |= INTERSECT_BOTTOM;
}
}
else
{
COORD x1, y1;
p = pLine->first.x;
x1 = pLine->second.x - p;
xmin = xmin - p;
xmax = xmax - p;
p = pLine->first.y;
if (abs_delta_y > 0)
{
y1 = pLine->second.y - p;
ymin = ymin - p;
ymax = ymax - p;
}
else
{
y1 = p - pLine->second.y;
ymin = p - ymin;
ymax = p - ymax;
p = ymin;
ymin = ymax;
ymax = p;
abs_delta_y = -abs_delta_y;
}
if (abs_delta_x > abs_delta_y)
{
SIZE half_dx;
half_dx = abs_delta_x >> 1;
if (x0 < xmin)
{
if ((y0 = (COORD)(((long)abs_delta_y *
(x0 = xmin) + half_dx) / abs_delta_x)) > ymax)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_LEFT;
}
if (x1 > xmax)
{
if ((y1 = (COORD)(((long)abs_delta_y *
(x1 = xmax) + half_dx) / abs_delta_x)) < ymin)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_RIGHT;
}
if (y0 < ymin)
{
if ((x0 = (COORD)(((long)abs_delta_x *
(y0 = ymin) - half_dx + (abs_delta_y - 1)) /
abs_delta_y)) > xmax)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_TOP;
intersect_code &= ~INTERSECT_LEFT;
}
if (y1 > ymax)
{
if ((x1 = (COORD)(((long)abs_delta_x *
((y1 = ymax) + 1) - half_dx + (abs_delta_y - 1)) /
abs_delta_y) - 1) < xmin)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_BOTTOM;
intersect_code &= ~INTERSECT_RIGHT;
}
}
else
{
SIZE half_dy;
half_dy = abs_delta_y >> 1;
if (y0 < ymin)
{
if ((x0 = (COORD)(((long)abs_delta_x *
(y0 = ymin) + half_dy) / abs_delta_y)) > xmax)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_TOP;
}
if (y1 > ymax)
{
if ((x1 = (COORD)(((long)abs_delta_x *
(y1 = ymax) + half_dy) / abs_delta_y)) < xmin)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_BOTTOM;
}
if (x0 < xmin)
{
if ((y0 = (COORD)(((long)abs_delta_y *
(x0 = xmin) - half_dy + (abs_delta_x - 1)) /
abs_delta_x)) > ymax)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_LEFT;
intersect_code &= ~INTERSECT_TOP;
}
if (x1 > xmax)
{
if ((y1 = (COORD)(((long)abs_delta_y *
((x1 = xmax) + 1) - half_dy + (abs_delta_x - 1)) /
abs_delta_x) - 1) < ymin)
return ((INTERSECT_CODE)0);
intersect_code |= INTERSECT_RIGHT;
intersect_code &= ~INTERSECT_BOTTOM;
}
}
pLine->second.x = pLine->first.x + x1;
pLine->first.x += x0;
if (pLine->abs_delta_y > 0)
{
pLine->second.y = pLine->first.y + y1;
pLine->first.y += y0;
}
else
{
INTERSECT_CODE y_code;
pLine->second.y = pLine->first.y - y1;
pLine->first.y -= y0;
y_code = (INTERSECT_CODE)(intersect_code
& (INTERSECT_TOP | INTERSECT_BOTTOM));
if (y_code && y_code != (INTERSECT_TOP | INTERSECT_BOTTOM))
intersect_code ^= (INTERSECT_TOP | INTERSECT_BOTTOM);
}
}
if (!(intersect_code & INTERSECT_ALL_SIDES))
{
if (abs_delta_x > abs_delta_y)
pLine->error_term = -(SIZE)(abs_delta_x >> 1);
else
pLine->error_term = -(SIZE)(abs_delta_y >> 1);
}
else
{
intersect_code &= ~INTERSECT_NOCLIP;
if (abs_delta_x > abs_delta_y)
pLine->error_term = (SIZE)((x0 * (long)abs_delta_y) -
(y0 * (long)abs_delta_x)) - (abs_delta_x >> 1);
else
pLine->error_term = (SIZE)((y0 * (long)abs_delta_x) -
(x0 * (long)abs_delta_y)) - (abs_delta_y >> 1);
}
return (pLine->intersect_code = intersect_code);
}

View File

@@ -1,639 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "libs/graphics/cmap.h"
#include "libs/threadlib.h"
#include "libs/timelib.h"
#include "libs/inplib.h"
#include "libs/strlib.h"
// for GetStringAddress()
#include "libs/log.h"
#include <string.h>
#include <stdlib.h>
typedef struct xform_control
{
int CMapIndex; // -1 means unused
COLORMAPPTR CMapPtr;
SIZE Ticks;
DWORD StartTime;
DWORD EndTime;
Color OldCMap[NUMBER_OF_PLUTVALS];
} XFORM_CONTROL;
#define MAX_XFORMS 16
static struct
{
XFORM_CONTROL TaskControl[MAX_XFORMS];
volatile int Highest;
// 'pending' is Highest >= 0
Mutex Lock;
} XFormControl;
static int fadeAmount = FADE_NORMAL_INTENSITY;
static int fadeDelta;
static TimeCount fadeStartTime;
static sint32 fadeInterval;
#define SPARE_COLORMAPS 20
// Colormaps are rapidly replaced in some parts of the game, so
// it pays to have some spares on hand
static TFB_ColorMap *poolhead;
static int poolcount;
static TFB_ColorMap * colormaps[MAX_COLORMAPS];
static int mapcount;
Mutex maplock;
void
InitColorMaps (void)
{
int i;
// init colormaps
maplock = CreateMutex ("Colormaps Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
// init xform control
XFormControl.Highest = -1;
XFormControl.Lock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
for (i = 0; i < MAX_XFORMS; ++i)
XFormControl.TaskControl[i].CMapIndex = -1;
}
void
UninitColorMaps (void)
{
TFB_ColorMap *next;
// free spares
for ( ; poolhead; poolhead = next)
{
next = poolhead->next;
HFree (poolhead);
}
// uninit xform control
DestroyMutex (XFormControl.Lock);
// uninit colormaps
DestroyMutex (maplock);
}
static inline TFB_ColorMap *
alloc_colormap (void)
// returns an addrefed object
{
TFB_ColorMap *map;
if (poolhead)
{ // have some spares
map = poolhead;
poolhead = map->next;
--poolcount;
}
else
{ // no spares, need a new one
map = HMalloc (sizeof (*map));
map->palette = AllocNativePalette ();
if (!map->palette)
{
HFree (map);
return NULL;
}
}
map->next = NULL;
map->index = -1;
map->refcount = 1;
map->version = 0;
return map;
}
static TFB_ColorMap *
clone_colormap (TFB_ColorMap *from, int index)
// returns an addrefed object
{
TFB_ColorMap *map;
map = alloc_colormap ();
if (!map)
{
log_add (log_Warning, "FATAL: clone_colormap(): "
"could not allocate a map");
exit (EXIT_FAILURE);
}
else
{ // fresh new map
map->index = index;
if (from)
map->version = from->version;
}
map->version++;
return map;
}
static inline void
free_colormap (TFB_ColorMap *map)
{
if (!map)
{
log_add (log_Warning, "free_colormap(): tried to free a NULL map");
return;
}
if (poolcount < SPARE_COLORMAPS)
{ // return to the spare pool
map->next = poolhead;
poolhead = map;
++poolcount;
}
else
{ // don't need any more spares
FreeNativePalette (map->palette);
HFree (map);
}
}
static inline TFB_ColorMap *
get_colormap (int index)
{
TFB_ColorMap *map;
map = colormaps[index];
if (!map)
{
log_add (log_Fatal, "BUG: get_colormap(): map not present");
exit (EXIT_FAILURE);
}
map->refcount++;
return map;
}
static inline void
release_colormap (TFB_ColorMap *map)
{
if (!map)
return;
if (map->refcount <= 0)
{
log_add (log_Warning, "BUG: release_colormap(): refcount not >0");
return;
}
map->refcount--;
if (map->refcount == 0)
free_colormap (map);
}
void
TFB_ReturnColorMap (TFB_ColorMap *map)
{
LockMutex (maplock);
release_colormap (map);
UnlockMutex (maplock);
}
TFB_ColorMap *
TFB_GetColorMap (int index)
{
TFB_ColorMap *map;
LockMutex (maplock);
map = get_colormap (index);
UnlockMutex (maplock);
return map;
}
void
GetColorMapColors (Color *colors, TFB_ColorMap *map)
{
int i;
if (!map)
return;
for (i = 0; i < NUMBER_OF_PLUTVALS; ++i)
colors[i] = GetNativePaletteColor (map->palette, i);
}
BOOLEAN
SetColorMap (COLORMAPPTR map)
{
int start, end;
int total_size;
UBYTE *colors = (UBYTE*)map;
TFB_ColorMap **mpp;
if (!map)
return TRUE;
start = *colors++;
end = *colors++;
if (start > end)
{
log_add (log_Warning, "ERROR: SetColorMap(): "
"starting map (%d) not less or eq ending (%d)",
start, end);
return FALSE;
}
if (start >= MAX_COLORMAPS)
{
log_add (log_Warning, "ERROR: SetColorMap(): "
"starting map (%d) beyond range (0-%d)",
start, (int)MAX_COLORMAPS - 1);
return FALSE;
}
if (end >= MAX_COLORMAPS)
{
log_add (log_Warning, "SetColorMap(): "
"ending map (%d) beyond range (0-%d)\n",
end, (int)MAX_COLORMAPS - 1);
end = MAX_COLORMAPS - 1;
}
total_size = end + 1;
LockMutex (maplock);
if (total_size > mapcount)
mapcount = total_size;
// parse the supplied PLUTs into our colormaps
for (mpp = colormaps + start; start <= end; ++start, ++mpp)
{
int i;
TFB_ColorMap *newmap;
TFB_ColorMap *oldmap;
oldmap = *mpp;
newmap = clone_colormap (oldmap, start);
for (i = 0; i < NUMBER_OF_PLUTVALS; ++i, colors += PLUTVAL_BYTE_SIZE)
{
Color color;
color.a = 0xff;
color.r = colors[PLUTVAL_RED];
color.g = colors[PLUTVAL_GREEN];
color.b = colors[PLUTVAL_BLUE];
SetNativePaletteColor (newmap->palette, i, color);
}
*mpp = newmap;
release_colormap (oldmap);
}
UnlockMutex (maplock);
return TRUE;
}
/* Fade Transforms */
int
GetFadeAmount (void)
{
int newAmount;
LockMutex (XFormControl.Lock);
if (fadeInterval)
{ // have a pending fade
TimeCount Now = GetTimeCounter ();
sint32 elapsed;
elapsed = Now - fadeStartTime;
if (elapsed > fadeInterval)
elapsed = fadeInterval;
newAmount = fadeAmount + (long)fadeDelta * elapsed / fadeInterval;
if (elapsed >= fadeInterval)
{ // fade is over
fadeAmount = newAmount;
fadeInterval = 0;
}
}
else
{ // no fade pending, return the current
newAmount = fadeAmount;
}
UnlockMutex (XFormControl.Lock);
return newAmount;
}
static void
finishPendingFade (void)
{
if (fadeInterval)
{ // end the fade immediately
fadeAmount += fadeDelta;
fadeInterval = 0;
}
}
static void
FlushFadeXForms (void)
{
LockMutex (XFormControl.Lock);
finishPendingFade ();
UnlockMutex (XFormControl.Lock);
}
DWORD
FadeScreen (ScreenFadeType fadeType, SIZE TimeInterval)
{
TimeCount TimeOut;
int FadeEnd;
switch (fadeType)
{
case FadeAllToBlack:
case FadeSomeToBlack:
FadeEnd = FADE_NO_INTENSITY;
break;
case FadeAllToColor:
case FadeSomeToColor:
FadeEnd = FADE_NORMAL_INTENSITY;
break;
case FadeAllToWhite:
case FadeSomeToWhite:
FadeEnd = FADE_FULL_INTENSITY;
break;
default:
return (GetTimeCounter ());
}
// Don't make users wait for fades
if (QuitPosted)
TimeInterval = 0;
LockMutex (XFormControl.Lock);
finishPendingFade ();
if (TimeInterval <= 0)
{ // end the fade immediately
fadeAmount = FadeEnd;
// cancel any pending fades
fadeInterval = 0;
TimeOut = GetTimeCounter ();
}
else
{
fadeInterval = TimeInterval;
fadeDelta = FadeEnd - fadeAmount;
fadeStartTime = GetTimeCounter ();
TimeOut = fadeStartTime + TimeInterval + 1;
}
UnlockMutex (XFormControl.Lock);
return TimeOut;
}
/* Colormap Transforms */
static void
finish_colormap_xform (int which)
{
SetColorMap (XFormControl.TaskControl[which].CMapPtr);
XFormControl.TaskControl[which].CMapIndex = -1;
// check Highest ptr
if (which == XFormControl.Highest)
{
do
--which;
while (which >= 0 && XFormControl.TaskControl[which].CMapIndex == -1);
XFormControl.Highest = which;
}
}
static inline BYTE
blendChan (BYTE c1, BYTE c2, int weight, int scale)
{
return c1 + ((int)c2 - c1) * weight / scale;
}
/* This gives the XFormColorMap task a timeslice to do its thing
* Only one thread should ever be allowed to be calling this at any time
*/
BOOLEAN
XFormColorMap_step (void)
{
BOOLEAN Changed = FALSE;
int x;
DWORD Now = GetTimeCounter ();
LockMutex (XFormControl.Lock);
for (x = 0; x <= XFormControl.Highest; ++x)
{
XFORM_CONTROL *control = &XFormControl.TaskControl[x];
int index = control->CMapIndex;
int TicksLeft = control->EndTime - Now;
TFB_ColorMap *curmap;
if (index < 0)
continue; // unused slot
LockMutex (maplock);
curmap = colormaps[index];
if (!curmap)
{
UnlockMutex (maplock);
log_add (log_Error, "BUG: XFormColorMap_step(): no current map");
finish_colormap_xform (x);
continue;
}
if (TicksLeft > 0)
{
#define XFORM_SCALE 0x10000
TFB_ColorMap *newmap = NULL;
UBYTE *newClr;
Color *oldClr;
int frac;
int i;
newmap = clone_colormap (curmap, index);
oldClr = control->OldCMap;
newClr = (UBYTE*)control->CMapPtr + 2;
frac = (int)(control->Ticks - TicksLeft) * XFORM_SCALE
/ control->Ticks;
for (i = 0; i < NUMBER_OF_PLUTVALS; ++i, ++oldClr,
newClr += PLUTVAL_BYTE_SIZE)
{
Color color;
color.a = 0xff;
color.r = blendChan (oldClr->r, newClr[PLUTVAL_RED],
frac, XFORM_SCALE);
color.g = blendChan (oldClr->g, newClr[PLUTVAL_GREEN],
frac, XFORM_SCALE);
color.b = blendChan (oldClr->b, newClr[PLUTVAL_BLUE],
frac, XFORM_SCALE);
SetNativePaletteColor (newmap->palette, i, color);
}
colormaps[index] = newmap;
release_colormap (curmap);
}
UnlockMutex (maplock);
if (TicksLeft <= 0)
{ // asked for immediate xform or already done
finish_colormap_xform (x);
}
Changed = TRUE;
}
UnlockMutex (XFormControl.Lock);
return Changed;
}
static void
FlushPLUTXForms (void)
{
int i;
LockMutex (XFormControl.Lock);
for (i = 0; i <= XFormControl.Highest; ++i)
{
if (XFormControl.TaskControl[i].CMapIndex >= 0)
finish_colormap_xform (i);
}
XFormControl.Highest = -1; // all gone
UnlockMutex (XFormControl.Lock);
}
static DWORD
XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
{
TFB_ColorMap *map;
XFORM_CONTROL *control;
int index;
int x;
int first_avail = -1;
DWORD EndTime;
DWORD Now;
Now = GetTimeCounter ();
index = *(UBYTE*)ColorMapPtr;
LockMutex (XFormControl.Lock);
// Find an available slot, or reuse if required
for (x = 0; x <= XFormControl.Highest
&& index != XFormControl.TaskControl[x].CMapIndex;
++x)
{
if (first_avail == -1 && XFormControl.TaskControl[x].CMapIndex == -1)
first_avail = x;
}
if (index == XFormControl.TaskControl[x].CMapIndex)
{ // already xforming this colormap -- cancel and reuse slot
finish_colormap_xform (x);
}
else if (first_avail >= 0)
{ // picked up a slot along the way
x = first_avail;
}
else if (x >= MAX_XFORMS)
{ // flush some xforms if the queue is full
log_add (log_Debug, "WARNING: XFormPLUT(): no slots available");
x = XFormControl.Highest;
finish_colormap_xform (x);
}
// take next unused one
control = &XFormControl.TaskControl[x];
if (x > XFormControl.Highest)
XFormControl.Highest = x;
// make a copy of the current map
LockMutex (maplock);
map = colormaps[index];
if (!map)
{
UnlockMutex (maplock);
UnlockMutex (XFormControl.Lock);
log_add (log_Warning, "BUG: XFormPLUT(): no current map");
return (0);
}
GetColorMapColors (control->OldCMap, map);
UnlockMutex (maplock);
control->CMapIndex = index;
control->CMapPtr = ColorMapPtr;
control->Ticks = TimeInterval;
if (control->Ticks < 0)
control->Ticks = 0; /* prevent negative fade */
control->StartTime = Now;
control->EndTime = EndTime = Now + control->Ticks;
UnlockMutex (XFormControl.Lock);
return (EndTime);
}
DWORD
XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
{
if (!ColorMapPtr)
return (0);
// Don't make users wait for transforms
if (QuitPosted)
TimeInterval = 0;
return XFormPLUT (ColorMapPtr, TimeInterval);
}
void
FlushColorXForms (void)
{
FlushFadeXForms ();
FlushPLUTXForms ();
}
// The type conversions are implicit and will generate errors
// or warnings if types change imcompatibly
COLORMAPPTR
GetColorMapAddress (COLORMAP colormap)
{
return GetStringAddress (colormap);
}

View File

@@ -1,77 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef CMAP_H
#define CMAP_H
#include "libs/gfxlib.h"
#define MAX_COLORMAPS 250
// These are pertinent to colortable file format
// We load colormaps as binary and parse them when needed
#define PLUTVAL_BYTE_SIZE 3
// Channel order in colormap tables
#define PLUTVAL_RED 0
#define PLUTVAL_GREEN 1
#define PLUTVAL_BLUE 2
#define NUMBER_OF_PLUTVALS 256
// Size of the colormap in a colortable file
#define PLUT_BYTE_SIZE (PLUTVAL_BYTE_SIZE * NUMBER_OF_PLUTVALS)
#define FADE_NO_INTENSITY 0
#define FADE_NORMAL_INTENSITY 255
#define FADE_FULL_INTENSITY 510
typedef struct NativePalette NativePalette;
typedef struct tfb_colormap
{
int index;
// Colormap index as the game sees it
int version;
// Version goes up every time the colormap changes. This may
// be due to SetColorMap() or at every transformation step
// of XFormColorMap(). Paletted TFB_Images track the last
// colormap version they were drawn with for optimization.
int refcount;
struct tfb_colormap *next;
// for spares linking
NativePalette *palette;
} TFB_ColorMap;
extern int GetFadeAmount (void);
extern void InitColorMaps (void);
extern void UninitColorMaps (void);
extern void GetColorMapColors (Color *colors, TFB_ColorMap *);
extern TFB_ColorMap * TFB_GetColorMap (int index);
extern void TFB_ReturnColorMap (TFB_ColorMap *map);
extern BOOLEAN XFormColorMap_step (void);
// Native
NativePalette* AllocNativePalette (void);
void FreeNativePalette (NativePalette *);
void SetNativePaletteColor (NativePalette *, int index, Color);
Color GetNativePaletteColor (NativePalette *, int index);
#endif /* CMAP_H */

View File

@@ -1,398 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
GRAPHICS_STATUS _GraphicsStatusFlags;
CONTEXT _pCurContext;
#ifdef DEBUG
// We keep track of all contexts
CONTEXT firstContext;
// The first one in the list.
CONTEXT *contextEnd = &firstContext;
// Where to put the next context.
#endif
PRIMITIVE _locPrim;
FONT _CurFontPtr;
#define DEFAULT_FORE_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)
#define DEFAULT_BACK_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)
#define DEFAULT_DRAW_MODE MAKE_DRAW_MODE (DRAW_DEFAULT, 255)
CONTEXT
SetContext (CONTEXT Context)
{
CONTEXT LastContext;
LastContext = _pCurContext;
if (Context != LastContext)
{
if (LastContext)
{
UnsetContextFlags (
MAKE_WORD (0, GRAPHICS_ACTIVE | DRAWABLE_ACTIVE));
SetContextFlags (
MAKE_WORD (0, _GraphicsStatusFlags
& (GRAPHICS_ACTIVE | DRAWABLE_ACTIVE)));
DeactivateContext ();
}
_pCurContext = Context;
if (_pCurContext)
{
ActivateContext ();
_GraphicsStatusFlags &= ~(GRAPHICS_ACTIVE | DRAWABLE_ACTIVE);
_GraphicsStatusFlags |= HIBYTE (_get_context_flags ());
SetPrimColor (&_locPrim, _get_context_fg_color ());
_CurFramePtr = _get_context_fg_frame ();
_CurFontPtr = _get_context_font ();
}
}
return (LastContext);
}
#ifdef DEBUG
CONTEXT
CreateContextAux (const char *name)
#else /* if !defined(DEBUG) */
CONTEXT
CreateContextAux (void)
#endif /* !defined(DEBUG) */
{
CONTEXT NewContext;
NewContext = AllocContext ();
if (NewContext)
{
/* initialize context */
#ifdef DEBUG
NewContext->name = name;
NewContext->next = NULL;
*contextEnd = NewContext;
contextEnd = &NewContext->next;
#endif /* DEBUG */
NewContext->Mode = DEFAULT_DRAW_MODE;
NewContext->ForeGroundColor = DEFAULT_FORE_COLOR;
NewContext->BackGroundColor = DEFAULT_BACK_COLOR;
}
return NewContext;
}
#ifdef DEBUG
// Loop through the list of context to the pointer which points to the
// specified context. This is either 'firstContext' or the address of
// the 'next' field of some other context.
static CONTEXT *
FindContextPtr (CONTEXT context) {
CONTEXT *ptr;
for (ptr = &firstContext; *ptr != NULL; ptr = &(*ptr)->next) {
if (*ptr == context)
break;
}
return ptr;
}
#endif /* DEBUG */
BOOLEAN
DestroyContext (CONTEXT ContextRef)
{
if (ContextRef == 0)
return (FALSE);
if (_pCurContext && _pCurContext == ContextRef)
SetContext ((CONTEXT)0);
#ifdef DEBUG
// Unlink the context.
{
CONTEXT *contextPtr = FindContextPtr (ContextRef);
if (contextEnd == &ContextRef->next)
contextEnd = contextPtr;
*contextPtr = ContextRef->next;
}
#endif /* DEBUG */
FreeContext (ContextRef);
return TRUE;
}
Color
SetContextForeGroundColor (Color color)
{
Color oldColor;
if (!ContextActive ())
return DEFAULT_FORE_COLOR;
oldColor = _get_context_fg_color ();
if (!sameColor(oldColor, color))
{
SwitchContextForeGroundColor (color);
if (!(_get_context_fbk_flags () & FBK_IMAGE))
{
SetContextFBkFlags (FBK_DIRTY);
}
}
SetPrimColor (&_locPrim, color);
return (oldColor);
}
Color
GetContextForeGroundColor (void)
{
if (!ContextActive ())
return DEFAULT_FORE_COLOR;
return _get_context_fg_color ();
}
Color
SetContextBackGroundColor (Color color)
{
Color oldColor;
if (!ContextActive ())
return DEFAULT_BACK_COLOR;
oldColor = _get_context_bg_color ();
if (!sameColor(oldColor, color))
SwitchContextBackGroundColor (color);
return oldColor;
}
Color
GetContextBackGroundColor (void)
{
if (!ContextActive ())
return DEFAULT_BACK_COLOR;
return _get_context_bg_color ();
}
DrawMode
SetContextDrawMode (DrawMode mode)
{
DrawMode oldMode;
if (!ContextActive ())
return DEFAULT_DRAW_MODE;
oldMode = _get_context_draw_mode ();
SwitchContextDrawMode (mode);
return oldMode;
}
DrawMode
GetContextDrawMode (void)
{
if (!ContextActive ())
return DEFAULT_DRAW_MODE;
return _get_context_draw_mode ();
}
// Returns a rect based at 0,0 and the size of context foreground frame
static inline RECT
_get_context_fg_rect (void)
{
RECT r = { {0, 0}, {0, 0} };
if (_CurFramePtr)
r.extent = GetFrameBounds (_CurFramePtr);
return r;
}
BOOLEAN
SetContextClipRect (RECT *lpRect)
{
if (!ContextActive ())
return (FALSE);
if (lpRect)
{
if (rectsEqual (*lpRect, _get_context_fg_rect ()))
{ // Cliprect is undefined to mirror GetContextClipRect()
_pCurContext->ClipRect.extent.width = 0;
}
else
{ // We have a cliprect
_pCurContext->ClipRect = *lpRect;
}
}
else
{ // Set cliprect as undefined
_pCurContext->ClipRect.extent.width = 0;
}
return TRUE;
}
BOOLEAN
GetContextClipRect (RECT *lpRect)
{
if (!ContextActive ())
return (FALSE);
*lpRect = _pCurContext->ClipRect;
if (!_pCurContext->ClipRect.extent.width)
{ // Though the cliprect is undefined, drawing will be clipped
// to the extent of the foreground frame
*lpRect = _get_context_fg_rect ();
}
return (_pCurContext->ClipRect.extent.width != 0);
}
POINT
SetContextOrigin (POINT orgOffset)
{
// XXX: This is a hack, kind of. But that's what the original did.
return SetFrameHot (_CurFramePtr, orgOffset);
}
FRAME
SetContextFontEffect (FRAME EffectFrame)
{
FRAME LastEffect;
if (!ContextActive ())
return (NULL);
LastEffect = _get_context_fonteff ();
if (EffectFrame != LastEffect)
{
SwitchContextFontEffect (EffectFrame);
if (EffectFrame != 0)
{
SetContextFBkFlags (FBK_IMAGE);
}
else
{
UnsetContextFBkFlags (FBK_IMAGE);
}
}
return LastEffect;
}
void
FixContextFontEffect (void)
{
SIZE w, h;
TFB_Image* img;
if (!ContextActive () || (_get_context_font_backing () != 0
&& !(_get_context_fbk_flags () & FBK_DIRTY)))
return;
if (!GetContextFontLeading (&h) || !GetContextFontLeadingWidth (&w))
return;
img = _pCurContext->FontBacking;
if (img)
TFB_DrawScreen_DeleteImage (img);
img = TFB_DrawImage_CreateForScreen (w, h, TRUE);
if (_get_context_fbk_flags () & FBK_IMAGE)
{ // image pattern backing
FRAME EffectFrame = _get_context_fonteff ();
TFB_DrawImage_Image (EffectFrame->image,
-EffectFrame->HotSpot.x, -EffectFrame->HotSpot.y,
0, 0, NULL, DRAW_REPLACE_MODE, img);
}
else
{ // solid color backing
RECT r = { {0, 0}, {w, h} };
Color color = _get_context_fg_color ();
TFB_DrawImage_Rect (&r, color, DRAW_REPLACE_MODE, img);
}
_pCurContext->FontBacking = img;
UnsetContextFBkFlags (FBK_DIRTY);
}
// 'area' may be NULL to copy the entire CONTEXT cliprect
// 'area' is relative to the CONTEXT cliprect
DRAWABLE
CopyContextRect (const RECT* area)
{
RECT clipRect;
RECT fgRect;
RECT r;
if (!ContextActive () || !_CurFramePtr)
return NULL;
fgRect = _get_context_fg_rect ();
GetContextClipRect (&clipRect);
r = clipRect;
if (area)
{ // a portion of the context
r.corner.x += area->corner.x;
r.corner.y += area->corner.y;
r.extent = area->extent;
}
// TODO: Should this take CONTEXT origin into account too?
// validate the rect
if (!BoxIntersect (&r, &fgRect, &r))
return NULL;
if (_CurFramePtr->Type == SCREEN_DRAWABLE)
return LoadDisplayPixmap (&r, NULL);
else
return CopyFrameRect (_CurFramePtr, &r);
}
#ifdef DEBUG
const char *
GetContextName (CONTEXT context)
{
return context->name;
}
CONTEXT
GetFirstContext (void)
{
return firstContext;
}
CONTEXT
GetNextContext (CONTEXT context)
{
return context->next;
}
#endif /* DEBUG */

View File

@@ -1,147 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _CONTEXT_H
#define _CONTEXT_H
#include "tfb_draw.h"
#include "libs/memlib.h"
typedef UWORD FBK_FLAGS;
#define FBK_DIRTY (1 << 0)
#define FBK_IMAGE (1 << 1)
struct context_desc
{
UWORD Flags;
// Low nibble currently unused
// High nibble contains GRAPHICS_STATUS
Color ForeGroundColor, BackGroundColor;
DrawMode Mode;
FRAME ForeGroundFrame;
FONT Font;
RECT ClipRect;
FRAME FontEffect;
TFB_Image *FontBacking;
FBK_FLAGS BackingFlags;
#ifdef DEBUG
const char *name;
CONTEXT next;
#endif
};
#define AllocContext() HCalloc (sizeof (CONTEXT_DESC))
#define FreeContext HFree
extern CONTEXT _pCurContext;
extern PRIMITIVE _locPrim;
#define _get_context_fg_color() (_pCurContext->ForeGroundColor)
#define _get_context_bg_color() (_pCurContext->BackGroundColor)
#define _get_context_flags() (_pCurContext->Flags)
#define _get_context_fg_frame() (_pCurContext->ForeGroundFrame)
#define _get_context_font() (_pCurContext->Font)
#define _get_context_fbk_flags() (_pCurContext->BackingFlags)
#define _get_context_fonteff() (_pCurContext->FontEffect)
#define _get_context_font_backing() (_pCurContext->FontBacking)
#define _get_context_draw_mode() (_pCurContext->Mode)
#define SwitchContextDrawMode(m) \
{ \
_pCurContext->Mode = (m); \
}
#define SwitchContextForeGroundColor(c) \
{ \
_pCurContext->ForeGroundColor = (c); \
}
#define SwitchContextBackGroundColor(c) \
{ \
_pCurContext->BackGroundColor = (c); \
}
#define SetContextFlags(f) \
{ \
_pCurContext->Flags |= (f); \
}
#define UnsetContextFlags(f) \
{ \
_pCurContext->Flags &= ~(f); \
}
#define SwitchContextFGFrame(f) \
{ \
_pCurContext->ForeGroundFrame = (f); \
}
#define SwitchContextFont(f) \
{ \
_pCurContext->Font = (f); \
SetContextFBkFlags (FBK_DIRTY); \
}
#define SwitchContextBGFunc(f) \
{ \
_pCurContext->BackGroundFunc = (f); \
}
#define SetContextFBkFlags(f) \
{ \
_pCurContext->BackingFlags |= (f); \
}
#define UnsetContextFBkFlags(f) \
{ \
_pCurContext->BackingFlags &= ~(f); \
}
#define SwitchContextFontEffect(f) \
{ \
_pCurContext->FontEffect = (f); \
SetContextFBkFlags (FBK_DIRTY); \
}
typedef BYTE GRAPHICS_STATUS;
extern GRAPHICS_STATUS _GraphicsStatusFlags;
#define GRAPHICS_ACTIVE (GRAPHICS_STATUS)(1 << 0)
#define GRAPHICS_VISIBLE (GRAPHICS_STATUS)(1 << 1)
#define CONTEXT_ACTIVE (GRAPHICS_STATUS)(1 << 2)
#define DRAWABLE_ACTIVE (GRAPHICS_STATUS)(1 << 3)
#define DeactivateGraphics() (_GraphicsStatusFlags &= ~GRAPHICS_ACTIVE)
#define ActivateGraphics() (_GraphicsStatusFlags |= GRAPHICS_ACTIVE)
#define GraphicsActive() (_GraphicsStatusFlags & GRAPHICS_ACTIVE)
#define DeactivateVisible() (_GraphicsStatusFlags &= ~GRAPHICS_VISIBLE)
#define ActivateVisible() (_GraphicsStatusFlags |= GRAPHICS_VISIBLE)
#define DeactivateContext() (_GraphicsStatusFlags &= ~CONTEXT_ACTIVE)
#define ActivateContext() (_GraphicsStatusFlags |= CONTEXT_ACTIVE)
#define ContextActive() (_GraphicsStatusFlags & CONTEXT_ACTIVE)
#define DeactivateDrawable() (_GraphicsStatusFlags &= ~DRAWABLE_ACTIVE)
#define ActivateDrawable() (_GraphicsStatusFlags |= DRAWABLE_ACTIVE)
#define DrawableActive() (_GraphicsStatusFlags & DRAWABLE_ACTIVE)
#define SYSTEM_ACTIVE (GRAPHICS_STATUS)(CONTEXT_ACTIVE | DRAWABLE_ACTIVE)
#define GraphicsSystemActive() \
((_GraphicsStatusFlags & SYSTEM_ACTIVE) == SYSTEM_ACTIVE)
#define GraphicsStatus() \
(_GraphicsStatusFlags & (GRAPHICS_STATUS)(GRAPHICS_ACTIVE \
| GRAPHICS_VISIBLE))
// pValidRect or origin may be NULL
BOOLEAN GetContextValidRect (RECT *pValidRect, POINT *origin);
extern void FixContextFontEffect (void);
#endif /* _CONTEXT_H */

View File

@@ -1,589 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "libs/threadlib.h"
#include "libs/graphics/drawcmd.h"
#include "libs/graphics/drawable.h"
#include "libs/graphics/context.h"
#include "libs/graphics/dcqueue.h"
#include "libs/graphics/gfx_common.h"
#include "libs/graphics/bbox.h"
#include "libs/timelib.h"
#include "libs/log.h"
#include "libs/misc.h"
// for TFB_DEBUG_HALT
static RecursiveMutex DCQ_Mutex;
CondVar RenderingCond;
TFB_DrawCommand DCQ[DCQ_MAX];
TFB_DrawCommandQueue DrawCommandQueue;
#define FPS_PERIOD (ONE_SECOND / 100)
int RenderedFrames = 0;
// Wait for the queue to be emptied.
static void
TFB_WaitForSpace (int requested_slots)
{
int old_depth, i;
log_add (log_Debug, "DCQ overload (Size = %d, FullSize = %d, "
"Requested = %d). Sleeping until renderer is done.",
DrawCommandQueue.Size, DrawCommandQueue.FullSize,
requested_slots);
// Restore the DCQ locking level. I *think* this is
// always 1, but...
TFB_BatchReset ();
old_depth = GetRecursiveMutexDepth (DCQ_Mutex);
for (i = 0; i < old_depth; i++)
UnlockRecursiveMutex (DCQ_Mutex);
WaitCondVar (RenderingCond);
for (i = 0; i < old_depth; i++)
LockRecursiveMutex (DCQ_Mutex);
log_add (log_Debug, "DCQ clear (Size = %d, FullSize = %d). Continuing.",
DrawCommandQueue.Size, DrawCommandQueue.FullSize);
}
void
Lock_DCQ (int slots)
{
LockRecursiveMutex (DCQ_Mutex);
while (DrawCommandQueue.FullSize >= DCQ_MAX - slots)
{
TFB_WaitForSpace (slots);
}
}
void
Unlock_DCQ (void)
{
UnlockRecursiveMutex (DCQ_Mutex);
}
// Always have the DCQ locked when calling this.
static void
Synchronize_DCQ (void)
{
if (!DrawCommandQueue.Batching)
{
int front = DrawCommandQueue.Front;
int back = DrawCommandQueue.InsertionPoint;
DrawCommandQueue.Back = DrawCommandQueue.InsertionPoint;
if (front <= back)
{
DrawCommandQueue.Size = (back - front);
}
else
{
DrawCommandQueue.Size = (back + DCQ_MAX - front);
}
DrawCommandQueue.FullSize = DrawCommandQueue.Size;
}
}
void
TFB_BatchGraphics (void)
{
LockRecursiveMutex (DCQ_Mutex);
DrawCommandQueue.Batching++;
UnlockRecursiveMutex (DCQ_Mutex);
}
void
TFB_UnbatchGraphics (void)
{
LockRecursiveMutex (DCQ_Mutex);
if (DrawCommandQueue.Batching)
{
DrawCommandQueue.Batching--;
}
Synchronize_DCQ ();
UnlockRecursiveMutex (DCQ_Mutex);
}
// Cancel all pending batch operations, making them unbatched. This will
// cause a small amount of flicker when invoked, but prevents
// batching problems from freezing the game.
void
TFB_BatchReset (void)
{
LockRecursiveMutex (DCQ_Mutex);
DrawCommandQueue.Batching = 0;
Synchronize_DCQ ();
UnlockRecursiveMutex (DCQ_Mutex);
}
// Draw Command Queue Stuff
void
Init_DrawCommandQueue (void)
{
DrawCommandQueue.Back = 0;
DrawCommandQueue.Front = 0;
DrawCommandQueue.InsertionPoint = 0;
DrawCommandQueue.Batching = 0;
DrawCommandQueue.FullSize = 0;
DrawCommandQueue.Size = 0;
TFB_BBox_Init (ScreenWidth, ScreenHeight);
DCQ_Mutex = CreateRecursiveMutex ("DCQ",
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
RenderingCond = CreateCondVar ("DCQ empty",
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
}
void
Uninit_DrawCommandQueue (void)
{
DestroyCondVar (RenderingCond);
DestroyRecursiveMutex (DCQ_Mutex);
}
void
TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command)
{
Lock_DCQ (1);
DCQ[DrawCommandQueue.InsertionPoint] = *Command;
DrawCommandQueue.InsertionPoint = (DrawCommandQueue.InsertionPoint + 1)
% DCQ_MAX;
DrawCommandQueue.FullSize++;
Synchronize_DCQ ();
Unlock_DCQ ();
}
int
TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target)
{
LockRecursiveMutex (DCQ_Mutex);
if (DrawCommandQueue.Size == 0)
{
Unlock_DCQ ();
return (0);
}
if (DrawCommandQueue.Front == DrawCommandQueue.Back &&
DrawCommandQueue.Size != DCQ_MAX)
{
log_add (log_Debug, "Augh! Assertion failure in DCQ! "
"Front == Back, Size != DCQ_MAX");
DrawCommandQueue.Size = 0;
Unlock_DCQ ();
return (0);
}
*target = DCQ[DrawCommandQueue.Front];
DrawCommandQueue.Front = (DrawCommandQueue.Front + 1) % DCQ_MAX;
DrawCommandQueue.Size--;
DrawCommandQueue.FullSize--;
UnlockRecursiveMutex (DCQ_Mutex);
return 1;
}
void
TFB_DrawCommandQueue_Clear ()
{
LockRecursiveMutex (DCQ_Mutex);
DrawCommandQueue.Size = 0;
DrawCommandQueue.Front = 0;
DrawCommandQueue.Back = 0;
DrawCommandQueue.Batching = 0;
DrawCommandQueue.FullSize = 0;
DrawCommandQueue.InsertionPoint = 0;
UnlockRecursiveMutex (DCQ_Mutex);
}
void
TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
{
if (TFB_DEBUG_HALT)
{
return;
}
if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYTOIMAGE
&& _CurFramePtr->Type == SCREEN_DRAWABLE)
{
static RECT scissor_rect;
// Set the clipping region.
// We allow drawing with no current context set, so the whole screen
if ((_pCurContext && !rectsEqual (scissor_rect, _pCurContext->ClipRect))
|| (!_pCurContext && scissor_rect.extent.width != 0))
{
// Enqueue command to set the glScissor spec
TFB_DrawCommand DC;
if (_pCurContext)
scissor_rect = _pCurContext->ClipRect;
else
scissor_rect.extent.width = 0;
if (scissor_rect.extent.width)
{
DC.Type = TFB_DRAWCOMMANDTYPE_SCISSORENABLE;
DC.data.scissor.rect = scissor_rect;
}
else
{
DC.Type = TFB_DRAWCOMMANDTYPE_SCISSORDISABLE;
}
TFB_EnqueueDrawCommand(&DC);
}
}
TFB_DrawCommandQueue_Push (DrawCommand);
}
static void
computeFPS (void)
{
static TimeCount last_time;
static TimePeriod fps_counter;
TimeCount current_time;
TimePeriod delta_time;
current_time = GetTimeCounter ();
delta_time = current_time - last_time;
last_time = current_time;
fps_counter += delta_time;
if (fps_counter > FPS_PERIOD)
{
log_add (log_User, "fps %.2f, effective %.2f",
(float)ONE_SECOND / delta_time,
(float)ONE_SECOND * RenderedFrames / fps_counter);
fps_counter = 0;
RenderedFrames = 0;
}
}
// Only call from main() thread!!
void
TFB_FlushGraphics (void)
{
int commands_handled;
BOOLEAN livelock_deterrence;
// This is technically a locking violation on DrawCommandQueue.Size,
// but it is likely to not be very destructive.
if (DrawCommandQueue.Size == 0)
{
static int last_fade = 255;
static int last_transition = 255;
int current_fade = GetFadeAmount ();
int current_transition = TransitionAmount;
if ((current_fade != 255 && current_fade != last_fade) ||
(current_transition != 255 &&
current_transition != last_transition) ||
(current_fade == 255 && last_fade != 255) ||
(current_transition == 255 && last_transition != 255))
{
TFB_SwapBuffers (TFB_REDRAW_FADING);
// if fading, redraw every frame
}
else
{
TaskSwitch ();
}
last_fade = current_fade;
last_transition = current_transition;
BroadcastCondVar (RenderingCond);
return;
}
if (GfxFlags & TFB_GFXFLAGS_SHOWFPS)
computeFPS ();
commands_handled = 0;
livelock_deterrence = FALSE;
if (DrawCommandQueue.FullSize > DCQ_FORCE_BREAK_SIZE)
{
TFB_BatchReset ();
}
if (DrawCommandQueue.Size > DCQ_FORCE_SLOWDOWN_SIZE)
{
Lock_DCQ (-1);
livelock_deterrence = TRUE;
}
TFB_BBox_Reset ();
for (;;)
{
TFB_DrawCommand DC;
if (!TFB_DrawCommandQueue_Pop (&DC))
{
// the Queue is now empty.
break;
}
++commands_handled;
if (!livelock_deterrence && commands_handled + DrawCommandQueue.Size
> DCQ_LIVELOCK_MAX)
{
// log_add (log_Debug, "Initiating livelock deterrence!");
livelock_deterrence = TRUE;
Lock_DCQ (-1);
}
switch (DC.Type)
{
case TFB_DRAWCOMMANDTYPE_SETMIPMAP:
{
TFB_DrawCommand_SetMipmap *cmd = &DC.data.setmipmap;
TFB_DrawImage_SetMipmap (cmd->image, cmd->mipmap,
cmd->hotx, cmd->hoty);
break;
}
case TFB_DRAWCOMMANDTYPE_IMAGE:
{
TFB_DrawCommand_Image *cmd = &DC.data.image;
TFB_Image *DC_image = cmd->image;
const int x = cmd->x;
const int y = cmd->y;
TFB_DrawCanvas_Image (DC_image, x, y,
cmd->scale, cmd->scaleMode, cmd->colormap,
cmd->drawMode,
TFB_GetScreenCanvas (cmd->destBuffer));
if (cmd->destBuffer == TFB_SCREEN_MAIN)
{
LockMutex (DC_image->mutex);
if (cmd->scale)
TFB_BBox_RegisterCanvas (DC_image->ScaledImg,
x - DC_image->last_scale_hs.x,
y - DC_image->last_scale_hs.y);
else
TFB_BBox_RegisterCanvas (DC_image->NormalImg,
x - DC_image->NormalHs.x,
y - DC_image->NormalHs.y);
UnlockMutex (DC_image->mutex);
}
break;
}
case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE:
{
TFB_DrawCommand_FilledImage *cmd = &DC.data.filledimage;
TFB_Image *DC_image = cmd->image;
const int x = cmd->x;
const int y = cmd->y;
TFB_DrawCanvas_FilledImage (DC_image, x, y,
cmd->scale, cmd->scaleMode, cmd->color,
cmd->drawMode,
TFB_GetScreenCanvas (cmd->destBuffer));
if (cmd->destBuffer == TFB_SCREEN_MAIN)
{
LockMutex (DC_image->mutex);
if (cmd->scale)
TFB_BBox_RegisterCanvas (DC_image->ScaledImg,
x - DC_image->last_scale_hs.x,
y - DC_image->last_scale_hs.y);
else
TFB_BBox_RegisterCanvas (DC_image->NormalImg,
x - DC_image->NormalHs.x,
y - DC_image->NormalHs.y);
UnlockMutex (DC_image->mutex);
}
break;
}
case TFB_DRAWCOMMANDTYPE_FONTCHAR:
{
TFB_DrawCommand_FontChar *cmd = &DC.data.fontchar;
TFB_Char *DC_char = cmd->fontchar;
const int x = cmd->x;
const int y = cmd->y;
TFB_DrawCanvas_FontChar (DC_char, cmd->backing, x, y,
cmd->drawMode, TFB_GetScreenCanvas (cmd->destBuffer));
if (cmd->destBuffer == TFB_SCREEN_MAIN)
{
RECT r;
r.corner.x = x - DC_char->HotSpot.x;
r.corner.y = y - DC_char->HotSpot.y;
r.extent.width = DC_char->extent.width;
r.extent.height = DC_char->extent.height;
TFB_BBox_RegisterRect (&r);
}
break;
}
case TFB_DRAWCOMMANDTYPE_LINE:
{
TFB_DrawCommand_Line *cmd = &DC.data.line;
if (cmd->destBuffer == TFB_SCREEN_MAIN)
{
TFB_BBox_RegisterPoint (cmd->x1, cmd->y1);
TFB_BBox_RegisterPoint (cmd->x2, cmd->y2);
}
TFB_DrawCanvas_Line (cmd->x1, cmd->y1, cmd->x2, cmd->y2,
cmd->color, cmd->drawMode,
TFB_GetScreenCanvas (cmd->destBuffer));
break;
}
case TFB_DRAWCOMMANDTYPE_RECTANGLE:
{
TFB_DrawCommand_Rect *cmd = &DC.data.rect;
if (cmd->destBuffer == TFB_SCREEN_MAIN)
TFB_BBox_RegisterRect (&cmd->rect);
TFB_DrawCanvas_Rect (&cmd->rect, cmd->color, cmd->drawMode,
TFB_GetScreenCanvas (cmd->destBuffer));
break;
}
case TFB_DRAWCOMMANDTYPE_SCISSORENABLE:
{
TFB_DrawCommand_Scissor *cmd = &DC.data.scissor;
TFB_DrawCanvas_SetClipRect (
TFB_GetScreenCanvas (TFB_SCREEN_MAIN), &cmd->rect);
TFB_BBox_SetClipRect (&DC.data.scissor.rect);
break;
}
case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE:
TFB_DrawCanvas_SetClipRect (
TFB_GetScreenCanvas (TFB_SCREEN_MAIN), NULL);
TFB_BBox_SetClipRect (NULL);
break;
case TFB_DRAWCOMMANDTYPE_COPYTOIMAGE:
{
TFB_DrawCommand_CopyToImage *cmd = &DC.data.copytoimage;
TFB_Image *DC_image = cmd->image;
const POINT dstPt = {0, 0};
if (DC_image == 0)
{
log_add (log_Debug, "DCQ ERROR: COPYTOIMAGE passed null "
"image ptr");
break;
}
LockMutex (DC_image->mutex);
TFB_DrawCanvas_CopyRect (
TFB_GetScreenCanvas (cmd->srcBuffer), &cmd->rect,
DC_image->NormalImg, dstPt);
UnlockMutex (DC_image->mutex);
break;
}
case TFB_DRAWCOMMANDTYPE_COPY:
{
TFB_DrawCommand_Copy *cmd = &DC.data.copy;
const RECT r = cmd->rect;
if (cmd->destBuffer == TFB_SCREEN_MAIN)
TFB_BBox_RegisterRect (&cmd->rect);
TFB_DrawCanvas_CopyRect (
TFB_GetScreenCanvas (cmd->srcBuffer), &r,
TFB_GetScreenCanvas (cmd->destBuffer), r.corner);
break;
}
case TFB_DRAWCOMMANDTYPE_DELETEIMAGE:
{
TFB_Image *DC_image = DC.data.deleteimage.image;
TFB_DrawImage_Delete (DC_image);
break;
}
case TFB_DRAWCOMMANDTYPE_DELETEDATA:
{
void *data = DC.data.deletedata.data;
HFree (data);
break;
}
case TFB_DRAWCOMMANDTYPE_SENDSIGNAL:
ClearSemaphore (DC.data.sendsignal.sem);
break;
case TFB_DRAWCOMMANDTYPE_REINITVIDEO:
{
TFB_DrawCommand_ReinitVideo *cmd = &DC.data.reinitvideo;
int oldDriver = GraphicsDriver;
int oldFlags = GfxFlags;
int oldWidth = ScreenWidthActual;
int oldHeight = ScreenHeightActual;
if (TFB_ReInitGraphics (cmd->driver, cmd->flags,
cmd->width, cmd->height))
{
log_add (log_Error, "Could not provide requested mode: "
"reverting to last known driver.");
// We don't know what exactly failed, so roll it all back
if (TFB_ReInitGraphics (oldDriver, oldFlags,
oldWidth, oldHeight))
{
log_add (log_Fatal,
"Couldn't reinit at that point either. "
"Your video has been somehow tied in knots.");
exit (EXIT_FAILURE);
}
}
TFB_SwapBuffers (TFB_REDRAW_YES);
break;
}
case TFB_DRAWCOMMANDTYPE_CALLBACK:
{
DC.data.callback.callback (DC.data.callback.arg);
break;
}
}
}
if (livelock_deterrence)
Unlock_DCQ ();
TFB_SwapBuffers (TFB_REDRAW_NO);
RenderedFrames++;
BroadcastCondVar (RenderingCond);
}

View File

@@ -1,55 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef DCQUEUE_H
#define DCQUEUE_H
// Maximum size of the DCQ. The larger the DCQ, the larger frameskips
// become tolerable before initiating livelock deterrence and game
// slowdown. Other constants for controlling the frameskip/slowdown
// balance may be found in sdl_common.c near TFB_FlushGraphics.
// Livelock deterrance constants. Because the entire screen is rarely
// refreshed, we may not drop draw commands on the floor with abandon.
// Furthermore, if the main program is queuing commands at a speed
// comparable to our processing of the commands, we never finish and
// the game freezes. Thus, if the queue starts out larger than
// DCQ_FORCE_SLOWDOWN_SIZE, or DCQ_LIVELOCK_MAX commands find
// themselves being processed in one go, livelock deterrence is
// enabled, and TFB_FlushGraphics locks the DCQ until it has processed
// all entries. If batched but pending commands exceed DCQ_FORCE_BREAK_SIZE,
// a continuity break is performed. This will effectively slow down the
// game logic, a fate we seek to avoid - however, it seems to be unavoidable
// on slower machines. Even there, it's seems nonexistent outside of
// communications screens. --Michael
#ifdef DCQ_OF_DOOM
#define DCQ_MAX 512
#define DCQ_FORCE_SLOWDOWN_SIZE 128
#define DCQ_FORCE_BREAK_SIZE 512
#define DCQ_LIVELOCK_MAX 256
#else
#define DCQ_MAX 16384
#define DCQ_FORCE_SLOWDOWN_SIZE 4096
#define DCQ_FORCE_BREAK_SIZE 16384
#define DCQ_LIVELOCK_MAX 4096
#endif
extern CondVar RenderingCond;
#endif

View File

@@ -1,501 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "libs/gfxlib.h"
#include "libs/graphics/context.h"
#include "libs/graphics/drawable.h"
#include "libs/graphics/tfb_draw.h"
#include "libs/memlib.h"
#include "tfb_draw.h"
#include <math.h>
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
FRAME _CurFramePtr;
FRAME
SetContextFGFrame (FRAME Frame)
{
FRAME LastFrame;
if (Frame != (LastFrame = (FRAME)_CurFramePtr))
{
if (LastFrame)
DeactivateDrawable ();
_CurFramePtr = Frame;
if (_CurFramePtr)
ActivateDrawable ();
if (ContextActive ())
{
SwitchContextFGFrame (Frame);
}
}
return (LastFrame);
}
FRAME
GetContextFGFrame (void)
{
return _CurFramePtr;
}
static DRAWABLE
request_drawable (COUNT NumFrames, DRAWABLE_TYPE DrawableType,
CREATE_FLAGS flags, SIZE width, SIZE height)
{
DRAWABLE Drawable;
COUNT i;
Drawable = AllocDrawable (NumFrames);
if (!Drawable)
return NULL;
Drawable->Flags = flags;
Drawable->MaxIndex = NumFrames - 1;
for (i = 0; i < NumFrames; ++i)
{
FRAME FramePtr = &Drawable->Frame[i];
if (DrawableType == RAM_DRAWABLE && width > 0 && height > 0)
{
FramePtr->image = TFB_DrawImage_New (TFB_DrawCanvas_New_TrueColor (
width, height, (flags & WANT_ALPHA) ? TRUE : FALSE));
}
FramePtr->Type = DrawableType;
FramePtr->Index = i;
SetFrameBounds (FramePtr, width, height);
}
return Drawable;
}
DRAWABLE
CreateDisplay (CREATE_FLAGS CreateFlags, SIZE *pwidth, SIZE *pheight)
{
DRAWABLE Drawable;
// TODO: ScreenWidth and ScreenHeight should be passed in
// instead of returned.
Drawable = request_drawable (1, SCREEN_DRAWABLE,
(CreateFlags & (WANT_PIXMAP | WANT_MASK)),
ScreenWidth, ScreenHeight);
if (Drawable)
{
FRAME F;
F = CaptureDrawable (Drawable);
if (F == 0)
DestroyDrawable (Drawable);
else
{
*pwidth = GetFrameWidth (F);
*pheight = GetFrameHeight (F);
ReleaseDrawable (F);
return (Drawable);
}
}
*pwidth = *pheight = 0;
return (0);
}
DRAWABLE
AllocDrawable (COUNT n)
{
DRAWABLE Drawable;
Drawable = (DRAWABLE) HCalloc(sizeof (DRAWABLE_DESC));
if (Drawable)
{
int i;
Drawable->Frame = (FRAME)HMalloc (sizeof (FRAME_DESC) * n);
if (Drawable->Frame == NULL)
{
HFree (Drawable);
return NULL;
}
/* Zero out the newly allocated frames, since HMalloc doesn't have
* MEM_ZEROINIT. */
for (i = 0; i < n; i++) {
FRAME F;
F = &Drawable->Frame[i];
F->parent = Drawable;
F->Type = 0;
F->Index = 0;
F->image = 0;
F->Bounds.width = 0;
F->Bounds.height = 0;
F->HotSpot.x = 0;
F->HotSpot.y = 0;
}
}
return Drawable;
}
DRAWABLE
CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width, SIZE height, COUNT
num_frames)
{
DRAWABLE Drawable;
Drawable = request_drawable (num_frames, RAM_DRAWABLE,
(CreateFlags & (WANT_MASK | WANT_PIXMAP
| WANT_ALPHA | MAPPED_TO_DISPLAY)),
width, height);
if (Drawable)
{
FRAME F;
F = CaptureDrawable (Drawable);
if (F)
{
ReleaseDrawable (F);
return (Drawable);
}
}
return (0);
}
BOOLEAN
DestroyDrawable (DRAWABLE Drawable)
{
if (_CurFramePtr && (Drawable == _CurFramePtr->parent))
SetContextFGFrame ((FRAME)NULL);
if (Drawable)
{
FreeDrawable (Drawable);
return (TRUE);
}
return (FALSE);
}
BOOLEAN
GetFrameRect (FRAME FramePtr, RECT *pRect)
{
if (FramePtr)
{
pRect->corner.x = -FramePtr->HotSpot.x;
pRect->corner.y = -FramePtr->HotSpot.y;
pRect->extent = GetFrameBounds (FramePtr);
return (TRUE);
}
return (FALSE);
}
HOT_SPOT
SetFrameHot (FRAME FramePtr, HOT_SPOT HotSpot)
{
if (FramePtr)
{
HOT_SPOT OldHot;
OldHot = FramePtr->HotSpot;
FramePtr->HotSpot = HotSpot;
return (OldHot);
}
return (MAKE_HOT_SPOT (0, 0));
}
HOT_SPOT
GetFrameHot (FRAME FramePtr)
{
if (FramePtr)
{
return FramePtr->HotSpot;
}
return (MAKE_HOT_SPOT (0, 0));
}
DRAWABLE
RotateFrame (FRAME Frame, int angle_deg)
{
DRAWABLE Drawable;
FRAME RotFramePtr;
double dx, dy;
double d;
double angle = angle_deg * M_PI / 180;
if (!Frame)
return NULL;
assert (Frame->Type != SCREEN_DRAWABLE);
Drawable = request_drawable (1, RAM_DRAWABLE, WANT_PIXMAP, 0, 0);
if (!Drawable)
return 0;
RotFramePtr = CaptureDrawable (Drawable);
if (!RotFramePtr)
{
FreeDrawable (Drawable);
return 0;
}
RotFramePtr->image = TFB_DrawImage_New_Rotated (
Frame->image, angle_deg);
SetFrameBounds (RotFramePtr, RotFramePtr->image->extent.width,
RotFramePtr->image->extent.height);
/* now we need to rotate the hot-spot, eww */
dx = Frame->HotSpot.x - (GetFrameWidth (Frame) / 2);
dy = Frame->HotSpot.y - (GetFrameHeight (Frame) / 2);
d = sqrt ((double)dx*dx + (double)dy*dy);
if ((int)d != 0)
{
double organg = atan2 (-dy, dx);
dx = cos (organg + angle) * d;
dy = -sin (organg + angle) * d;
}
RotFramePtr->HotSpot.x = (GetFrameWidth (RotFramePtr) / 2) + (int)dx;
RotFramePtr->HotSpot.y = (GetFrameHeight (RotFramePtr) / 2) + (int)dy;
ReleaseDrawable (RotFramePtr);
return Drawable;
}
// color.a is ignored
void
SetFrameTransparentColor (FRAME frame, Color color)
{
TFB_Image *img;
if (!frame)
return;
assert (frame->Type != SCREEN_DRAWABLE);
img = frame->image;
LockMutex (img->mutex);
// TODO: This should defer to TFB_DrawImage instead
TFB_DrawCanvas_SetTransparentColor (img->NormalImg, color, FALSE);
UnlockMutex (img->mutex);
}
Color
GetFramePixel (FRAME frame, POINT pixelPt)
{
TFB_Image *img;
Color ret;
if (!frame)
return BUILD_COLOR_RGBA (0, 0, 0, 0);
assert (frame->Type != SCREEN_DRAWABLE);
img = frame->image;
LockMutex (img->mutex);
// TODO: This should defer to TFB_DrawImage instead
ret = TFB_DrawCanvas_GetPixel (img->NormalImg, pixelPt.x, pixelPt.y);
UnlockMutex (img->mutex);
return ret;
}
static FRAME
makeMatchingFrame (FRAME frame, int width, int height)
{
DRAWABLE drawable;
FRAME newFrame;
CREATE_FLAGS flags;
flags = GetFrameParentDrawable (frame)->Flags;
drawable = CreateDrawable (flags, width, height, 1);
if (!drawable)
return NULL;
newFrame = CaptureDrawable (drawable);
if (!newFrame)
{
FreeDrawable (drawable);
return NULL;
}
return newFrame;
}
// Creates an new DRAWABLE containing a copy of specified FRAME's rect
// Source FRAME must not be a SCREEN_DRAWABLE
DRAWABLE
CopyFrameRect (FRAME frame, const RECT *area)
{
FRAME newFrame;
POINT nullPt = MAKE_POINT (0, 0);
if (!frame)
return NULL;
assert (frame->Type != SCREEN_DRAWABLE);
newFrame = makeMatchingFrame (frame, area->extent.width,
area->extent.height);
if (!newFrame)
return NULL;
TFB_DrawImage_CopyRect (frame->image, area, newFrame->image, nullPt);
return ReleaseDrawable (newFrame);
}
// Creates an new DRAWABLE mostly identical to specified FRAME
// Source FRAME must not be a SCREEN_DRAWABLE
DRAWABLE
CloneFrame (FRAME frame)
{
FRAME newFrame;
RECT r;
if (!frame)
return NULL;
assert (frame->Type != SCREEN_DRAWABLE);
GetFrameRect (frame, &r);
r.corner.x = 0;
r.corner.y = 0;
newFrame = CaptureDrawable (CopyFrameRect (frame, &r));
if (!newFrame)
return NULL;
// copy the hot-spot
newFrame->HotSpot = frame->HotSpot;
return ReleaseDrawable (newFrame);
}
// Creates a new DRAWABLE of specified size and scales the passed
// frame onto it. The aspect ratio is not preserved.
DRAWABLE
RescaleFrame (FRAME frame, int width, int height)
{
FRAME newFrame;
TFB_Image *img;
TFB_Canvas src, dst;
if (!frame)
return NULL;
assert (frame->Type != SCREEN_DRAWABLE);
newFrame = makeMatchingFrame (frame, width, height);
if (!newFrame)
return NULL;
// scale the hot-spot
newFrame->HotSpot.x = frame->HotSpot.x * width / frame->Bounds.width;
newFrame->HotSpot.y = frame->HotSpot.y * height / frame->Bounds.height;
img = frame->image;
LockMutex (img->mutex);
// NOTE: We do not lock the target image because nothing has a
// reference to it yet!
src = img->NormalImg;
dst = newFrame->image->NormalImg;
TFB_DrawCanvas_Rescale_Nearest (src, dst, -1, NULL, NULL, NULL);
UnlockMutex (img->mutex);
return ReleaseDrawable (newFrame);
}
BOOLEAN
ReadFramePixelColors (FRAME frame, Color *pixels, int width, int height)
{
TFB_Image *img;
if (!frame)
return FALSE;
assert (frame->Type != SCREEN_DRAWABLE);
// TODO: Do we need to lock the img->mutex here?
img = frame->image;
return TFB_DrawCanvas_GetPixelColors (img->NormalImg, pixels,
width, height);
}
// Warning: this functions bypasses DCQ, which is why it is not a DrawXXX
BOOLEAN
WriteFramePixelColors (FRAME frame, const Color *pixels, int width, int height)
{
TFB_Image *img;
if (!frame)
return FALSE;
assert (frame->Type != SCREEN_DRAWABLE);
// TODO: Do we need to lock the img->mutex here?
img = frame->image;
return TFB_DrawCanvas_SetPixelColors (img->NormalImg, pixels,
width, height);
}
BOOLEAN
ReadFramePixelIndexes (FRAME frame, BYTE *pixels, int width, int height)
{
TFB_Image *img;
if (!frame)
return FALSE;
assert (frame->Type != SCREEN_DRAWABLE);
// TODO: Do we need to lock the img->mutex here?
img = frame->image;
return TFB_DrawCanvas_GetPixelIndexes (img->NormalImg, pixels,
width, height);
}
// Warning: this functions bypasses DCQ, which is why it is not a DrawXXX
BOOLEAN
WriteFramePixelIndexes (FRAME frame, const BYTE *pixels, int width, int height)
{
TFB_Image *img;
if (!frame)
return FALSE;
assert (frame->Type != SCREEN_DRAWABLE);
// TODO: Do we need to lock the img->mutex here?
img = frame->image;
return TFB_DrawCanvas_SetPixelIndexes (img->NormalImg, pixels,
width, height);
}

View File

@@ -1,88 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _DRAWABLE_H
#define _DRAWABLE_H
#include <stdio.h>
#include "tfb_draw.h"
#define ValidPrimType(pt) ((pt)<NUM_PRIMS)
typedef struct bresenham_line
{
POINT first, second;
SIZE abs_delta_x, abs_delta_y;
SIZE error_term;
BOOLEAN end_points_exchanged;
INTERSECT_CODE intersect_code;
} BRESENHAM_LINE;
typedef UWORD DRAWABLE_TYPE;
#define ROM_DRAWABLE 0
#define RAM_DRAWABLE 1
#define SCREEN_DRAWABLE 2
struct frame_desc
{
DRAWABLE_TYPE Type;
UWORD Index;
HOT_SPOT HotSpot;
EXTENT Bounds;
TFB_Image *image;
struct drawable_desc *parent;
};
struct drawable_desc
{
CREATE_FLAGS Flags;
UWORD MaxIndex;
FRAME_DESC *Frame;
};
#define GetFrameWidth(f) ((f)->Bounds.width)
#define GetFrameHeight(f) ((f)->Bounds.height)
#define GetFrameBounds(f) ((f)->Bounds)
#define SetFrameBounds(f,w,h) \
((f)->Bounds.width=(w), \
((f))->Bounds.height=(h))
#define DRAWABLE_PRIORITY DEFAULT_MEM_PRIORITY
extern DRAWABLE AllocDrawable (COUNT num_frames);
#define FreeDrawable(D) _ReleaseCelData (D)
typedef struct
{
RECT Box;
FRAME FramePtr;
} IMAGE_BOX;
extern INTERSECT_CODE _clip_line (const RECT *pClipRect,
BRESENHAM_LINE *pLine);
extern void *_GetCelData (uio_Stream *fp, DWORD length);
extern BOOLEAN _ReleaseCelData (void *handle);
extern FRAME _CurFramePtr;
// ClipRect is relative to ctxOrigin
extern void _text_blt (RECT *pClipRect, TEXT *TextPtr, POINT ctxOrigin);
#endif /* _DRAWABLE_H */

View File

@@ -1,202 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef DRAWCMD_H
#define DRAWCMD_H
#include "libs/graphics/tfb_draw.h"
enum
{
TFB_DRAWCOMMANDTYPE_LINE,
TFB_DRAWCOMMANDTYPE_RECTANGLE,
TFB_DRAWCOMMANDTYPE_IMAGE,
TFB_DRAWCOMMANDTYPE_FILLEDIMAGE,
TFB_DRAWCOMMANDTYPE_FONTCHAR,
TFB_DRAWCOMMANDTYPE_COPY,
TFB_DRAWCOMMANDTYPE_COPYTOIMAGE,
TFB_DRAWCOMMANDTYPE_SCISSORENABLE,
TFB_DRAWCOMMANDTYPE_SCISSORDISABLE,
TFB_DRAWCOMMANDTYPE_SETMIPMAP,
TFB_DRAWCOMMANDTYPE_DELETEIMAGE,
TFB_DRAWCOMMANDTYPE_DELETEDATA,
TFB_DRAWCOMMANDTYPE_SENDSIGNAL,
TFB_DRAWCOMMANDTYPE_REINITVIDEO,
TFB_DRAWCOMMANDTYPE_CALLBACK,
};
typedef struct tfb_dc_line
{
int x1, y1, x2, y2;
Color color;
DrawMode drawMode;
SCREEN destBuffer;
} TFB_DrawCommand_Line;
typedef struct tfb_dc_rect
{
RECT rect;
Color color;
DrawMode drawMode;
SCREEN destBuffer;
} TFB_DrawCommand_Rect;
typedef struct tfb_dc_img
{
TFB_Image *image;
int x, y;
SCREEN destBuffer;
TFB_ColorMap *colormap;
DrawMode drawMode;
int scale;
int scaleMode;
} TFB_DrawCommand_Image;
typedef struct tfb_dc_filledimg
{
TFB_Image *image;
int x, y;
Color color;
SCREEN destBuffer;
DrawMode drawMode;
int scale;
int scaleMode;
} TFB_DrawCommand_FilledImage;
typedef struct tfb_dc_fontchar
{
TFB_Char *fontchar;
TFB_Image *backing;
int x, y;
DrawMode drawMode;
SCREEN destBuffer;
} TFB_DrawCommand_FontChar;
typedef struct tfb_dc_copy
{
RECT rect;
SCREEN srcBuffer, destBuffer;
} TFB_DrawCommand_Copy;
typedef struct tfb_dc_copyimg
{
TFB_Image *image;
RECT rect;
SCREEN srcBuffer;
} TFB_DrawCommand_CopyToImage;
typedef struct tfb_dc_scissor
{
RECT rect;
} TFB_DrawCommand_Scissor;
typedef struct tfb_dc_setmip
{
TFB_Image *image;
TFB_Image *mipmap;
int hotx, hoty;
} TFB_DrawCommand_SetMipmap;
typedef struct tfb_dc_delimg
{
TFB_Image *image;
} TFB_DrawCommand_DeleteImage;
typedef struct tfb_dc_deldata
{
void *data;
// data must be a result of HXalloc() call
} TFB_DrawCommand_DeleteData;
typedef struct tfb_dc_signal
{
Semaphore sem;
} TFB_DrawCommand_SendSignal;
typedef struct tfb_dc_reinit_video
{
int driver, flags, width, height;
} TFB_DrawCommand_ReinitVideo;
typedef struct tfb_dc_callback
{
void (*callback)(void *arg);
void *arg;
} TFB_DrawCommand_Callback;
typedef struct tfb_drawcommand
{
int Type;
union {
TFB_DrawCommand_Line line;
TFB_DrawCommand_Rect rect;
TFB_DrawCommand_Image image;
TFB_DrawCommand_FilledImage filledimage;
TFB_DrawCommand_FontChar fontchar;
TFB_DrawCommand_Copy copy;
TFB_DrawCommand_CopyToImage copytoimage;
TFB_DrawCommand_Scissor scissor;
TFB_DrawCommand_SetMipmap setmipmap;
TFB_DrawCommand_DeleteImage deleteimage;
TFB_DrawCommand_DeleteData deletedata;
TFB_DrawCommand_SendSignal sendsignal;
TFB_DrawCommand_ReinitVideo reinitvideo;
TFB_DrawCommand_Callback callback;
} data;
} TFB_DrawCommand;
// Queue Stuff
typedef struct tfb_drawcommandqueue
{
int Front;
int Back;
int InsertionPoint;
int Batching;
volatile int FullSize;
volatile int Size;
} TFB_DrawCommandQueue;
void Init_DrawCommandQueue (void);
void Uninit_DrawCommandQueue (void);
void TFB_BatchGraphics (void);
void TFB_UnbatchGraphics (void);
void TFB_BatchReset (void);
void TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command);
int TFB_DrawCommandQueue_Pop (TFB_DrawCommand* Command);
void TFB_DrawCommandQueue_Clear (void);
extern TFB_DrawCommandQueue DrawCommandQueue;
void TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand);
void Lock_DCQ (int slots);
void Unlock_DCQ (void);
#endif

View File

@@ -1,72 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
#include "options.h"
#include "libs/reslib.h"
DRAWABLE
LoadGraphicFile (const char *pStr)
{
uio_Stream *fp;
// FIXME: this theoretically needs a mechanism to prevent races
if (_cur_resfile_name)
// something else is loading resources atm
return 0;
fp = res_OpenResFile (contentDir, pStr, "rb");
if (fp != NULL)
{
DRAWABLE hData;
_cur_resfile_name = pStr;
hData = (DRAWABLE)_GetCelData (fp, LengthResFile (fp));
_cur_resfile_name = 0;
res_CloseResFile (fp);
return hData;
}
return (NULL);
}
FONT
LoadFontFile (const char *pStr)
{
uio_Stream *fp;
// FIXME: this theoretically needs a mechanism to prevent races
if (_cur_resfile_name)
// something else is loading resources atm
return 0;
fp = res_OpenResFile (contentDir, pStr, "rb");
if (fp != NULL)
{
FONT hData;
_cur_resfile_name = pStr;
hData = (FONT)_GetFontData (fp, LengthResFile (fp));
_cur_resfile_name = 0;
res_CloseResFile (fp);
return hData;
}
return (0);
}

View File

@@ -1,334 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
#include "tfb_prim.h"
#include "libs/log.h"
static inline TFB_Char *getCharFrame (FONT_DESC *fontPtr, UniChar ch);
FONT
SetContextFont (FONT Font)
{
FONT LastFont;
LastFont = _CurFontPtr;
_CurFontPtr = Font;
if (ContextActive ())
SwitchContextFont (Font);
return (LastFont);
}
BOOLEAN
DestroyFont (FONT FontRef)
{
if (FontRef == NULL)
return (FALSE);
if (_CurFontPtr && _CurFontPtr == FontRef)
SetContextFont ((FONT)NULL);
return (FreeFont (FontRef));
}
// XXX: Should be in frame.c (renamed to something decent?)
void
font_DrawText (TEXT *lpText)
{
RECT ClipRect;
POINT origin;
TEXT text;
FixContextFontEffect ();
if (!GraphicsSystemActive () || !GetContextValidRect (NULL, &origin))
return;
// TextRect() clobbers TEXT.CharCount so we have to make a copy
text = *lpText;
if (!TextRect (&text, &ClipRect, NULL))
return;
// ClipRect is relative to origin
_text_blt (&ClipRect, &text, origin);
}
/* Draw the stroke by drawing the same text in the
* background color one pixel shifted to all 4 directions.
*/
void
font_DrawTracedText (TEXT *pText, Color text, Color trace)
{
// Preserve current foreground color for full correctness
Color oldfg = SetContextForeGroundColor (trace);
pText->baseline.x--;
font_DrawText (pText);
pText->baseline.x += 2;
font_DrawText (pText);
pText->baseline.x--;
pText->baseline.y--;
font_DrawText (pText);
pText->baseline.y += 2;
font_DrawText (pText);
pText->baseline.y--;
SetContextForeGroundColor (text);
font_DrawText (pText);
SetContextForeGroundColor (oldfg);
}
BOOLEAN
GetContextFontLeading (SIZE *pheight)
{
if (_CurFontPtr != 0)
{
*pheight = (SIZE)_CurFontPtr->Leading;
return (TRUE);
}
*pheight = 0;
return (FALSE);
}
BOOLEAN
GetContextFontLeadingWidth (SIZE *pwidth)
{
if (_CurFontPtr != 0)
{
*pwidth = (SIZE)_CurFontPtr->LeadingWidth;
return (TRUE);
}
*pwidth = 0;
return (FALSE);
}
BOOLEAN
TextRect (TEXT *lpText, RECT *pRect, BYTE *pdelta)
{
BYTE char_delta_array[MAX_DELTAS];
FONT FontPtr;
FontPtr = _CurFontPtr;
if (FontPtr != 0 && lpText->CharCount != 0)
{
COORD top_y, bot_y;
SIZE width;
UniChar next_ch = 0;
const char *pStr;
COUNT num_chars;
num_chars = lpText->CharCount;
/* At this point lpText->CharCount contains the *maximum* number of
* characters that lpText->pStr may contain.
* After the while loop below, it will contain the actual number.
*/
if (pdelta == 0)
{
pdelta = char_delta_array;
if (num_chars > MAX_DELTAS)
{
num_chars = MAX_DELTAS;
lpText->CharCount = MAX_DELTAS;
}
}
top_y = 0;
bot_y = 0;
width = 0;
pStr = lpText->pStr;
if (num_chars > 0)
{
next_ch = getCharFromString (&pStr);
if (next_ch == '\0')
num_chars = 0;
}
while (num_chars--)
{
UniChar ch;
SIZE last_width;
TFB_Char *charFrame;
last_width = width;
ch = next_ch;
if (num_chars > 0)
{
next_ch = getCharFromString (&pStr);
if (next_ch == '\0')
{
lpText->CharCount -= num_chars;
num_chars = 0;
}
}
charFrame = getCharFrame (FontPtr, ch);
if (charFrame != NULL && charFrame->disp.width)
{
COORD y;
y = -charFrame->HotSpot.y;
if (y < top_y)
top_y = y;
y += charFrame->disp.height;
if (y > bot_y)
bot_y = y;
width += charFrame->disp.width;
#if 0
if (num_chars && next_ch < (UNICODE) MAX_CHARS
&& !(FontPtr->KernTab[ch]
& (FontPtr->KernTab[next_ch] >> 2)))
width -= FontPtr->KernAmount;
#endif
}
*pdelta++ = (BYTE)(width - last_width);
}
if (width > 0 && (bot_y -= top_y) > 0)
{
/* subtract off default character spacing */
if (pdelta[-1] > 0)
{
--pdelta[-1];
--width;
}
if (lpText->align == ALIGN_LEFT)
pRect->corner.x = 0;
else if (lpText->align == ALIGN_CENTER)
pRect->corner.x = -(width >> 1);
else
pRect->corner.x = -width;
pRect->corner.y = top_y;
pRect->extent.width = width;
pRect->extent.height = bot_y;
pRect->corner.x += lpText->baseline.x;
pRect->corner.y += lpText->baseline.y;
return (TRUE);
}
}
pRect->corner = lpText->baseline;
pRect->extent.width = 0;
pRect->extent.height = 0;
return (FALSE);
}
void
_text_blt (RECT *pClipRect, TEXT *TextPtr, POINT ctxOrigin)
{
FONT FontPtr;
COUNT num_chars;
UniChar next_ch;
const char *pStr;
POINT origin;
TFB_Image *backing;
DrawMode mode = _get_context_draw_mode ();
FontPtr = _CurFontPtr;
if (FontPtr == NULL)
return;
backing = _get_context_font_backing ();
if (!backing)
return;
origin.x = pClipRect->corner.x;
origin.y = TextPtr->baseline.y;
num_chars = TextPtr->CharCount;
if (num_chars == 0)
return;
pStr = TextPtr->pStr;
next_ch = getCharFromString (&pStr);
if (next_ch == '\0')
num_chars = 0;
while (num_chars--)
{
UniChar ch;
TFB_Char* fontChar;
ch = next_ch;
if (num_chars > 0)
{
next_ch = getCharFromString (&pStr);
if (next_ch == '\0')
num_chars = 0;
}
fontChar = getCharFrame (FontPtr, ch);
if (fontChar != NULL && fontChar->disp.width)
{
RECT r;
r.corner.x = origin.x - fontChar->HotSpot.x;
r.corner.y = origin.y - fontChar->HotSpot.y;
r.extent.width = fontChar->disp.width;
r.extent.height = fontChar->disp.height;
if (BoxIntersect (&r, pClipRect, &r))
{
TFB_Prim_FontChar (origin, fontChar, backing, mode,
ctxOrigin);
}
origin.x += fontChar->disp.width;
#if 0
if (num_chars && next_ch < (UNICODE) MAX_CHARS
&& !(FontPtr->KernTab[ch]
& (FontPtr->KernTab[next_ch] >> 2)))
origin.x -= FontPtr->KernAmount;
#endif
}
}
}
static inline TFB_Char *
getCharFrame (FONT_DESC *fontPtr, UniChar ch)
{
UniChar pageStart = ch & CHARACTER_PAGE_MASK;
size_t charIndex;
FONT_PAGE *page = fontPtr->fontPages;
for (;;)
{
if (page == NULL)
return NULL;
if (page->pageStart == pageStart)
break;
page = page->next;
}
charIndex = ch - page->firstChar;
if (ch >= page->firstChar && charIndex < page->numChars
&& page->charDesc[charIndex].data)
{
return &page->charDesc[charIndex];
}
else
{
//log_add (log_Debug, "Character %u not present", (unsigned int) ch);
return NULL;
}
}

View File

@@ -1,71 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _FONT_H
#define _FONT_H
#include "libs/memlib.h"
#define MAX_DELTAS 100
typedef struct FontPage
{
struct FontPage *next;
UniChar pageStart;
#define CHARACTER_PAGE_MASK 0xfffff800
UniChar firstChar;
size_t numChars;
TFB_Char *charDesc;
} FONT_PAGE;
static inline FONT_PAGE *
AllocFontPage (int numChars)
{
FONT_PAGE *result = HMalloc (sizeof (FONT_PAGE));
result->charDesc = HCalloc (numChars * sizeof *result->charDesc);
return result;
}
static inline void
FreeFontPage (FONT_PAGE *page)
{
HFree (page->charDesc);
HFree (page);
}
struct font_desc
{
UWORD Leading;
UWORD LeadingWidth;
FONT_PAGE *fontPages;
};
#define CHAR_DESCPTR PCHAR_DESC
#define FONT_PRIORITY DEFAULT_MEM_PRIORITY
#define AllocFont(size) (FONT)HCalloc (sizeof (FONT_DESC) + (size))
#define FreeFont _ReleaseFontData
extern FONT _CurFontPtr;
extern void *_GetFontData (uio_Stream *fp, DWORD length);
extern BOOLEAN _ReleaseFontData (void *handle);
#endif /* _FONT_H */

View File

@@ -1,266 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
#include "gfx_common.h"
#include "tfb_draw.h"
#include "tfb_prim.h"
HOT_SPOT
MAKE_HOT_SPOT (COORD x, COORD y)
{
HOT_SPOT hs;
hs.x = x;
hs.y = y;
return hs;
}
// XXX: INTERNAL_PRIMITIVE and INTERNAL_PRIM_DESC are not used
typedef union
{
POINT Point;
STAMP Stamp;
BRESENHAM_LINE Line;
TEXT Text;
RECT Rect;
} INTERNAL_PRIM_DESC;
typedef struct
{
PRIM_LINKS Links;
GRAPHICS_PRIM Type;
Color Color;
INTERNAL_PRIM_DESC Object;
} INTERNAL_PRIMITIVE;
// pValidRect or origin may be NULL
BOOLEAN
GetContextValidRect (RECT *pValidRect, POINT *origin)
{
RECT tempRect;
POINT tempPt;
if (!pValidRect)
pValidRect = &tempRect;
if (!origin)
origin = &tempPt;
// Start with a rect the size of foreground frame
pValidRect->corner.x = 0;
pValidRect->corner.y = 0;
pValidRect->extent = GetFrameBounds (_CurFramePtr);
*origin = _CurFramePtr->HotSpot;
if (_pCurContext->ClipRect.extent.width)
{
// If the cliprect is completely outside of the valid frame
// bounds we have nothing to draw
if (!BoxIntersect (&_pCurContext->ClipRect,
pValidRect, pValidRect))
return (FALSE);
// Foreground frame hotspot defines a drawing position offset
// WRT the context cliprect
origin->x += _pCurContext->ClipRect.corner.x;
origin->y += _pCurContext->ClipRect.corner.y;
}
return (TRUE);
}
static void
ClearBackGround (RECT *pClipRect)
{
RECT clearRect;
Color color = _get_context_bg_color ();
clearRect.corner.x = 0;
clearRect.corner.y = 0;
clearRect.extent = pClipRect->extent;
TFB_Prim_FillRect (&clearRect, color, DRAW_REPLACE_MODE,
pClipRect->corner);
}
void
DrawBatch (PRIMITIVE *lpBasePrim, PRIM_LINKS PrimLinks,
BATCH_FLAGS BatchFlags)
{
RECT ValidRect;
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (&ValidRect, &origin))
{
COUNT CurIndex;
PRIMITIVE *lpPrim;
DrawMode mode = _get_context_draw_mode ();
BatchGraphics ();
if (BatchFlags & BATCH_BUILD_PAGE)
{
ClearBackGround (&ValidRect);
}
CurIndex = GetPredLink (PrimLinks);
for (; CurIndex != END_OF_LIST;
CurIndex = GetSuccLink (GetPrimLinks (lpPrim)))
{
GRAPHICS_PRIM PrimType;
PRIMITIVE *lpWorkPrim;
RECT ClipRect;
Color color;
lpPrim = &lpBasePrim[CurIndex];
PrimType = GetPrimType (lpPrim);
if (!ValidPrimType (PrimType))
continue;
lpWorkPrim = lpPrim;
switch (PrimType)
{
case POINT_PRIM:
color = GetPrimColor (lpWorkPrim);
TFB_Prim_Point (&lpWorkPrim->Object.Point, color,
mode, origin);
break;
case STAMP_PRIM:
TFB_Prim_Stamp (&lpWorkPrim->Object.Stamp, mode, origin);
break;
case STAMPFILL_PRIM:
color = GetPrimColor (lpWorkPrim);
TFB_Prim_StampFill (&lpWorkPrim->Object.Stamp, color,
mode, origin);
break;
case LINE_PRIM:
color = GetPrimColor (lpWorkPrim);
TFB_Prim_Line (&lpWorkPrim->Object.Line, color,
mode, origin);
break;
case TEXT_PRIM:
if (!TextRect (&lpWorkPrim->Object.Text, &ClipRect, NULL))
continue;
// ClipRect is relative to origin
_text_blt (&ClipRect, &lpWorkPrim->Object.Text, origin);
break;
case RECT_PRIM:
color = GetPrimColor (lpWorkPrim);
TFB_Prim_Rect (&lpWorkPrim->Object.Rect, color,
mode, origin);
break;
case RECTFILL_PRIM:
color = GetPrimColor (lpWorkPrim);
TFB_Prim_FillRect (&lpWorkPrim->Object.Rect, color,
mode, origin);
break;
}
}
UnbatchGraphics ();
}
}
void
ClearDrawable (void)
{
RECT ValidRect;
if (GraphicsSystemActive () && GetContextValidRect (&ValidRect, NULL))
{
ClearBackGround (&ValidRect);
}
}
void
DrawPoint (POINT *lpPoint)
{
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (NULL, &origin))
{
Color color = GetPrimColor (&_locPrim);
DrawMode mode = _get_context_draw_mode ();
TFB_Prim_Point (lpPoint, color, mode, origin);
}
}
void
DrawRectangle (RECT *lpRect)
{
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (NULL, &origin))
{
Color color = GetPrimColor (&_locPrim);
DrawMode mode = _get_context_draw_mode ();
TFB_Prim_Rect (lpRect, color, mode, origin);
}
}
void
DrawFilledRectangle (RECT *lpRect)
{
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (NULL, &origin))
{
Color color = GetPrimColor (&_locPrim);
DrawMode mode = _get_context_draw_mode ();
TFB_Prim_FillRect (lpRect, color, mode, origin);
}
}
void
DrawLine (LINE *lpLine)
{
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (NULL, &origin))
{
Color color = GetPrimColor (&_locPrim);
DrawMode mode = _get_context_draw_mode ();
TFB_Prim_Line (lpLine, color, mode, origin);
}
}
void
DrawStamp (STAMP *stmp)
{
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (NULL, &origin))
{
DrawMode mode = _get_context_draw_mode ();
TFB_Prim_Stamp (stmp, mode, origin);
}
}
void
DrawFilledStamp (STAMP *stmp)
{
POINT origin;
if (GraphicsSystemActive () && GetContextValidRect (NULL, &origin))
{
Color color = GetPrimColor (&_locPrim);
DrawMode mode = _get_context_draw_mode ();
TFB_Prim_StampFill (stmp, color, mode, origin);
}
}

View File

@@ -1,196 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
#include "libs/graphics/gfx_common.h"
#include "libs/graphics/drawcmd.h"
#include "libs/timelib.h"
#include "libs/misc.h"
// for TFB_DEBUG_HALT
int ScreenWidth;
int ScreenHeight;
int ScreenWidthActual;
int ScreenHeightActual;
int ScreenColorDepth;
int GraphicsDriver;
int TFB_DEBUG_HALT = 0;
volatile int TransitionAmount = 255;
RECT TransitionClipRect;
static int gscale = GSCALE_IDENTITY;
static int gscale_mode = TFB_SCALE_NEAREST;
void
DrawFromExtraScreen (RECT *r)
{
TFB_DrawScreen_Copy(r, TFB_SCREEN_EXTRA, TFB_SCREEN_MAIN);
}
void
LoadIntoExtraScreen (RECT *r)
{
TFB_DrawScreen_Copy(r, TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA);
}
int
SetGraphicScale (int scale)
{
int old_scale = gscale;
gscale = (scale ? scale : GSCALE_IDENTITY);
return old_scale;
}
int
GetGraphicScale (void)
{
return gscale;
}
int
SetGraphicScaleMode (int mode)
{
int old_mode = gscale_mode;
assert (mode >= TFB_SCALE_NEAREST && mode <= TFB_SCALE_TRILINEAR);
gscale_mode = mode;
return old_mode;
}
int
GetGraphicScaleMode (void)
{
return gscale_mode;
}
/* Batching and Unbatching functions. A "Batch" is a collection of
DrawCommands that will never be flipped to the screen half-rendered.
BatchGraphics and UnbatchGraphics function vaguely like a non-blocking
recursive lock to do this respect. */
void
BatchGraphics (void)
{
TFB_BatchGraphics ();
}
void
UnbatchGraphics (void)
{
TFB_UnbatchGraphics ();
}
/* Sleeps this thread until all Draw Commands queued by that thread have
been processed. */
void
FlushGraphics ()
{
TFB_DrawScreen_WaitForSignal ();
}
static void
ExpandRect (RECT *rect, int expansion)
{
if (rect->corner.x - expansion >= 0)
{
rect->extent.width += expansion;
rect->corner.x -= expansion;
}
else
{
rect->extent.width += rect->corner.x;
rect->corner.x = 0;
}
if (rect->corner.y - expansion >= 0)
{
rect->extent.height += expansion;
rect->corner.y -= expansion;
}
else
{
rect->extent.height += rect->corner.y;
rect->corner.y = 0;
}
if (rect->corner.x + rect->extent.width + expansion <= ScreenWidth)
rect->extent.width += expansion;
else
rect->extent.width = ScreenWidth - rect->corner.x;
if (rect->corner.y + rect->extent.height + expansion <= ScreenHeight)
rect->extent.height += expansion;
else
rect->extent.height = ScreenHeight - rect->corner.y;
}
void
SetTransitionSource (const RECT *pRect)
{
RECT ActualRect;
if (pRect)
{ /* expand the rect to accomodate scalers in OpenGL mode */
ActualRect = *pRect;
pRect = &ActualRect;
ExpandRect (&ActualRect, 2);
}
TFB_DrawScreen_Copy (pRect, TFB_SCREEN_MAIN, TFB_SCREEN_TRANSITION);
}
// ScreenTransition() is synchronous (does not return until transition done)
void
ScreenTransition (int TransType, const RECT *pRect)
{
const TimePeriod DURATION = ONE_SECOND * 31 / 60;
TimeCount startTime;
(void) TransType; /* dodge compiler warning */
if (pRect)
{
TransitionClipRect = *pRect;
}
else
{
TransitionClipRect.corner.x = 0;
TransitionClipRect.corner.y = 0;
TransitionClipRect.extent.width = ScreenWidth;
TransitionClipRect.extent.height = ScreenHeight;
}
TFB_UploadTransitionScreen ();
TransitionAmount = 0;
FlushGraphics ();
startTime = GetTimeCounter ();
while (TransitionAmount < 255)
{
TimePeriod deltaT;
int newAmount;
SleepThread (ONE_SECOND / 100);
deltaT = GetTimeCounter () - startTime;
newAmount = deltaT * 255 / DURATION;
if (newAmount > 255)
newAmount = 255;
TransitionAmount = newAmount;
}
}

View File

@@ -1,109 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef GFX_COMMON_H
#define GFX_COMMON_H
#include <stdio.h>
#include <stdlib.h>
#include "libs/gfxlib.h"
// driver for TFB_InitGraphics
enum
{
TFB_GFXDRIVER_SDL_OPENGL,
TFB_GFXDRIVER_SDL_PURE,
};
// forced redraw
enum
{
TFB_REDRAW_NO = 0,
TFB_REDRAW_FADING,
TFB_REDRAW_EXPOSE,
TFB_REDRAW_YES
};
// flags for TFB_InitGraphics
#define TFB_GFXFLAGS_FULLSCREEN (1<<0)
#define TFB_GFXFLAGS_SHOWFPS (1<<1)
#define TFB_GFXFLAGS_SCANLINES (1<<2)
#define TFB_GFXFLAGS_SCALE_BILINEAR (1<<3)
#define TFB_GFXFLAGS_SCALE_BIADAPT (1<<4)
#define TFB_GFXFLAGS_SCALE_BIADAPTADV (1<<5)
#define TFB_GFXFLAGS_SCALE_TRISCAN (1<<6)
#define TFB_GFXFLAGS_SCALE_HQXX (1<<7)
#define TFB_GFXFLAGS_SCALE_ANY \
( TFB_GFXFLAGS_SCALE_BILINEAR | \
TFB_GFXFLAGS_SCALE_BIADAPT | \
TFB_GFXFLAGS_SCALE_BIADAPTADV | \
TFB_GFXFLAGS_SCALE_TRISCAN | \
TFB_GFXFLAGS_SCALE_HQXX )
#define TFB_GFXFLAGS_SCALE_SOFT_ONLY \
( TFB_GFXFLAGS_SCALE_ANY & ~TFB_GFXFLAGS_SCALE_BILINEAR )
// The flag variable itself
extern int GfxFlags;
// The following functions are driver-defined
void TFB_PreInit (void);
int TFB_InitGraphics (int driver, int flags, int width, int height);
int TFB_ReInitGraphics (int driver, int flags, int width, int height);
void TFB_UninitGraphics (void);
void TFB_ProcessEvents (void);
void TFB_SetGamma (float gamma);
void TFB_UploadTransitionScreen (void);
// This function should not be called directly
void TFB_SwapBuffers (int force_full_redraw);
#define GSCALE_IDENTITY 256
typedef enum {
TFB_SCALE_STEP, /* not really a scaler */
TFB_SCALE_NEAREST,
TFB_SCALE_BILINEAR,
TFB_SCALE_TRILINEAR
} SCALE;
void LoadIntoExtraScreen (RECT *r);
void DrawFromExtraScreen (RECT *r);
int SetGraphicScale (int scale);
int GetGraphicScale (void);
int SetGraphicScaleMode (int mode /* enum SCALE */);
int GetGraphicScaleMode (void);
void SetTransitionSource (const RECT *pRect);
void ScreenTransition (int transition, const RECT *pRect);
// TODO: there should be accessor functions for these
extern volatile int TransitionAmount;
extern RECT TransitionClipRect;
extern float FrameRate;
extern int FrameRateTickBase;
void TFB_FlushGraphics (void); // Only call from main thread!!
extern int ScreenWidth;
extern int ScreenHeight;
extern int ScreenWidthActual;
extern int ScreenHeightActual;
extern int ScreenColorDepth;
extern int GraphicsDriver;
#endif

View File

@@ -1,32 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _GFXINTRN_H
#define _GFXINTRN_H
#include <stdio.h>
#include <string.h>
#include "libs/gfxlib.h"
#include "libs/reslib.h"
#include "context.h"
#include "drawable.h"
#include "font.h"
#endif /* _GFXINTRN_H */

View File

@@ -1,605 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 <string.h>
#include <stdio.h>
#include "options.h"
#include "port.h"
#include "libs/uio.h"
#include "libs/reslib.h"
// for _cur_resfile_name
#include "libs/log.h"
#include "libs/memlib.h"
#include "libs/graphics/tfb_draw.h"
#include "libs/graphics/drawable.h"
#include "libs/graphics/font.h"
typedef struct anidata
{
int transparent_color;
int colormap_index;
int hotspot_x;
int hotspot_y;
} AniData;
extern uio_Repository *repository;
static uio_AutoMount *autoMount[] = { NULL };
static void
process_image (FRAME FramePtr, TFB_Canvas img[], AniData *ani, int cel_ct)
{
TFB_Image *tfbimg;
int hx, hy;
FramePtr->Type = ROM_DRAWABLE;
FramePtr->Index = cel_ct;
// handle transparency cases
if (TFB_DrawCanvas_IsPaletted (img[cel_ct]))
{ // indexed color image
if (ani[cel_ct].transparent_color >= 0)
{
TFB_DrawCanvas_SetTransparentIndex (img[cel_ct],
ani[cel_ct].transparent_color, FALSE);
}
}
else
{ // special transparency cases for truecolor images
if (ani[cel_ct].transparent_color == 0)
{ // make RGB=0,0,0 transparent
Color color = {0, 0, 0, 0};
TFB_DrawCanvas_SetTransparentColor (img[cel_ct], color, FALSE);
}
}
if (ani[cel_ct].transparent_color == -1)
{ // enforce -1 to mean 'no transparency'
TFB_DrawCanvas_SetTransparentIndex (img[cel_ct], -1, FALSE);
// set transparent_color == -2 to use PNG tRNS transparency
}
hx = ani[cel_ct].hotspot_x;
hy = ani[cel_ct].hotspot_y;
FramePtr->image = TFB_DrawImage_New (img[cel_ct]);
tfbimg = FramePtr->image;
tfbimg->colormap_index = ani[cel_ct].colormap_index;
img[cel_ct] = tfbimg->NormalImg;
FramePtr->HotSpot = MAKE_HOT_SPOT (hx, hy);
SetFrameBounds (FramePtr, tfbimg->extent.width, tfbimg->extent.height);
#ifdef CLIPDEBUG
{
/* for debugging clipping:
draws white (or most matching color from palette) pixels to
every corner of the image
*/
Color color = {0xff, 0xff, 0xff, 0xff};
RECT r = {{0, 0}, {1, 1}};
if (tfbimg->extent.width > 2 && tfbimg->extent.height > 2)
{
TFB_DrawImage_Rect (&r, color, tfbimg);
r.corner.x = tfbimg->extent.width - 1;
TFB_DrawImage_Rect (&r, color, tfbimg);
r.corner.y = tfbimg->extent.height - 1;
TFB_DrawImage_Rect (&r, color, tfbimg);
r.corner.x = 0;
TFB_DrawImage_Rect (&r, color, tfbimg);
}
}
#endif
}
static void
processFontChar (TFB_Char* CharPtr, TFB_Canvas canvas)
{
BYTE* newdata;
size_t dpitch;
TFB_DrawCanvas_GetExtent (canvas, &CharPtr->extent);
// Currently, each font char has its own separate data
// but that can change to common mem area
dpitch = CharPtr->extent.width;
newdata = HMalloc (dpitch * CharPtr->extent.height * sizeof (BYTE));
TFB_DrawCanvas_GetFontCharData (canvas, newdata, dpitch);
CharPtr->data = newdata;
CharPtr->pitch = dpitch;
CharPtr->disp.width = CharPtr->extent.width + 1;
CharPtr->disp.height = CharPtr->extent.height + 1;
// XXX: why the +1?
// I brought it into this function from the only calling
// function, but I don't know why it was there in the first
// place.
// XXX: the +1 appears to be for character and line spacing
// text_blt just adds the frame width to move to the next char
{
// This tunes the font positioning to be about what it should
// TODO: prolly needs a little tweaking still
int tune_amount = 0;
if (CharPtr->extent.height == 8)
tune_amount = -1;
else if (CharPtr->extent.height == 9)
tune_amount = -2;
else if (CharPtr->extent.height > 9)
tune_amount = -3;
CharPtr->HotSpot = MAKE_HOT_SPOT (0,
CharPtr->extent.height + tune_amount);
}
}
void *
_GetCelData (uio_Stream *fp, DWORD length)
{
int cel_total, cel_index, n;
DWORD opos;
char CurrentLine[1024], filename[PATH_MAX];
TFB_Canvas *img;
AniData *ani;
DRAWABLE Drawable;
uio_MountHandle *aniMount = 0;
uio_DirHandle *aniDir = 0;
uio_Stream *aniFile = 0;
opos = uio_ftell (fp);
{
char *s1, *s2;
char aniDirName[PATH_MAX];
const char *aniFileName;
uint8 buf[4] = { 0, 0, 0, 0 };
uint32 header;
if (_cur_resfile_name == 0
|| (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
{
n = 0;
}
else
{
if (s2 > s1)
s1 = s2;
n = s1 - _cur_resfile_name + 1;
}
uio_fread(buf, 4, 1, fp);
header = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
if (_cur_resfile_name && header == 0x04034b50)
{
// zipped ani file
if (n)
{
strncpy (aniDirName, _cur_resfile_name, n - 1);
aniDirName[n - 1] = 0;
aniFileName = _cur_resfile_name + n;
}
else
{
strcpy(aniDirName, ".");
aniFileName = _cur_resfile_name;
}
aniDir = uio_openDir (repository, aniDirName, 0);
aniMount = uio_mountDir (repository, aniDirName, uio_FSTYPE_ZIP,
aniDir, aniFileName, "/", autoMount,
uio_MOUNT_RDONLY | uio_MOUNT_TOP,
NULL);
aniFile = uio_fopen (aniDir, aniFileName, "r");
opos = 0;
n = 0;
}
else
{
// unpacked ani file
strncpy (filename, _cur_resfile_name, n);
aniFile = fp;
aniDir = contentDir;
}
}
cel_total = 0;
uio_fseek (aniFile, opos, SEEK_SET);
while (uio_fgets (CurrentLine, sizeof (CurrentLine), aniFile))
{
++cel_total;
}
img = HMalloc (sizeof (TFB_Canvas) * cel_total);
ani = HMalloc (sizeof (AniData) * cel_total);
if (!img || !ani)
{
log_add (log_Warning, "Couldn't allocate space for '%s'", _cur_resfile_name);
if (aniMount)
{
uio_fclose(aniFile);
uio_closeDir(aniDir);
uio_unmountDir(aniMount);
}
HFree (img);
HFree (ani);
return NULL;
}
cel_index = 0;
uio_fseek (aniFile, opos, SEEK_SET);
while (uio_fgets (CurrentLine, sizeof (CurrentLine), aniFile) && cel_index < cel_total)
{
sscanf (CurrentLine, "%s %d %d %d %d", &filename[n],
&ani[cel_index].transparent_color, &ani[cel_index].colormap_index,
&ani[cel_index].hotspot_x, &ani[cel_index].hotspot_y);
img[cel_index] = TFB_DrawCanvas_LoadFromFile (aniDir, filename);
if (img[cel_index] == NULL)
{
const char *err;
err = TFB_DrawCanvas_GetError ();
log_add (log_Warning, "_GetCelData: Unable to load image!");
if (err != NULL)
log_add (log_Warning, "Gfx Driver reports: %s", err);
}
else
{
++cel_index;
}
if ((int)uio_ftell (aniFile) - (int)opos >= (int)length)
break;
}
Drawable = NULL;
if (cel_index && (Drawable = AllocDrawable (cel_index)))
{
if (!Drawable)
{
while (cel_index--)
TFB_DrawCanvas_Delete (img[cel_index]);
HFree (Drawable);
Drawable = NULL;
}
else
{
FRAME FramePtr;
Drawable->Flags = WANT_PIXMAP;
Drawable->MaxIndex = cel_index - 1;
FramePtr = &Drawable->Frame[cel_index];
while (--FramePtr, cel_index--)
process_image (FramePtr, img, ani, cel_index);
}
}
if (Drawable == NULL)
log_add (log_Warning, "Couldn't get cel data for '%s'",
_cur_resfile_name);
if (aniMount)
{
uio_fclose(aniFile);
uio_closeDir(aniDir);
uio_unmountDir(aniMount);
}
HFree (img);
HFree (ani);
return Drawable;
}
BOOLEAN
_ReleaseCelData (void *handle)
{
DRAWABLE DrawablePtr;
int cel_ct;
FRAME FramePtr = NULL;
if ((DrawablePtr = handle) == 0)
return (FALSE);
cel_ct = DrawablePtr->MaxIndex + 1;
if (DrawablePtr->Frame)
{
FramePtr = DrawablePtr->Frame;
if (FramePtr->Type == SCREEN_DRAWABLE)
{
FramePtr = NULL;
}
}
HFree (handle);
if (FramePtr)
{
int i;
for (i = 0; i < cel_ct; i++)
{
TFB_Image *img = FramePtr[i].image;
if (img)
{
FramePtr[i].image = NULL;
TFB_DrawScreen_DeleteImage (img);
}
}
HFree (FramePtr);
}
return (TRUE);
}
typedef struct BuildCharDesc
{
TFB_Canvas canvas;
UniChar index;
} BuildCharDesc;
static int
compareBCDIndex (const void *arg1, const void *arg2)
{
const BuildCharDesc *bcd1 = (const BuildCharDesc *) arg1;
const BuildCharDesc *bcd2 = (const BuildCharDesc *) arg2;
return (int) bcd1->index - (int) bcd2->index;
}
void *
_GetFontData (uio_Stream *fp, DWORD length)
{
COUNT numDirEntries;
DIRENTRY fontDir = NULL;
BuildCharDesc *bcds = NULL;
size_t numBCDs = 0;
int dirEntryI;
uio_DirHandle *fontDirHandle = NULL;
uio_MountHandle *fontMount = NULL;
FONT fontPtr = NULL;
if (_cur_resfile_name == 0)
goto err;
if (fp != (uio_Stream*)~0)
{
// font is zipped instead of being in a directory
char *s1, *s2;
int n;
const char *fontZipName;
char fontDirName[PATH_MAX];
if ((((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
{
strcpy(fontDirName, ".");
fontZipName = _cur_resfile_name;
}
else
{
if (s2 > s1)
s1 = s2;
n = s1 - _cur_resfile_name + 1;
strncpy (fontDirName, _cur_resfile_name, n - 1);
fontDirName[n - 1] = 0;
fontZipName = _cur_resfile_name + n;
}
fontDirHandle = uio_openDir (repository, fontDirName, 0);
fontMount = uio_mountDir (repository, _cur_resfile_name, uio_FSTYPE_ZIP,
fontDirHandle, fontZipName, "/", autoMount,
uio_MOUNT_RDONLY | uio_MOUNT_TOP,
NULL);
uio_closeDir (fontDirHandle);
}
fontDir = CaptureDirEntryTable (LoadDirEntryTable (contentDir,
_cur_resfile_name, ".", match_MATCH_SUBSTRING));
if (fontDir == 0)
goto err;
numDirEntries = GetDirEntryTableCount (fontDir);
fontDirHandle = uio_openDirRelative (contentDir, _cur_resfile_name, 0);
if (fontDirHandle == NULL)
goto err;
bcds = HMalloc (numDirEntries * sizeof (BuildCharDesc));
if (bcds == NULL)
goto err;
// Load the surfaces for all dir Entries
for (dirEntryI = 0; dirEntryI < numDirEntries; dirEntryI++)
{
char *char_name;
unsigned int charIndex;
TFB_Canvas canvas;
EXTENT size;
char_name = GetDirEntryAddress (SetAbsDirEntryTableIndex (
fontDir, dirEntryI));
if (sscanf (char_name, "%x.", &charIndex) != 1)
continue;
if (charIndex > 0xffff)
continue;
canvas = TFB_DrawCanvas_LoadFromFile (fontDirHandle, char_name);
if (canvas == NULL)
continue;
TFB_DrawCanvas_GetExtent (canvas, &size);
if (size.width == 0 || size.height == 0)
{
TFB_DrawCanvas_Delete (canvas);
continue;
}
bcds[numBCDs].canvas = canvas;
bcds[numBCDs].index = charIndex;
numBCDs++;
}
uio_closeDir (fontDirHandle);
DestroyDirEntryTable (ReleaseDirEntryTable (fontDir));
if (fontMount != 0)
uio_unmountDir(fontMount);
#if 0
if (numBCDs == 0)
goto err;
#endif
// sort on the character index
qsort (bcds, numBCDs, sizeof (BuildCharDesc), compareBCDIndex);
fontPtr = AllocFont (0);
if (fontPtr == NULL)
goto err;
fontPtr->Leading = 0;
fontPtr->LeadingWidth = 0;
{
size_t startBCD = 0;
UniChar pageStart;
FONT_PAGE **pageEndPtr = &fontPtr->fontPages;
while (startBCD < numBCDs)
{
// Process one character page.
size_t endBCD;
pageStart = bcds[startBCD].index & CHARACTER_PAGE_MASK;
endBCD = startBCD;
while (endBCD < numBCDs &&
(bcds[endBCD].index & CHARACTER_PAGE_MASK) == pageStart)
endBCD++;
{
size_t bcdI;
int numChars = bcds[endBCD - 1].index + 1
- bcds[startBCD].index;
FONT_PAGE *page = AllocFontPage (numChars);
page->pageStart = pageStart;
page->firstChar = bcds[startBCD].index;
page->numChars = numChars;
*pageEndPtr = page;
pageEndPtr = &page->next;
for (bcdI = startBCD; bcdI < endBCD; bcdI++)
{
// Process one character.
BuildCharDesc *bcd = &bcds[bcdI];
TFB_Char *destChar =
&page->charDesc[bcd->index - page->firstChar];
if (destChar->data != NULL)
{
// There's already an image for this character.
log_add (log_Debug, "Duplicate image for character %d "
"for font %s.", (int) bcd->index,
_cur_resfile_name);
TFB_DrawCanvas_Delete (bcd->canvas);
continue;
}
processFontChar (destChar, bcd->canvas);
TFB_DrawCanvas_Delete (bcd->canvas);
if (destChar->disp.height > fontPtr->Leading)
fontPtr->Leading = destChar->disp.height;
if (destChar->disp.width > fontPtr->LeadingWidth)
fontPtr->LeadingWidth = destChar->disp.width;
}
}
startBCD = endBCD;
}
*pageEndPtr = NULL;
}
fontPtr->Leading++;
HFree (bcds);
(void) fp; /* Satisfying compiler (unused parameter) */
(void) length; /* Satisfying compiler (unused parameter) */
return fontPtr;
err:
if (fontPtr != 0)
HFree (fontPtr);
if (bcds != NULL)
{
size_t bcdI;
for (bcdI = 0; bcdI < numBCDs; bcdI++)
TFB_DrawCanvas_Delete (bcds[bcdI].canvas);
HFree (bcds);
}
if (fontDirHandle != NULL)
uio_closeDir (fontDirHandle);
if (fontDir != 0)
DestroyDirEntryTable (ReleaseDirEntryTable (fontDir));
if (fontMount != 0)
uio_unmountDir(fontMount);
return 0;
}
BOOLEAN
_ReleaseFontData (void *handle)
{
FONT font = (FONT) handle;
if (font == NULL)
return FALSE;
{
FONT_PAGE *page;
FONT_PAGE *nextPage;
for (page = font->fontPages; page != NULL; page = nextPage)
{
size_t charI;
for (charI = 0; charI < page->numChars; charI++)
{
TFB_Char *c = &page->charDesc[charI];
if (c->data == NULL)
continue;
// XXX: fix this if fonts get per-page data
// rather than per-char
TFB_DrawScreen_DeleteData (c->data);
}
nextPage = page->next;
FreeFontPage (page);
}
}
HFree (font);
return TRUE;
}

View File

@@ -1,415 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "libs/graphics/context.h"
#include "libs/graphics/drawable.h"
#include "libs/graphics/tfb_draw.h"
#include "libs/log.h"
//#define DEBUG_INTERSEC
static inline BOOLEAN
images_intersect (IMAGE_BOX *box1, IMAGE_BOX *box2, const RECT *rect)
{
return TFB_DrawImage_Intersect (box1->FramePtr->image, box1->Box.corner,
box2->FramePtr->image, box2->Box.corner, rect);
}
static TIME_VALUE
frame_intersect (INTERSECT_CONTROL *pControl0, RECT *pr0,
INTERSECT_CONTROL *pControl1, RECT *pr1, TIME_VALUE t0,
TIME_VALUE t1)
{
SIZE time_error0, time_error1;
SIZE cycle0, cycle1;
SIZE dx_0, dy_0, dx_1, dy_1;
SIZE xincr0, yincr0, xincr1, yincr1;
SIZE xerror0, xerror1, yerror0, yerror1;
RECT r_intersect;
IMAGE_BOX IB0, IB1;
BOOLEAN check0, check1;
IB0.FramePtr = pControl0->IntersectStamp.frame;
IB0.Box.corner = pr0->corner;
IB0.Box.extent.width = GetFrameWidth (IB0.FramePtr);
IB0.Box.extent.height = GetFrameHeight (IB0.FramePtr);
IB1.FramePtr = pControl1->IntersectStamp.frame;
IB1.Box.corner = pr1->corner;
IB1.Box.extent.width = GetFrameWidth (IB1.FramePtr);
IB1.Box.extent.height = GetFrameHeight (IB1.FramePtr);
dx_0 = pr0->extent.width;
dy_0 = pr0->extent.height;
if (dx_0 >= 0)
xincr0 = 1;
else
{
xincr0 = -1;
dx_0 = -dx_0;
}
if (dy_0 >= 0)
yincr0 = 1;
else
{
yincr0 = -1;
dy_0 = -dy_0;
}
if (dx_0 >= dy_0)
cycle0 = dx_0;
else
cycle0 = dy_0;
xerror0 = yerror0 = cycle0;
dx_1 = pr1->extent.width;
dy_1 = pr1->extent.height;
if (dx_1 >= 0)
xincr1 = 1;
else
{
xincr1 = -1;
dx_1 = -dx_1;
}
if (dy_1 >= 0)
yincr1 = 1;
else
{
yincr1 = -1;
dy_1 = -dy_1;
}
if (dx_1 >= dy_1)
cycle1 = dx_1;
else
cycle1 = dy_1;
xerror1 = yerror1 = cycle1;
check0 = check1 = FALSE;
if (t0 <= 1)
{
time_error0 = time_error1 = 0;
if (t0 == 0)
{
++t0;
goto CheckFirstIntersection;
}
}
else
{
SIZE delta;
COUNT start;
long error;
start = (COUNT)cycle0 * (COUNT)(t0 - 1);
time_error0 = start & ((1 << TIME_SHIFT) - 1);
if ((start >>= (COUNT)TIME_SHIFT) > 0)
{
if ((error = (long)xerror0
- (long)dx_0 * (long)start) > 0)
xerror0 = (SIZE)error;
else
{
delta = -(SIZE)(error / (long)cycle0) + 1;
IB0.Box.corner.x += xincr0 * delta;
xerror0 = (SIZE)(error + (long)cycle0 * (long)delta);
}
if ((error = (long)yerror0
- (long)dy_0 * (long)start) > 0)
yerror0 = (SIZE)error;
else
{
delta = -(SIZE)(error / (long)cycle0) + 1;
IB0.Box.corner.y += yincr0 * delta;
yerror0 = (SIZE)(error + (long)cycle0 * (long)delta);
}
pr0->corner = IB0.Box.corner;
}
start = (COUNT)cycle1 * (COUNT)(t0 - 1);
time_error1 = start & ((1 << TIME_SHIFT) - 1);
if ((start >>= (COUNT)TIME_SHIFT) > 0)
{
if ((error = (long)xerror1
- (long)dx_1 * (long)start) > 0)
xerror1 = (SIZE)error;
else
{
delta = -(SIZE)(error / (long)cycle1) + 1;
IB1.Box.corner.x += xincr1 * delta;
xerror1 = (SIZE)(error + (long)cycle1 * (long)delta);
}
if ((error = (long)yerror1
- (long)dy_1 * (long)start) > 0)
yerror1 = (SIZE)error;
else
{
delta = -(SIZE)(error / (long)cycle1) + 1;
IB1.Box.corner.y += yincr1 * delta;
yerror1 = (SIZE)(error + (long)cycle1 * (long)delta);
}
pr1->corner = IB1.Box.corner;
}
}
pControl0->last_time_val = pControl1->last_time_val = t0;
do
{
++t0;
if ((time_error0 += cycle0) >= (1 << TIME_SHIFT))
{
if ((xerror0 -= dx_0) <= 0)
{
IB0.Box.corner.x += xincr0;
xerror0 += cycle0;
}
if ((yerror0 -= dy_0) <= 0)
{
IB0.Box.corner.y += yincr0;
yerror0 += cycle0;
}
check0 = TRUE;
time_error0 -= (1 << TIME_SHIFT);
}
if ((time_error1 += cycle1) >= (1 << TIME_SHIFT))
{
if ((xerror1 -= dx_1) <= 0)
{
IB1.Box.corner.x += xincr1;
xerror1 += cycle1;
}
if ((yerror1 -= dy_1) <= 0)
{
IB1.Box.corner.y += yincr1;
yerror1 += cycle1;
}
check1 = TRUE;
time_error1 -= (1 << TIME_SHIFT);
}
if (check0 || check1)
{ /* if check0 && check1, this may not be quite right --
* if shapes had a pixel's separation to begin with
* and both moved toward each other, you would actually
* get a pixel overlap but since the last positions were
* separated by a pixel, the shapes wouldn't be touching
* each other.
*/
CheckFirstIntersection:
if (BoxIntersect (&IB0.Box, &IB1.Box, &r_intersect)
&& images_intersect (&IB0, &IB1, &r_intersect))
return (t0);
if (check0)
{
pr0->corner = IB0.Box.corner;
pControl0->last_time_val = t0;
check0 = FALSE;
}
if (check1)
{
pr1->corner = IB1.Box.corner;
pControl1->last_time_val = t0;
check1 = FALSE;
}
}
} while (t0 <= t1);
return ((TIME_VALUE)0);
}
TIME_VALUE
DrawablesIntersect (INTERSECT_CONTROL *pControl0,
INTERSECT_CONTROL *pControl1, TIME_VALUE max_time_val)
{
SIZE dy;
SIZE time_y_0, time_y_1;
RECT r0, r1;
FRAME FramePtr0, FramePtr1;
if (!ContextActive () || max_time_val == 0)
return ((TIME_VALUE)0);
else if (max_time_val > MAX_TIME_VALUE)
max_time_val = MAX_TIME_VALUE;
pControl0->last_time_val = pControl1->last_time_val = 0;
r0.corner = pControl0->IntersectStamp.origin;
r1.corner = pControl1->IntersectStamp.origin;
r0.extent.width = pControl0->EndPoint.x - r0.corner.x;
r0.extent.height = pControl0->EndPoint.y - r0.corner.y;
r1.extent.width = pControl1->EndPoint.x - r1.corner.x;
r1.extent.height = pControl1->EndPoint.y - r1.corner.y;
FramePtr0 = pControl0->IntersectStamp.frame;
if (FramePtr0 == 0)
return(0);
r0.corner.x -= FramePtr0->HotSpot.x;
r0.corner.y -= FramePtr0->HotSpot.y;
FramePtr1 = pControl1->IntersectStamp.frame;
if (FramePtr1 == 0)
return(0);
r1.corner.x -= FramePtr1->HotSpot.x;
r1.corner.y -= FramePtr1->HotSpot.y;
dy = r1.corner.y - r0.corner.y;
time_y_0 = dy - GetFrameHeight (FramePtr0) + 1;
time_y_1 = dy + GetFrameHeight (FramePtr1) - 1;
dy = r0.extent.height - r1.extent.height;
if ((time_y_0 <= 0 && time_y_1 >= 0)
|| (time_y_0 > 0 && dy >= time_y_0)
|| (time_y_1 < 0 && dy <= time_y_1))
{
SIZE dx;
SIZE time_x_0, time_x_1;
dx = r1.corner.x - r0.corner.x;
time_x_0 = dx - GetFrameWidth (FramePtr0) + 1;
time_x_1 = dx + GetFrameWidth (FramePtr1) - 1;
dx = r0.extent.width - r1.extent.width;
if ((time_x_0 <= 0 && time_x_1 >= 0)
|| (time_x_0 > 0 && dx >= time_x_0)
|| (time_x_1 < 0 && dx <= time_x_1))
{
TIME_VALUE intersect_time;
if (dx == 0 && dy == 0)
time_y_0 = time_y_1 = 0;
else
{
SIZE t;
long time_beg, time_end, fract;
if (time_y_1 < 0)
{
t = time_y_0;
time_y_0 = -time_y_1;
time_y_1 = -t;
}
else if (time_y_0 <= 0)
{
if (dy < 0)
time_y_1 = -time_y_0;
time_y_0 = 0;
}
if (dy < 0)
dy = -dy;
if (dy < time_y_1)
time_y_1 = dy;
/* just to be safe, widen search area */
--time_y_0;
++time_y_1;
if (time_x_1 < 0)
{
t = time_x_0;
time_x_0 = -time_x_1;
time_x_1 = -t;
}
else if (time_x_0 <= 0)
{
if (dx < 0)
time_x_1 = -time_x_0;
time_x_0 = 0;
}
if (dx < 0)
dx = -dx;
if (dx < time_x_1)
time_x_1 = dx;
/* just to be safe, widen search area */
--time_x_0;
++time_x_1;
#ifdef DEBUG_INTERSEC
log_add (log_Debug, "FramePtr0<%d, %d> --> <%d, %d>",
GetFrameWidth (FramePtr0), GetFrameHeight (FramePtr0),
r0.corner.x, r0.corner.y);
log_add (log_Debug, "FramePtr1<%d, %d> --> <%d, %d>",
GetFrameWidth (FramePtr1), GetFrameHeight (FramePtr1),
r1.corner.x, r1.corner.y);
log_add (log_Debug, "time_x(%d, %d)-%d, time_y(%d, %d)-%d",
time_x_0, time_x_1, dx, time_y_0, time_y_1, dy);
#endif /* DEBUG_INTERSEC */
if (dx == 0)
{
time_beg = time_y_0;
time_end = time_y_1;
fract = dy;
}
else if (dy == 0)
{
time_beg = time_x_0;
time_end = time_x_1;
fract = dx;
}
else
{
long time_x, time_y;
time_x = (long)time_x_0 * (long)dy;
time_y = (long)time_y_0 * (long)dx;
time_beg = time_x < time_y ? time_y : time_x;
time_x = (long)time_x_1 * (long)dy;
time_y = (long)time_y_1 * (long)dx;
time_end = time_x > time_y ? time_y : time_x;
fract = (long)dx * (long)dy;
}
if ((time_beg <<= TIME_SHIFT) < fract)
time_y_0 = 0;
else
time_y_0 = (SIZE)(time_beg / fract);
if (time_end >= fract /* just in case of overflow */
|| (time_end <<= TIME_SHIFT) >=
fract * (long)max_time_val)
time_y_1 = max_time_val - 1;
else
time_y_1 = (SIZE)((time_end + fract - 1) / fract) - 1;
}
#ifdef DEBUG_INTERSEC
log_add (log_Debug, "start_time = %d, end_time = %d",
time_y_0, time_y_1);
#endif /* DEBUG_INTERSEC */
if (time_y_0 <= time_y_1
&& (intersect_time = frame_intersect (
pControl0, &r0, pControl1, &r1,
(TIME_VALUE)time_y_0, (TIME_VALUE)time_y_1)))
{
FramePtr0 = pControl0->IntersectStamp.frame;
pControl0->EndPoint.x = r0.corner.x + FramePtr0->HotSpot.x;
pControl0->EndPoint.y = r0.corner.y + FramePtr0->HotSpot.y;
FramePtr1 = pControl1->IntersectStamp.frame;
pControl1->EndPoint.x = r1.corner.x + FramePtr1->HotSpot.x;
pControl1->EndPoint.y = r1.corner.y + FramePtr1->HotSpot.y;
return (intersect_time);
}
}
}
return ((TIME_VALUE)0);
}

View File

@@ -1,65 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "libs/gfxlib.h"
#include "libs/graphics/drawable.h"
#include "libs/log.h"
// Reads a piece of screen into a passed FRAME or a newly created one
DRAWABLE
LoadDisplayPixmap (const RECT *area, FRAME frame)
{
// TODO: This should just return a FRAME instead of DRAWABLE
DRAWABLE buffer = GetFrameParentDrawable (frame);
COUNT index;
if (!buffer)
{ // asked to create a new DRAWABLE instead
buffer = CreateDrawable (WANT_PIXMAP | MAPPED_TO_DISPLAY,
area->extent.width, area->extent.height, 1);
if (!buffer)
return NULL;
index = 0;
}
else
{
index = GetFrameIndex (frame);
}
frame = SetAbsFrameIndex (CaptureDrawable (buffer), index);
if (_CurFramePtr->Type != SCREEN_DRAWABLE
|| frame->Type == SCREEN_DRAWABLE
|| !(GetFrameParentDrawable (frame)->Flags & MAPPED_TO_DISPLAY))
{
log_add (log_Warning, "Unimplemented function activated: "
"LoadDisplayPixmap()");
}
else
{
TFB_Image *img = frame->image;
TFB_DrawScreen_CopyToImage (img, area, TFB_SCREEN_MAIN);
}
ReleaseDrawable (frame);
return buffer;
}

View File

@@ -1,170 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
#include "libs/log.h"
DRAWABLE
GetFrameParentDrawable (FRAME f)
{
if (f != NULL)
{
return f->parent;
}
return NULL;
}
FRAME
CaptureDrawable (DRAWABLE DrawablePtr)
{
if (DrawablePtr)
{
return &DrawablePtr->Frame[0];
}
return NULL;
}
DRAWABLE
ReleaseDrawable (FRAME FramePtr)
{
if (FramePtr != 0)
{
DRAWABLE Drawable;
Drawable = GetFrameParentDrawable (FramePtr);
return (Drawable);
}
return NULL;
}
COUNT
GetFrameCount (FRAME FramePtr)
{
DRAWABLE_DESC *DrawablePtr;
if (FramePtr == 0)
return (0);
DrawablePtr = GetFrameParentDrawable (FramePtr);
return DrawablePtr->MaxIndex + 1;
}
COUNT
GetFrameIndex (FRAME FramePtr)
{
if (FramePtr == 0)
return (0);
return FramePtr->Index;
}
FRAME
SetAbsFrameIndex (FRAME FramePtr, COUNT FrameIndex)
{
if (FramePtr != 0)
{
DRAWABLE_DESC *DrawablePtr;
DrawablePtr = GetFrameParentDrawable (FramePtr);
FrameIndex = FrameIndex % (DrawablePtr->MaxIndex + 1);
FramePtr = &DrawablePtr->Frame[FrameIndex];
}
return FramePtr;
}
FRAME
SetRelFrameIndex (FRAME FramePtr, SIZE FrameOffs)
{
if (FramePtr != 0)
{
COUNT num_frames;
DRAWABLE_DESC *DrawablePtr;
DrawablePtr = GetFrameParentDrawable (FramePtr);
num_frames = DrawablePtr->MaxIndex + 1;
if (FrameOffs < 0)
{
while ((FrameOffs += num_frames) < 0)
;
}
FrameOffs = ((SWORD)FramePtr->Index + FrameOffs) % num_frames;
FramePtr = &DrawablePtr->Frame[FrameOffs];
}
return FramePtr;
}
FRAME
SetEquFrameIndex (FRAME DstFramePtr, FRAME SrcFramePtr)
{
COUNT Index;
if (!DstFramePtr || !SrcFramePtr)
return 0;
Index = GetFrameIndex (SrcFramePtr);
#ifdef DEBUG
{
DRAWABLE_DESC *DrawablePtr = GetFrameParentDrawable (DstFramePtr);
if (Index > DrawablePtr->MaxIndex)
log_add (log_Debug, "SetEquFrameIndex: source index (%d) beyond "
"destination range (%d)", (int)Index,
(int)DrawablePtr->MaxIndex);
}
#endif
return SetAbsFrameIndex (DstFramePtr, Index);
}
FRAME
IncFrameIndex (FRAME FramePtr)
{
DRAWABLE_DESC *DrawablePtr;
if (FramePtr == 0)
return (0);
DrawablePtr = GetFrameParentDrawable (FramePtr);
if (FramePtr->Index < DrawablePtr->MaxIndex)
return ++FramePtr;
else
return DrawablePtr->Frame;
}
FRAME
DecFrameIndex (FRAME FramePtr)
{
if (FramePtr == 0)
return (0);
if (FramePtr->Index > 0)
return --FramePtr;
else
{
DRAWABLE_DESC *DrawablePtr;
DrawablePtr = GetFrameParentDrawable (FramePtr);
return &DrawablePtr->Frame[DrawablePtr->MaxIndex];
}
}

View File

@@ -1,80 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*/
#ifndef _PRIM_H
#define _PRIM_H
enum gfx_object
{
POINT_PRIM = 0,
STAMP_PRIM,
STAMPFILL_PRIM,
LINE_PRIM,
TEXT_PRIM,
RECT_PRIM,
RECTFILL_PRIM,
NUM_PRIMS
};
typedef BYTE GRAPHICS_PRIM;
typedef union
{
POINT Point;
STAMP Stamp;
LINE Line;
TEXT Text;
RECT Rect;
} PRIM_DESC;
typedef DWORD PRIM_LINKS;
typedef struct
{
PRIM_LINKS Links;
GRAPHICS_PRIM Type;
Color color;
PRIM_DESC Object;
} PRIMITIVE;
#define END_OF_LIST ((COUNT)0xFFFF)
#define GetPredLink(l) LOWORD(l)
#define GetSuccLink(l) HIWORD(l)
#define MakeLinks MAKE_DWORD
#define SetPrimLinks(pPrim,p,s) ((pPrim)->Links = MakeLinks (p, s))
#define GetPrimLinks(pPrim) ((pPrim)->Links)
#define SetPrimType(pPrim,t) ((pPrim)->Type = t)
#define GetPrimType(pPrim) ((pPrim)->Type)
#define SetPrimColor(pPrim,c) ((pPrim)->color = c)
#define GetPrimColor(pPrim) ((pPrim)->color)
static inline void
SetPrimNextLink (PRIMITIVE *pPrim, COUNT Link)
{
SetPrimLinks (pPrim, END_OF_LIST, Link);
}
static inline COUNT
GetPrimNextLink (PRIMITIVE *pPrim)
{
return GetSuccLink (GetPrimLinks (pPrim));
}
#endif /* PRIM_H */

View File

@@ -1,54 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "gfxintrn.h"
static void
GetCelFileData (const char *pathname, RESOURCE_DATA *resdata)
{
resdata->ptr = LoadResourceFromPath (pathname, _GetCelData);
}
static void
GetFontFileData (const char *pathname, RESOURCE_DATA *resdata)
{
resdata->ptr = LoadResourceFromPath (pathname, _GetFontData);
}
BOOLEAN
InstallGraphicResTypes (void)
{
InstallResTypeVectors ("GFXRES", GetCelFileData, _ReleaseCelData, NULL);
InstallResTypeVectors ("FONTRES", GetFontFileData, _ReleaseFontData, NULL);
return (TRUE);
}
/* Needs to be void * because it could be either a DRAWABLE or a FONT. */
void *
LoadGraphicInstance (RESOURCE res)
{
void *hData;
hData = res_GetResource (res);
if (hData)
res_DetachResource (res);
return (hData);
}

View File

@@ -1,260 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
// Scaler function lookup table
//
const Scale_FuncDef_t
Scale_C_Functions[] =
{
{TFB_GFXFLAGS_SCALE_BILINEAR, Scale_BilinearFilter},
{TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter},
{TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_BiAdaptAdvFilter},
{TFB_GFXFLAGS_SCALE_TRISCAN, Scale_TriScanFilter},
{TFB_GFXFLAGS_SCALE_HQXX, Scale_HqFilter},
// Default
{0, Scale_Nearest}
};
// See
// nearest2x.c -- Nearest Neighboor scaling
// bilinear2x.c -- Bilinear scaling
// biadv2x.c -- Advanced Biadapt scaling
// triscan2x.c -- Triscan scaling
// Biadapt scaling to 2x
void
SCALE_(BiAdaptFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r)
{
int x, y;
const int w = src->w, h = src->h;
int xend, yend;
int dsrc, ddst;
SDL_Rect *region = r;
SDL_Rect limits;
SDL_PixelFormat *fmt = dst->format;
const int sp = src->pitch, dp = dst->pitch;
const int bpp = fmt->BytesPerPixel;
const int slen = sp / bpp, dlen = dp / bpp;
Uint32 *src_p = (Uint32 *)src->pixels;
Uint32 *dst_p = (Uint32 *)dst->pixels;
Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br;
// these macros are for clarity; they make the current pixel (0,0)
// and allow to access pixels in all directions
#define SRC(x, y) (src_p + (x) + ((y) * slen))
SCALE_(PlatInit) ();
// expand updated region if necessary
// pixels neighbooring the updated region may
// change as a result of updates
limits.x = 0;
limits.y = 0;
limits.w = src->w;
limits.h = src->h;
Scale_ExpandRect (region, 2, &limits);
xend = region->x + region->w;
yend = region->y + region->h;
dsrc = slen - region->w;
ddst = (dlen - region->w) * 2;
// move ptrs to the first updated pixel
src_p += slen * region->y + region->x;
dst_p += (dlen * region->y + region->x) * 2;
for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc)
{
for (x = region->x; x < xend; ++x, ++src_p, ++dst_p)
{
pixval_tl = SCALE_GETPIX (SRC (0, 0));
SCALE_SETPIX (dst_p, pixval_tl);
if (y + 1 < h)
{
// check pixel below the current one
pixval_bl = SCALE_GETPIX (SRC (0, 1));
if (pixval_tl == pixval_bl)
SCALE_SETPIX (dst_p + dlen, pixval_tl);
else
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
pixval_tl, pixval_bl)
);
}
else
{
// last pixel in column - propagate
SCALE_SETPIX (dst_p + dlen, pixval_tl);
pixval_bl = pixval_tl;
}
++dst_p;
if (x + 1 >= w)
{
// last pixel in row - propagate
SCALE_SETPIX (dst_p, pixval_tl);
if (pixval_tl == pixval_bl)
SCALE_SETPIX (dst_p + dlen, pixval_tl);
else
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
pixval_tl, pixval_bl)
);
continue;
}
// check pixel to the right from the current one
pixval_tr = SCALE_GETPIX (SRC (1, 0));
if (pixval_tl == pixval_tr)
SCALE_SETPIX (dst_p, pixval_tr);
else
SCALE_SETPIX (dst_p, Scale_Blend_11 (
pixval_tl, pixval_tr)
);
if (y + 1 >= h)
{
// last pixel in column - propagate
SCALE_SETPIX (dst_p + dlen, pixval_tl);
continue;
}
// check pixel to the bottom-right
pixval_br = SCALE_GETPIX (SRC (1, 1));
if (pixval_tl == pixval_br && pixval_tr == pixval_bl)
{
int cl, cr;
Uint32 clr;
if (pixval_tl == pixval_tr)
{
// all 4 are equal - propagate
SCALE_SETPIX (dst_p + dlen, pixval_tl);
continue;
}
// both pairs are equal, have to resolve the pixel
// race; we try detecting which color is
// the background by looking for a line or an edge
// examine 8 pixels surrounding the current quad
cl = cr = 1;
if (x > 0)
{
clr = SCALE_GETPIX (SRC (-1, 0));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
clr = SCALE_GETPIX (SRC (-1, 1));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
}
if (y > 0)
{
clr = SCALE_GETPIX (SRC (0, -1));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
clr = SCALE_GETPIX (SRC (1, -1));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
}
if (x + 2 < w)
{
clr = SCALE_GETPIX (SRC (2, 0));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
clr = SCALE_GETPIX (SRC (2, 1));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
}
if (y + 2 < h)
{
clr = SCALE_GETPIX (SRC (0, 2));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
clr = SCALE_GETPIX (SRC (1, 2));
if (clr == pixval_tl)
cl++;
else if (clr == pixval_tr)
cr++;
}
// least count wins
if (cl > cr)
SCALE_SETPIX (dst_p + dlen, pixval_tr);
else if (cr > cl)
SCALE_SETPIX (dst_p + dlen, pixval_tl);
else
SCALE_SETPIX (dst_p + dlen,
Scale_Blend_11 (pixval_tl, pixval_tr));
}
else if (pixval_tl == pixval_br)
{
// main diagonal is same color
// use its value
SCALE_SETPIX (dst_p + dlen, pixval_tl);
}
else if (pixval_tr == pixval_bl)
{
// 2nd diagonal is same color
// use its value
SCALE_SETPIX (dst_p + dlen, pixval_tr);
}
else
{
// blend all 4
SCALE_SETPIX (dst_p + dlen, Scale_Blend_1111 (
pixval_tl, pixval_bl, pixval_tr, pixval_br
));
}
}
}
SCALE_(PlatDone) ();
}

View File

@@ -1,30 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _2XSCALERS_H_
#define _2XSCALERS_H_
void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_BiAdaptFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
extern const Scale_FuncDef_t Scale_C_Functions[];
#endif /* _2XSCALERS_H_ */

View File

@@ -1,102 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "libs/platform.h"
#if defined(MMX_ASM)
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
#include "2xscalers_mmx.h"
// 3DNow! name for all functions
#undef SCALE_
#define SCALE_(name) Scale ## _3DNow_ ## name
// Tell them which opcodes we want to support
#undef USE_MOVNTQ
#define USE_PREFETCH AMD_PREFETCH
#undef USE_PSADBW
// Bring in inline asm functions
#include "scalemmx.h"
// Scaler function lookup table
//
const Scale_FuncDef_t
Scale_3DNow_Functions[] =
{
{TFB_GFXFLAGS_SCALE_BILINEAR, Scale_3DNow_BilinearFilter},
{TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter},
{TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_MMX_BiAdaptAdvFilter},
{TFB_GFXFLAGS_SCALE_TRISCAN, Scale_MMX_TriScanFilter},
{TFB_GFXFLAGS_SCALE_HQXX, Scale_MMX_HqFilter},
// Default
{0, Scale_3DNow_Nearest}
};
void
Scale_3DNow_PrepPlatform (const SDL_PixelFormat* fmt)
{
Scale_MMX_PrepPlatform (fmt);
}
// Nearest Neighbor scaling to 2x
// void Scale_3DNow_Nearest (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "nearest2x.c"
// Bilinear scaling to 2x
// void Scale_3DNow_BilinearFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "bilinear2x.c"
#if 0 && NO_IMPROVEMENT
// Advanced Biadapt scaling to 2x
// void Scale_3DNow_BiAdaptAdvFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "biadv2x.c"
// Triscan scaling to 2x
// derivative of scale2x -- scale2x.sf.net
// void Scale_3DNow_TriScanFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "triscan2x.c"
// Hq2x scaling
// (adapted from 'hq2x' by Maxim Stepin -- www.hiend3d.com/hq2x.html)
// void Scale_3DNow_HqFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "hq2x.c"
#endif /* NO_IMPROVEMENT */
#endif /* MMX_ASM */

View File

@@ -1,136 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "libs/platform.h"
#if defined(MMX_ASM)
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
#include "2xscalers_mmx.h"
// MMX name for all functions
#undef SCALE_
#define SCALE_(name) Scale ## _MMX_ ## name
// Tell them which opcodes we want to support
#undef USE_MOVNTQ
#undef USE_PREFETCH
#undef USE_PSADBW
// And Bring in inline asm functions
#include "scalemmx.h"
// Scaler function lookup table
//
const Scale_FuncDef_t
Scale_MMX_Functions[] =
{
{TFB_GFXFLAGS_SCALE_BILINEAR, Scale_MMX_BilinearFilter},
{TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter},
{TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_MMX_BiAdaptAdvFilter},
{TFB_GFXFLAGS_SCALE_TRISCAN, Scale_MMX_TriScanFilter},
{TFB_GFXFLAGS_SCALE_HQXX, Scale_MMX_HqFilter},
// Default
{0, Scale_MMX_Nearest}
};
// MMX transformation multipliers
Uint64 mmx_888to555_mult;
Uint64 mmx_Y_mult;
Uint64 mmx_U_mult;
Uint64 mmx_V_mult;
// Uint64 mmx_YUV_threshold = 0x00300706; original hq2x threshold
//Uint64 mmx_YUV_threshold = 0x0030100e;
Uint64 mmx_YUV_threshold = 0x0040120c;
void
Scale_MMX_PrepPlatform (const SDL_PixelFormat* fmt)
{
// prepare the channel-shuffle multiplier
mmx_888to555_mult = ((Uint64)0x0400) << (fmt->Rshift * 2)
| ((Uint64)0x0020) << (fmt->Gshift * 2)
| ((Uint64)0x0001) << (fmt->Bshift * 2);
// prepare the RGB->YUV multipliers
mmx_Y_mult = ((Uint64)(uint16)YUV_matrix[YUV_XFORM_R][YUV_XFORM_Y])
<< (fmt->Rshift * 2)
| ((Uint64)(uint16)YUV_matrix[YUV_XFORM_G][YUV_XFORM_Y])
<< (fmt->Gshift * 2)
| ((Uint64)(uint16)YUV_matrix[YUV_XFORM_B][YUV_XFORM_Y])
<< (fmt->Bshift * 2);
mmx_U_mult = ((Uint64)(uint16)YUV_matrix[YUV_XFORM_R][YUV_XFORM_U])
<< (fmt->Rshift * 2)
| ((Uint64)(uint16)YUV_matrix[YUV_XFORM_G][YUV_XFORM_U])
<< (fmt->Gshift * 2)
| ((Uint64)(uint16)YUV_matrix[YUV_XFORM_B][YUV_XFORM_U])
<< (fmt->Bshift * 2);
mmx_V_mult = ((Uint64)(uint16)YUV_matrix[YUV_XFORM_R][YUV_XFORM_V])
<< (fmt->Rshift * 2)
| ((Uint64)(uint16)YUV_matrix[YUV_XFORM_G][YUV_XFORM_V])
<< (fmt->Gshift * 2)
| ((Uint64)(uint16)YUV_matrix[YUV_XFORM_B][YUV_XFORM_V])
<< (fmt->Bshift * 2);
mmx_YUV_threshold = (SCALE_DIFFYUV_TY << 16) | (SCALE_DIFFYUV_TU << 8)
| SCALE_DIFFYUV_TV;
}
// Nearest Neighbor scaling to 2x
// void Scale_MMX_Nearest (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "nearest2x.c"
// Bilinear scaling to 2x
// void Scale_MMX_BilinearFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "bilinear2x.c"
// Advanced Biadapt scaling to 2x
// void Scale_MMX_BiAdaptAdvFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "biadv2x.c"
// Triscan scaling to 2x
// derivative of 'scale2x' -- scale2x.sf.net
// void Scale_MMX_TriScanFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "triscan2x.c"
// Hq2x scaling
// (adapted from 'hq2x' by Maxim Stepin -- www.hiend3d.com/hq2x.html)
// void Scale_MMX_HqFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "hq2x.c"
#endif /* MMX_ASM */

View File

@@ -1,56 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _2XSCALERS_MMX_H_
#define _2XSCALERS_MMX_H_
// MMX versions
void Scale_MMX_PrepPlatform (const SDL_PixelFormat* fmt);
void Scale_MMX_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_MMX_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_MMX_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_MMX_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_MMX_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
extern const Scale_FuncDef_t Scale_MMX_Functions[];
// SSE (Intel)/MMX Ext (Athlon) versions
void Scale_SSE_PrepPlatform (const SDL_PixelFormat* fmt);
void Scale_SSE_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_SSE_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_SSE_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_SSE_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_SSE_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
extern const Scale_FuncDef_t Scale_SSE_Functions[];
// 3DNow (AMD K6/Athlon) versions
void Scale_3DNow_PrepPlatform (const SDL_PixelFormat* fmt);
void Scale_3DNow_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_3DNow_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_3DNow_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_3DNow_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
void Scale_3DNow_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r);
extern const Scale_FuncDef_t Scale_3DNow_Functions[];
#endif /* _2XSCALERS_MMX_H_ */

View File

@@ -1,100 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "libs/platform.h"
#if defined(MMX_ASM)
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
#include "2xscalers_mmx.h"
// SSE name for all functions
#undef SCALE_
#define SCALE_(name) Scale ## _SSE_ ## name
// Tell them which opcodes we want to support
#define USE_MOVNTQ
#define USE_PREFETCH INTEL_PREFETCH
#define USE_PSADBW
// Bring in inline asm functions
#include "scalemmx.h"
// Scaler function lookup table
//
const Scale_FuncDef_t
Scale_SSE_Functions[] =
{
{TFB_GFXFLAGS_SCALE_BILINEAR, Scale_SSE_BilinearFilter},
{TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter},
{TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_SSE_BiAdaptAdvFilter},
{TFB_GFXFLAGS_SCALE_TRISCAN, Scale_SSE_TriScanFilter},
{TFB_GFXFLAGS_SCALE_HQXX, Scale_MMX_HqFilter},
// Default
{0, Scale_SSE_Nearest}
};
void
Scale_SSE_PrepPlatform (const SDL_PixelFormat* fmt)
{
Scale_MMX_PrepPlatform (fmt);
}
// Nearest Neighbor scaling to 2x
// void Scale_SSE_Nearest (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "nearest2x.c"
// Bilinear scaling to 2x
// void Scale_SSE_BilinearFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "bilinear2x.c"
// Advanced Biadapt scaling to 2x
// void Scale_SSE_BiAdaptAdvFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "biadv2x.c"
// Triscan scaling to 2x
// derivative of scale2x -- scale2x.sf.net
// void Scale_SSE_TriScanFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "triscan2x.c"
#if 0 && NO_IMPROVEMENT
// Hq2x scaling
// (adapted from 'hq2x' by Maxim Stepin -- www.hiend3d.com/hq2x.html)
// void Scale_SSE_HqFilter (SDL_Surface *src,
// SDL_Surface *dst, SDL_Rect *r)
#include "hq2x.c"
#endif
#endif /* MMX_ASM */

View File

@@ -1,5 +0,0 @@
uqm_CFILES="opengl.c palette.c primitives.c pure.c sdl_common.c
scalers.c 2xscalers.c
2xscalers_mmx.c 2xscalers_sse.c 2xscalers_3dnow.c
nearest2x.c bilinear2x.c biadv2x.c triscan2x.c hq2x.c
canvas.c sdluio.c rotozoom.c"

View File

@@ -1,532 +0,0 @@
/*
* Portions Copyright (C) 2003-2005 Alex Volkov (codepro@usa.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Core algorithm of the Advanced BiAdaptive screen scaler
// Template
// When this file is built standalone is produces a plain C version
// Also #included by 2xscalers_mmx.c for an MMX version
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
// Advanced biadapt scaling to 2x
// The name expands to either
// Scale_BiAdaptAdvFilter (for plain C) or
// Scale_MMX_BiAdaptAdvFilter (for MMX)
// [others when platforms are added]
void
SCALE_(BiAdaptAdvFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r)
{
int x, y;
const int w = src->w, h = src->h;
int xend, yend;
int dsrc, ddst;
SDL_Rect *region = r;
SDL_Rect limits;
SDL_PixelFormat *fmt = dst->format;
const int sp = src->pitch, dp = dst->pitch;
const int bpp = fmt->BytesPerPixel;
const int slen = sp / bpp, dlen = dp / bpp;
// for clarity purposes, the 'pixels' array here is transposed
Uint32 pixels[4][4];
static int resolve_coord[][2] =
{
{0, -1}, {1, -1}, { 2, 0}, { 2, 1},
{1, 2}, {0, 2}, {-1, 1}, {-1, 0},
{100, 100} // term
};
Uint32 *src_p = (Uint32 *)src->pixels;
Uint32 *dst_p = (Uint32 *)dst->pixels;
// these macros are for clarity; they make the current pixel (0,0)
// and allow to access pixels in all directions
#define PIX(x, y) (pixels[1 + (x)][1 + (y)])
#define SRC(x, y) (src_p + (x) + ((y) * slen))
// commonly used operations, for clarity also
// others are defined at their respective bpp levels
#define BIADAPT_RGBHIGH 8000
#define BIADAPT_YUVLOW 30
#define BIADAPT_YUVMED 70
#define BIADAPT_YUVHIGH 130
// high tolerance pixel comparison
#define BIADAPT_CMPRGB_HIGH(p1, p2) \
(p1 == p2 || SCALE_CMPRGB (p1, p2) <= BIADAPT_RGBHIGH)
// low tolerance pixel comparison
#define BIADAPT_CMPYUV_LOW(p1, p2) \
(p1 == p2 || SCALE_CMPYUV (p1, p2, BIADAPT_YUVLOW))
// medium tolerance pixel comparison
#define BIADAPT_CMPYUV_MED(p1, p2) \
(p1 == p2 || SCALE_CMPYUV (p1, p2, BIADAPT_YUVMED))
// high tolerance pixel comparison
#define BIADAPT_CMPYUV_HIGH(p1, p2) \
(p1 == p2 || SCALE_CMPYUV (p1, p2, BIADAPT_YUVHIGH))
SCALE_(PlatInit) ();
// expand updated region if necessary
// pixels neighbooring the updated region may
// change as a result of updates
limits.x = 0;
limits.y = 0;
limits.w = src->w;
limits.h = src->h;
Scale_ExpandRect (region, 2, &limits);
xend = region->x + region->w;
yend = region->y + region->h;
dsrc = slen - region->w;
ddst = (dlen - region->w) * 2;
#define SCALE_GETPIX(p) ( *(Uint32 *)(p) )
#define SCALE_SETPIX(p, c) ( *(Uint32 *)(p) = (c) )
// move ptrs to the first updated pixel
src_p += slen * region->y + region->x;
dst_p += (dlen * region->y + region->x) * 2;
for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc)
{
for (x = region->x; x < xend; ++x, ++src_p, ++dst_p)
{
// pixel equality counter
int cmatch;
// most pixels will fall into 'all 4 equal'
// pattern, so we check it first
cmatch = 0;
PIX (0, 0) = SCALE_GETPIX (SRC (0, 0));
SCALE_SETPIX (dst_p, PIX (0, 0));
if (y + 1 < h)
{
// check pixel below the current one
PIX (0, 1) = SCALE_GETPIX (SRC (0, 1));
if (PIX (0, 0) == PIX (0, 1))
{
SCALE_SETPIX (dst_p + dlen, PIX (0, 0));
cmatch |= 1;
}
}
else
{
// last pixel in column - propagate
PIX (0, 1) = PIX (0, 0);
SCALE_SETPIX (dst_p + dlen, PIX (0, 0));
cmatch |= 1;
}
if (x + 1 < w)
{
// check pixel to the right from the current one
PIX (1, 0) = SCALE_GETPIX (SRC (1, 0));
if (PIX (0, 0) == PIX (1, 0))
{
SCALE_SETPIX (dst_p + 1, PIX (0, 0));
cmatch |= 2;
}
}
else
{
// last pixel in row - propagate
PIX (1, 0) = PIX (0, 0);
SCALE_SETPIX (dst_p + 1, PIX (0, 0));
cmatch |= 2;
}
if (cmatch == 3)
{
if (y + 1 >= h || x + 1 >= w)
{
// last pixel in row/column and nearest
// neighboor is identical
dst_p++;
SCALE_SETPIX (dst_p + dlen, PIX (0, 0));
continue;
}
// check pixel to the bottom-right
PIX (1, 1) = SCALE_GETPIX (SRC (1, 1));
if (PIX (0, 0) == PIX (1, 1))
{
// all 4 are equal - propagate
dst_p++;
SCALE_SETPIX (dst_p + dlen, PIX (0, 0));
continue;
}
}
// some neighboors are different, lets check them
if (x > 0)
PIX (-1, 0) = SCALE_GETPIX (SRC (-1, 0));
else
PIX (-1, 0) = PIX (0, 0);
if (x + 2 < w)
PIX (2, 0) = SCALE_GETPIX (SRC (2, 0));
else
PIX (2, 0) = PIX (1, 0);
if (y + 1 < h)
{
if (x > 0)
PIX (-1, 1) = SCALE_GETPIX (SRC (-1, 1));
else
PIX (-1, 1) = PIX (0, 1);
if (x + 2 < w)
{
PIX (1, 1) = SCALE_GETPIX (SRC (1, 1));
PIX (2, 1) = SCALE_GETPIX (SRC (2, 1));
}
else if (x + 1 < w)
{
PIX (1, 1) = SCALE_GETPIX (SRC (1, 1));
PIX (2, 1) = PIX (1, 1);
}
else
{
PIX (1, 1) = PIX (0, 1);
PIX (2, 1) = PIX (0, 1);
}
}
else
{
// last pixel in column
PIX (-1, 1) = PIX (-1, 0);
PIX (1, 1) = PIX (1, 0);
PIX (2, 1) = PIX (2, 0);
}
if (y + 2 < h)
{
PIX (0, 2) = SCALE_GETPIX (SRC (0, 2));
if (x > 0)
PIX (-1, 2) = SCALE_GETPIX (SRC (-1, 2));
else
PIX (-1, 2) = PIX (0, 2);
if (x + 2 < w)
{
PIX (1, 2) = SCALE_GETPIX (SRC (1, 2));
PIX (2, 2) = SCALE_GETPIX (SRC (2, 2));
}
else if (x + 1 < w)
{
PIX (1, 2) = SCALE_GETPIX (SRC (1, 2));
PIX (2, 2) = PIX (1, 2);
}
else
{
PIX (1, 2) = PIX (0, 2);
PIX (2, 2) = PIX (0, 2);
}
}
else
{
// last pixel in column
PIX (-1, 2) = PIX (-1, 1);
PIX (0, 2) = PIX (0, 1);
PIX (1, 2) = PIX (1, 1);
PIX (2, 2) = PIX (2, 1);
}
if (y > 0)
{
PIX (0, -1) = SCALE_GETPIX (SRC (0, -1));
if (x > 0)
PIX (-1, -1) = SCALE_GETPIX (SRC (-1, -1));
else
PIX (-1, -1) = PIX (0, -1);
if (x + 2 < w)
{
PIX (1, -1) = SCALE_GETPIX (SRC (1, -1));
PIX (2, -1) = SCALE_GETPIX (SRC (2, -1));
}
else if (x + 1 < w)
{
PIX (1, -1) = SCALE_GETPIX (SRC (1, -1));
PIX (2, -1) = PIX (1, -1);
}
else
{
PIX (1, -1) = PIX (0, -1);
PIX (2, -1) = PIX (0, -1);
}
}
else
{
PIX (-1, -1) = PIX (-1, 0);
PIX (0, -1) = PIX (0, 0);
PIX (1, -1) = PIX (1, 0);
PIX (2, -1) = PIX (2, 0);
}
// check pixel below the current one
if (!(cmatch & 1))
{
if (SCALE_CMPYUV (PIX (0, 0), PIX (0, 1), BIADAPT_YUVLOW))
{
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (0, 0), PIX (0, 1))
);
cmatch |= 1;
}
// detect a 2:1 line going across the current pixel
else if ( (PIX (0, 0) == PIX (-1, 0)
&& PIX (0, 0) == PIX (1, 1)
&& PIX (0, 0) == PIX (2, 1) &&
((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ||
(PIX (0, 0) == PIX (1, 0)
&& PIX (0, 0) == PIX (-1, 1)
&& PIX (0, 0) == PIX (2, -1) &&
((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) )
{
SCALE_SETPIX (dst_p + dlen, PIX (0, 0));
}
// detect a 2:1 line going across the pixel below current
else if ( (PIX (0, 1) == PIX (-1, 0)
&& PIX (0, 1) == PIX (1, 1)
&& PIX (0, 1) == PIX (2, 2) &&
((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) ||
(PIX (0, 1) == PIX (1, 0)
&& PIX (0, 1) == PIX (-1, 1)
&& PIX (0, 1) == PIX (2, 0) &&
((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) )
{
SCALE_SETPIX (dst_p + dlen, PIX (0, 1));
}
else
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (0, 0), PIX (0, 1))
);
}
dst_p++;
// check pixel to the right from the current one
if (!(cmatch & 2))
{
if (SCALE_CMPYUV (PIX (0, 0), PIX (1, 0), BIADAPT_YUVLOW))
{
SCALE_SETPIX (dst_p, Scale_Blend_11 (
PIX (0, 0), PIX (1, 0))
);
cmatch |= 2;
}
// detect a 1:2 line going across the current pixel
else if ( (PIX (0, 0) == PIX (1, -1)
&& PIX (0, 0) == PIX (0, 1)
&& PIX (0, 0) == PIX (-1, 2) &&
((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) ||
(PIX (0, 0) == PIX (0, -1)
&& PIX (0, 0) == PIX (1, 1)
&& PIX (0, 0) == PIX (1, 2) &&
((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) )
{
SCALE_SETPIX (dst_p, PIX (0, 0));
}
// detect a 1:2 line going across the pixel to the right
else if ( (PIX (1, 0) == PIX (1, -1)
&& PIX (1, 0) == PIX (0, 1)
&& PIX (1, 0) == PIX (0, 2) &&
((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) ||
(PIX (1, 0) == PIX (0, -1)
&& PIX (1, 0) == PIX (1, 1)
&& PIX (1, 0) == PIX (2, 2) &&
((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) ||
(!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0))
&& !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) )
{
SCALE_SETPIX (dst_p, PIX (1, 0));
}
else
SCALE_SETPIX (dst_p, Scale_Blend_11 (
PIX (0, 0), PIX (1, 0))
);
}
if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1))
{
// diagonals are equal
int *coord;
int cl, cr;
Uint32 clr;
// both pairs are equal, have to resolve the pixel
// race; we try detecting which color is
// the background by looking for a line or an edge
// examine 8 pixels surrounding the current quad
cl = cr = 2;
for (coord = resolve_coord[0]; *coord < 100; coord += 2)
{
clr = PIX (coord[0], coord[1]);
if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0)))
cl++;
else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0)))
cr++;
}
// least count wins
if (cl > cr)
clr = PIX (1, 0);
else if (cr > cl)
clr = PIX (0, 0);
else
clr = Scale_Blend_11 (PIX (0, 0), PIX (1, 0));
SCALE_SETPIX (dst_p + dlen, clr);
continue;
}
if (cmatch == 3
|| (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1))
&& BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1))))
{
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (0, 1), PIX (1, 0))
);
continue;
}
else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1)))
{
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (0, 0), PIX (1, 1))
);
continue;
}
// check pixel to the bottom-right
if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))
&& BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1)))
{
if (SCALE_GETY (PIX (0, 0)) > SCALE_GETY (PIX (1, 0)))
{
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (0, 0), PIX (1, 1))
);
}
else
{
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (1, 0), PIX (0, 1))
);
}
}
else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)))
{
// main diagonal is same color
// use its value
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (0, 0), PIX (1, 1))
);
}
else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1)))
{
// 2nd diagonal is same color
// use its value
SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (
PIX (1, 0), PIX (0, 1))
);
}
else
{
// blend all 4
SCALE_SETPIX (dst_p + dlen, Scale_Blend_1111 (
PIX (0, 0), PIX (0, 1),
PIX (1, 0), PIX (1, 1)
));
}
}
}
SCALE_(PlatDone) ();
}

View File

@@ -1,112 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Core algorithm of the BiLinear screen scaler
// Template
// When this file is built standalone is produces a plain C version
// Also #included by 2xscalers_mmx.c for an MMX version
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
// Bilinear scaling to 2x
// The name expands to either
// Scale_BilinearFilter (for plain C) or
// Scale_MMX_BilinearFilter (for MMX)
// Scale_SSE_BilinearFilter (for SSE)
// [others when platforms are added]
void
SCALE_(BilinearFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r)
{
int x, y;
const int w = src->w, h = src->h;
int xend, yend;
int dsrc, ddst;
SDL_Rect *region = r;
SDL_Rect limits;
SDL_PixelFormat *fmt = dst->format;
const int pitch = src->pitch, dp = dst->pitch;
const int bpp = fmt->BytesPerPixel;
const int len = pitch / bpp, dlen = dp / bpp;
Uint32 p[4]; // influential pixels array
Uint32 *srow0 = (Uint32 *) src->pixels;
Uint32 *dst_p = (Uint32 *) dst->pixels;
SCALE_(PlatInit) ();
// expand updated region if necessary
// pixels neighbooring the updated region may
// change as a result of updates
limits.x = 0;
limits.y = 0;
limits.w = w;
limits.h = h;
Scale_ExpandRect (region, 1, &limits);
xend = region->x + region->w;
yend = region->y + region->h;
dsrc = len - region->w;
ddst = (dlen - region->w) * 2;
// move ptrs to the first updated pixel
srow0 += len * region->y + region->x;
dst_p += (dlen * region->y + region->x) * 2;
for (y = region->y; y < yend; ++y, dst_p += ddst, srow0 += dsrc)
{
Uint32 *srow1;
SCALE_(Prefetch) (srow0 + 16);
SCALE_(Prefetch) (srow0 + 32);
if (y < h - 1)
srow1 = srow0 + len;
else
srow1 = srow0;
SCALE_(Prefetch) (srow1 + 16);
SCALE_(Prefetch) (srow1 + 32);
for (x = region->x; x < xend; ++x, ++srow0, ++srow1, dst_p += 2)
{
if (x < w - 1)
{ // can blend directly from pixels
SCALE_BILINEAR_BLEND4 (srow0, srow1, dst_p, dlen);
}
else
{ // need to make temp pixel rows
p[0] = srow0[0];
p[1] = p[0];
p[2] = srow1[0];
p[3] = p[2];
SCALE_BILINEAR_BLEND4 (&p[0], &p[2], dst_p, dlen);
}
}
SCALE_(Prefetch) (srow0 + dsrc);
SCALE_(Prefetch) (srow0 + dsrc + 16);
SCALE_(Prefetch) (srow1 + dsrc);
SCALE_(Prefetch) (srow1 + dsrc + 16);
}
SCALE_(PlatDone) ();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,207 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Core algorithm of the BiLinear screen scaler
// Template
// When this file is built standalone is produces a plain C version
// Also #included by 2xscalers_mmx.c for an MMX version
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
// Nearest Neighbor scaling to 2x
// The name expands to
// Scale_Nearest (for plain C)
// Scale_MMX_Nearest (for MMX)
// Scale_SSE_Nearest (for SSE)
// [others when platforms are added]
void
SCALE_(Nearest) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r)
{
int y;
const int rw = r->w, rh = r->h;
const int sp = src->pitch, dp = dst->pitch;
const int bpp = dst->format->BytesPerPixel;
const int slen = sp / bpp, dlen = dp / bpp;
const int dsrc = slen-rw, ddst = (dlen-rw) * 2;
Uint32 *src_p = (Uint32 *)src->pixels;
Uint32 *dst_p = (Uint32 *)dst->pixels;
// guard asm code against such atrocities
if (rw == 0 || rh == 0)
return;
SCALE_(PlatInit) ();
// move ptrs to the first updated pixel
src_p += slen * r->y + r->x;
dst_p += (dlen * r->y + r->x) * 2;
#if defined(MMX_ASM) && defined(MSVC_ASM)
// Just about everything has to be done in asm for MSVC
// to actually take advantage of asm here
// MSVC does not support beautiful GCC-like asm templates
y = rh;
__asm
{
// setup vars
mov esi, src_p
mov edi, dst_p
PREFETCH (esi + 0x40)
PREFETCH (esi + 0x80)
PREFETCH (esi + 0xc0)
mov edx, dlen
lea edx, [edx * 4]
mov eax, dsrc
lea eax, [eax * 4]
mov ebx, ddst
lea ebx, [ebx * 4]
mov ecx, rw
loop_y:
test ecx, 1
jz even_x
// one-pixel transfer
movd mm1, [esi]
punpckldq mm1, mm1 // pix1 | pix1 -> mm1
add esi, 4
MOVNTQ (edi, mm1)
add edi, 8
MOVNTQ (edi - 8 + edx, mm1)
even_x:
shr ecx, 1 // x = rw / 2
jz end_x // rw was 1
loop_x:
// two-pixel transfer
movq mm1, [esi]
movq mm2, mm1
PREFETCH (esi + 0x100)
punpckldq mm1, mm1 // pix1 | pix1 -> mm1
add esi, 8
MOVNTQ (edi, mm1)
punpckhdq mm2, mm2 // pix2 | pix2 -> mm2
MOVNTQ (edi + edx, mm1)
add edi, 16
MOVNTQ (edi - 8, mm2)
MOVNTQ (edi - 8 + edx, mm2)
dec ecx
jnz loop_x
end_x:
// try to prefetch as early as possible to have it on time
PREFETCH (esi + eax)
mov ecx, rw
add esi, eax
PREFETCH (esi + 0x40)
PREFETCH (esi + 0x80)
PREFETCH (esi + 0xc0)
add edi, ebx
dec y
jnz loop_y
}
#elif defined(MMX_ASM) && defined(GCC_ASM)
SCALE_(Prefetch) (src_p + 16);
SCALE_(Prefetch) (src_p + 32);
SCALE_(Prefetch) (src_p + 48);
for (y = rh; y; --y)
{
int x = rw;
if (x & 1)
{ // one-pixel transfer
__asm__ (
"movd (%0), %%mm1 \n\t"
"punpckldq %%mm1, %%mm1 \n\t"
MOVNTQ (%%mm1, (%1)) "\n\t"
MOVNTQ (%%mm1, (%1,%2)) "\n\t"
: /* nothing */
: /*0*/"r" (src_p), /*1*/"r" (dst_p), /*2*/"r" (dlen*sizeof(Uint32))
);
++src_p;
dst_p += 2;
--x;
}
for (x >>= 1; x; --x, src_p += 2, dst_p += 4)
{ // two-pixel transfer
__asm__ (
"movq (%0), %%mm1 \n\t"
"movq %%mm1, %%mm2 \n\t"
PREFETCH (0x100(%0)) "\n\t"
"punpckldq %%mm1, %%mm1 \n\t"
MOVNTQ (%%mm1, (%1)) "\n\t"
MOVNTQ (%%mm1, (%1,%2)) "\n\t"
"punpckhdq %%mm2, %%mm2 \n\t"
MOVNTQ (%%mm2, 8(%1)) "\n\t"
MOVNTQ (%%mm2, 8(%1,%2)) "\n\t"
: /* nothing */
: /*0*/"r" (src_p), /*1*/"r" (dst_p), /*2*/"r" (dlen*sizeof(Uint32))
);
}
src_p += dsrc;
// try to prefetch as early as possible to have it on time
SCALE_(Prefetch) (src_p);
dst_p += ddst;
SCALE_(Prefetch) (src_p + 16);
SCALE_(Prefetch) (src_p + 32);
SCALE_(Prefetch) (src_p + 48);
}
#else
// Plain C version
for (y = 0; y < rh; ++y)
{
int x;
for (x = 0; x < rw; ++x, ++src_p, dst_p += 2)
{
Uint32 pix = *src_p;
dst_p[0] = pix;
dst_p[1] = pix;
dst_p[dlen] = pix;
dst_p[dlen + 1] = pix;
}
dst_p += ddst;
src_p += dsrc;
}
#endif
SCALE_(PlatDone) ();
}

View File

@@ -1,581 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifdef HAVE_OPENGL
#include "libs/graphics/sdl/opengl.h"
#include "libs/graphics/bbox.h"
#include "scalers.h"
#include "options.h"
#include "libs/log.h"
typedef struct _gl_screeninfo {
SDL_Surface *scaled;
GLuint texture;
BOOLEAN dirty, active;
SDL_Rect updated;
} TFB_GL_SCREENINFO;
static TFB_GL_SCREENINFO GL_Screens[TFB_GFX_NUMSCREENS];
static int ScreenFilterMode;
static TFB_ScaleFunc scaler = NULL;
static BOOLEAN first_init = TRUE;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define R_MASK 0xff000000
#define G_MASK 0x00ff0000
#define B_MASK 0x0000ff00
#define A_MASK 0x000000ff
#else
#define R_MASK 0x000000ff
#define G_MASK 0x0000ff00
#define B_MASK 0x00ff0000
#define A_MASK 0xff000000
#endif
static void TFB_GL_Preprocess (int force_full_redraw, int transition_amount, int fade_amount);
static void TFB_GL_Postprocess (void);
static void TFB_GL_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect);
static void TFB_GL_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect);
static void TFB_GL_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect);
static TFB_GRAPHICS_BACKEND opengl_scaled_backend = {
TFB_GL_Preprocess,
TFB_GL_Postprocess,
TFB_GL_Scaled_ScreenLayer,
TFB_GL_ColorLayer };
static TFB_GRAPHICS_BACKEND opengl_unscaled_backend = {
TFB_GL_Preprocess,
TFB_GL_Postprocess,
TFB_GL_Unscaled_ScreenLayer,
TFB_GL_ColorLayer };
static SDL_Surface *
Create_Screen (SDL_Surface *template, int w, int h)
{
SDL_Surface *newsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
template->format->BitsPerPixel,
template->format->Rmask, template->format->Gmask,
template->format->Bmask, 0);
if (newsurf == 0) {
log_add (log_Error, "Couldn't create screen buffers: %s",
SDL_GetError());
}
return newsurf;
}
static int
ReInit_Screen (SDL_Surface **screen, SDL_Surface *template, int w, int h)
{
if (*screen)
SDL_FreeSurface (*screen);
*screen = Create_Screen (template, w, h);
return *screen == 0 ? -1 : 0;
}
static int
AttemptColorDepth (int flags, int width, int height, int bpp)
{
int videomode_flags;
ScreenColorDepth = bpp;
ScreenWidthActual = width;
ScreenHeightActual = height;
switch (bpp) {
case 15:
SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
break;
case 16:
SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
break;
case 24:
SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
break;
case 32:
SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
break;
default:
break;
}
SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
videomode_flags = SDL_OPENGL;
if (flags & TFB_GFXFLAGS_FULLSCREEN)
videomode_flags |= SDL_FULLSCREEN;
videomode_flags |= SDL_ANYFORMAT;
SDL_Video = SDL_SetVideoMode (ScreenWidthActual, ScreenHeightActual,
bpp, videomode_flags);
if (SDL_Video == NULL)
{
log_add (log_Error, "Couldn't set OpenGL %ix%ix%i video mode: %s",
ScreenWidthActual, ScreenHeightActual, bpp,
SDL_GetError ());
return -1;
}
else
{
log_add (log_Info, "Set the resolution to: %ix%ix%i"
" (surface reports %ix%ix%i)",
width, height, bpp,
SDL_GetVideoSurface()->w, SDL_GetVideoSurface()->h,
SDL_GetVideoSurface()->format->BitsPerPixel);
log_add (log_Info, "OpenGL renderer: %s version: %s",
glGetString (GL_RENDERER), glGetString (GL_VERSION));
}
return 0;
}
int
TFB_GL_ConfigureVideo (int driver, int flags, int width, int height, int togglefullscreen)
{
int i, texture_width, texture_height;
GraphicsDriver = driver;
if (AttemptColorDepth (flags, width, height, 32) &&
AttemptColorDepth (flags, width, height, 24) &&
AttemptColorDepth (flags, width, height, 16))
{
log_add (log_Error, "Couldn't set any OpenGL %ix%i video mode!",
width, height);
return -1;
}
if (!togglefullscreen)
{
if (format_conv_surf)
SDL_FreeSurface (format_conv_surf);
format_conv_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, 0, 0, 32,
R_MASK, G_MASK, B_MASK, A_MASK);
if (format_conv_surf == NULL)
{
log_add (log_Error, "Couldn't create format_conv_surf: %s",
SDL_GetError());
return -1;
}
for (i = 0; i < TFB_GFX_NUMSCREENS; i++)
{
if (0 != ReInit_Screen (&SDL_Screens[i], format_conv_surf,
ScreenWidth, ScreenHeight))
return -1;
}
SDL_Screen = SDL_Screens[0];
TransitionScreen = SDL_Screens[2];
if (first_init)
{
for (i = 0; i < TFB_GFX_NUMSCREENS; i++)
{
GL_Screens[i].scaled = NULL;
GL_Screens[i].dirty = TRUE;
GL_Screens[i].active = TRUE;
}
GL_Screens[1].active = FALSE;
first_init = FALSE;
}
}
if (GfxFlags & TFB_GFXFLAGS_SCALE_SOFT_ONLY)
{
if (!togglefullscreen)
{
for (i = 0; i < TFB_GFX_NUMSCREENS; i++)
{
if (!GL_Screens[i].active)
continue;
if (0 != ReInit_Screen (&GL_Screens[i].scaled, format_conv_surf,
ScreenWidth * 2, ScreenHeight * 2))
return -1;
}
scaler = Scale_PrepPlatform (flags, SDL_Screen->format);
}
texture_width = 1024;
texture_height = 512;
graphics_backend = &opengl_scaled_backend;
}
else
{
texture_width = 512;
texture_height = 256;
scaler = NULL;
graphics_backend = &opengl_unscaled_backend;
}
if (GfxFlags & TFB_GFXFLAGS_SCALE_ANY)
ScreenFilterMode = GL_LINEAR;
else
ScreenFilterMode = GL_NEAREST;
glViewport (0, 0, ScreenWidthActual, ScreenHeightActual);
glClearColor (0,0,0,0);
glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
SDL_GL_SwapBuffers ();
glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDisable (GL_DITHER);
glDepthMask(GL_FALSE);
for (i = 0; i < TFB_GFX_NUMSCREENS; i++)
{
if (!GL_Screens[i].active)
continue;
glGenTextures (1, &GL_Screens[i].texture);
glBindTexture (GL_TEXTURE_2D, GL_Screens[i].texture);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
return 0;
}
int
TFB_GL_InitGraphics (int driver, int flags, int width, int height)
{
char VideoName[256];
log_add (log_Info, "Initializing SDL with OpenGL support.");
SDL_VideoDriverName (VideoName, sizeof (VideoName));
log_add (log_Info, "SDL driver used: %s", VideoName);
log_add (log_Info, "SDL initialized.");
log_add (log_Info, "Initializing Screen.");
ScreenWidth = 320;
ScreenHeight = 240;
if (TFB_GL_ConfigureVideo (driver, flags, width, height, 0))
{
log_add (log_Fatal, "Could not initialize video: "
"no fallback at start of program!");
exit (EXIT_FAILURE);
}
// Initialize scalers (let them precompute whatever)
Scale_Init ();
return 0;
}
void TFB_GL_UploadTransitionScreen (void)
{
GL_Screens[TFB_SCREEN_TRANSITION].updated.x = 0;
GL_Screens[TFB_SCREEN_TRANSITION].updated.y = 0;
GL_Screens[TFB_SCREEN_TRANSITION].updated.w = ScreenWidth;
GL_Screens[TFB_SCREEN_TRANSITION].updated.h = ScreenHeight;
GL_Screens[TFB_SCREEN_TRANSITION].dirty = TRUE;
}
void
TFB_GL_ScanLines (void)
{
int y;
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
glBlendFunc (GL_DST_COLOR, GL_ZERO);
glColor3f (0.85f, 0.85f, 0.85f);
for (y = 0; y < ScreenHeightActual; y += 2)
{
glBegin (GL_LINES);
glVertex2i (0, y);
glVertex2i (ScreenWidthActual, y);
glEnd ();
}
glBlendFunc (GL_DST_COLOR, GL_ONE);
glColor3f (0.2f, 0.2f, 0.2f);
for (y = 1; y < ScreenHeightActual; y += 2)
{
glBegin (GL_LINES);
glVertex2i (0, y);
glVertex2i (ScreenWidthActual, y);
glEnd ();
}
}
static void
TFB_GL_DrawQuad (SDL_Rect *r)
{
BOOLEAN keep_aspect_ratio = optKeepAspectRatio;
int x1 = 0, y1 = 0, x2 = ScreenWidthActual, y2 = ScreenHeightActual;
int sx = 0, sy = 0;
int sw, sh;
float sx_multiplier = 1;
float sy_multiplier = 1;
if (keep_aspect_ratio)
{
float threshold = 0.75f;
float ratio = ScreenHeightActual / (float)ScreenWidthActual;
if (ratio > threshold)
{
// screen is narrower than 4:3
int height = (int)(ScreenWidthActual * threshold);
y1 = (ScreenHeightActual - height) / 2;
y2 = ScreenHeightActual - y1;
if (r != NULL)
{
sx_multiplier = ScreenWidthActual / (float)ScreenWidth;
sy_multiplier = height / (float)ScreenHeight;
sx = (int)(r->x * sx_multiplier);
sy = (int)(((ScreenHeight - (r->y + r->h)) * sy_multiplier) + y1);
}
}
else if (ratio < threshold)
{
// screen is wider than 4:3
int width = (int)(ScreenHeightActual / threshold);
x1 = (ScreenWidthActual - width) / 2;
x2 = ScreenWidthActual - x1;
if (r != NULL)
{
sx_multiplier = width / (float)ScreenWidth;
sy_multiplier = ScreenHeightActual / (float)ScreenHeight;
sx = (int)((r->x * sx_multiplier) + x1);
sy = (int)((ScreenHeight - (r->y + r->h)) * sy_multiplier);
}
}
else
{
// screen is 4:3
keep_aspect_ratio = 0;
}
}
if (r != NULL)
{
if (!keep_aspect_ratio)
{
sx_multiplier = ScreenWidthActual / (float)ScreenWidth;
sy_multiplier = ScreenHeightActual / (float)ScreenHeight;
sx = (int)(r->x * sx_multiplier);
sy = (int)((ScreenHeight - (r->y + r->h)) * sy_multiplier);
}
sw = (int)(r->w * sx_multiplier);
sh = (int)(r->h * sy_multiplier);
glScissor (sx, sy, sw, sh);
glEnable (GL_SCISSOR_TEST);
}
glBegin (GL_TRIANGLE_FAN);
glTexCoord2f (0, 0);
glVertex2i (x1, y1);
glTexCoord2f (ScreenWidth / 512.0f, 0);
glVertex2i (x2, y1);
glTexCoord2f (ScreenWidth / 512.0f, ScreenHeight / 256.0f);
glVertex2i (x2, y2);
glTexCoord2f (0, ScreenHeight / 256.0f);
glVertex2i (x1, y2);
glEnd ();
if (r != NULL)
{
glDisable (GL_SCISSOR_TEST);
}
}
static void
TFB_GL_Preprocess (int force_full_redraw, int transition_amount, int fade_amount)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0,ScreenWidthActual,ScreenHeightActual, 0, -1, 1);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
if (optKeepAspectRatio)
glClear (GL_COLOR_BUFFER_BIT);
(void) transition_amount;
(void) fade_amount;
if (force_full_redraw == TFB_REDRAW_YES)
{
GL_Screens[TFB_SCREEN_MAIN].updated.x = 0;
GL_Screens[TFB_SCREEN_MAIN].updated.y = 0;
GL_Screens[TFB_SCREEN_MAIN].updated.w = ScreenWidth;
GL_Screens[TFB_SCREEN_MAIN].updated.h = ScreenHeight;
GL_Screens[TFB_SCREEN_MAIN].dirty = TRUE;
}
else if (TFB_BBox.valid)
{
GL_Screens[TFB_SCREEN_MAIN].updated.x = TFB_BBox.region.corner.x;
GL_Screens[TFB_SCREEN_MAIN].updated.y = TFB_BBox.region.corner.y;
GL_Screens[TFB_SCREEN_MAIN].updated.w = TFB_BBox.region.extent.width;
GL_Screens[TFB_SCREEN_MAIN].updated.h = TFB_BBox.region.extent.height;
GL_Screens[TFB_SCREEN_MAIN].dirty = TRUE;
}
}
static void
TFB_GL_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect)
{
glBindTexture (GL_TEXTURE_2D, GL_Screens[screen].texture);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
if (GL_Screens[screen].dirty)
{
int PitchWords = SDL_Screens[screen]->pitch / 4;
glPixelStorei (GL_UNPACK_ROW_LENGTH, PitchWords);
/* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_*
correctly */
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
SDL_LockSurface (SDL_Screens[screen]);
glTexSubImage2D (GL_TEXTURE_2D, 0, GL_Screens[screen].updated.x,
GL_Screens[screen].updated.y,
GL_Screens[screen].updated.w,
GL_Screens[screen].updated.h,
GL_RGBA, GL_UNSIGNED_BYTE,
(Uint32 *)SDL_Screens[screen]->pixels +
(GL_Screens[screen].updated.y * PitchWords +
GL_Screens[screen].updated.x));
SDL_UnlockSurface (SDL_Screens[screen]);
GL_Screens[screen].dirty = FALSE;
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode);
glEnable (GL_TEXTURE_2D);
if (a == 255)
{
glDisable (GL_BLEND);
glColor4f (1, 1, 1, 1);
}
else
{
float a_f = a / 255.0f;
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
glColor4f (1, 1, 1, a_f);
}
TFB_GL_DrawQuad (rect);
}
static void
TFB_GL_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect)
{
glBindTexture (GL_TEXTURE_2D, GL_Screens[screen].texture);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
if (GL_Screens[screen].dirty)
{
int PitchWords = GL_Screens[screen].scaled->pitch / 4;
scaler (SDL_Screens[screen], GL_Screens[screen].scaled, &GL_Screens[screen].updated);
glPixelStorei (GL_UNPACK_ROW_LENGTH, PitchWords);
/* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_*
correctly */
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
SDL_LockSurface (GL_Screens[screen].scaled);
glTexSubImage2D (GL_TEXTURE_2D, 0, GL_Screens[screen].updated.x * 2,
GL_Screens[screen].updated.y * 2,
GL_Screens[screen].updated.w * 2,
GL_Screens[screen].updated.h * 2,
GL_RGBA, GL_UNSIGNED_BYTE,
(Uint32 *)GL_Screens[screen].scaled->pixels +
(GL_Screens[screen].updated.y * 2 * PitchWords +
GL_Screens[screen].updated.x * 2));
SDL_UnlockSurface (GL_Screens[screen].scaled);
GL_Screens[screen].dirty = FALSE;
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode);
glEnable (GL_TEXTURE_2D);
if (a == 255)
{
glDisable (GL_BLEND);
glColor4f (1, 1, 1, 1);
}
else
{
float a_f = a / 255.0f;
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
glColor4f (1, 1, 1, a_f);
}
TFB_GL_DrawQuad (rect);
}
static void
TFB_GL_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect)
{
float r_f = r / 255.0f;
float g_f = g / 255.0f;
float b_f = b / 255.0f;
float a_f = a / 255.0f;
glColor4f(r_f, g_f, b_f, a_f);
glDisable (GL_TEXTURE_2D);
if (a != 255)
{
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
}
else
{
glDisable (GL_BLEND);
}
TFB_GL_DrawQuad (rect);
}
static void
TFB_GL_Postprocess (void)
{
if (GfxFlags & TFB_GFXFLAGS_SCANLINES)
TFB_GL_ScanLines ();
SDL_GL_SwapBuffers ();
}
#endif

View File

@@ -1,88 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef OPENGL_H
#define OPENGL_H
#include "libs/graphics/sdl/sdl_common.h"
int TFB_GL_InitGraphics (int driver, int flags, int width, int height);
int TFB_GL_ConfigureVideo (int driver, int flags, int width, int height, int togglefullscreen);
void TFB_GL_UploadTransitionScreen (void);
#ifdef HAVE_OPENGL
#ifdef WIN32
#ifdef _MSC_VER
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")
#endif
/* To avoid including windows.h,
Win32's <GL/gl.h> needs APIENTRY and WINGDIAPI defined properly. */
#ifndef APIENTRY
#define GLUT_APIENTRY_DEFINED
#if __MINGW32__ || (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
#endif
#ifndef WINAPI
#define GLUT_WINAPI_DEFINED
#if __MINGW32__ || (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define WINAPI __stdcall
#else
#define WINAPI
#endif
#endif
/* This is from Win32's <winnt.h> */
#ifndef CALLBACK
#if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
#define CALLBACK __stdcall
#else
#define CALLBACK
#endif
#endif
/* This is from Win32's <wingdi.h> and <winnt.h> */
#ifndef WINGDIAPI
#define GLUT_WINGDIAPI_DEFINED
#define WINGDIAPI __declspec(dllimport)
#endif
/* This is from Win32's <ctype.h> */
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
#include "GL/glu.h"
#else /* !defined(WIN32) */
#include "port.h"
#include SDL_INCLUDE(SDL_opengl.h)
#endif /* WIN32 */
#endif /* HAVE_OPENGL */
#endif

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2009 Alex Volkov <codepro@usa.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "palette.h"
#include "libs/memlib.h"
#include "libs/log.h"
NativePalette *
AllocNativePalette (void)
{
return HCalloc (sizeof (NativePalette));
}
void
FreeNativePalette (NativePalette *palette)
{
HFree (palette);
}
void
SetNativePaletteColor (NativePalette *palette, int index, Color color)
{
assert (index < NUMBER_OF_PLUTVALS);
palette->colors[index] = ColorToNative (color);
}
Color
GetNativePaletteColor (NativePalette *palette, int index)
{
assert (index < NUMBER_OF_PLUTVALS);
return NativeToColor (palette->colors[index]);
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright 2009 Alex Volkov <codepro@usa.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef PALETTE_H_INCL__
#define PALETTE_H_INCL__
#include "port.h"
#include SDL_INCLUDE(SDL.h)
#include "libs/graphics/cmap.h"
struct NativePalette
{
SDL_Color colors[NUMBER_OF_PLUTVALS];
};
static inline Color
NativeToColor (SDL_Color native)
{
Color color;
color.r = native.r;
color.g = native.g;
color.b = native.b;
color.a = 0xff; // fully opaque
return color;
}
static inline SDL_Color
ColorToNative (Color color)
{
SDL_Color native;
native.r = color.r;
native.g = color.g;
native.b = color.b;
native.unused = 0;
return native;
}
#endif /* PALETTE_H_INCL__ */

View File

@@ -1,635 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "port.h"
#include "sdl_common.h"
#include "primitives.h"
// Pixel drawing routines
static Uint32
getpixel_8(SDL_Surface *surface, int x, int y)
{
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x;
return *p;
}
static void
putpixel_8(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 1;
*p = pixel;
}
static Uint32
getpixel_16(SDL_Surface *surface, int x, int y)
{
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 2;
return *(Uint16 *)p;
}
static void
putpixel_16(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 2;
*(Uint16 *)p = pixel;
}
static Uint32
getpixel_24_be(SDL_Surface *surface, int x, int y)
{
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
return p[0] << 16 | p[1] << 8 | p[2];
}
static void
putpixel_24_be(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
static Uint32
getpixel_24_le(SDL_Surface *surface, int x, int y)
{
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
return p[0] | p[1] << 8 | p[2] << 16;
}
static void
putpixel_24_le(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
static Uint32
getpixel_32(SDL_Surface *surface, int x, int y)
{
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4;
return *(Uint32 *)p;
}
static void
putpixel_32(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4;
*(Uint32 *)p = pixel;
}
GetPixelFn
getpixel_for(SDL_Surface *surface)
{
int bpp = surface->format->BytesPerPixel;
switch (bpp) {
case 1:
return &getpixel_8;
case 2:
return &getpixel_16;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
return &getpixel_24_be;
} else {
return &getpixel_24_le;
}
case 4:
return &getpixel_32;
}
return NULL;
}
PutPixelFn
putpixel_for(SDL_Surface *surface)
{
int bpp = surface->format->BytesPerPixel;
switch (bpp) {
case 1:
return &putpixel_8;
case 2:
return &putpixel_16;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
return &putpixel_24_be;
} else {
return &putpixel_24_le;
}
case 4:
return &putpixel_32;
}
return NULL;
}
static void
renderpixel_replace(SDL_Surface *surface, int x, int y, Uint32 pixel,
int factor)
{
(void) factor; // ignored
putpixel_32(surface, x, y, pixel);
}
static inline Uint8
clip_channel(int c)
{
if (c < 0)
c = 0;
else if (c > 255)
c = 255;
return c;
}
static inline Uint8
modulated_sum(Uint8 dc, Uint8 sc, int factor)
{
// We use >> 8 instead of / 255 because it is faster, but it does
// not work 100% correctly. It should be safe because this should
// not be called for factor==255
int b = dc + ((sc * factor) >> 8);
return clip_channel(b);
}
static inline Uint8
alpha_blend(Uint8 dc, Uint8 sc, int alpha)
{
// We use >> 8 instead of / 255 because it is faster, but it does
// not work 100% correctly. It should be safe because this should
// not be called for alpha==255
// No need to clip since we should never get values outside of 0..255
// range, unless alpha is over 255, which is not supported.
return (((sc - dc) * alpha) >> 8) + dc;
}
// Assumes 8 bits/channel, a safe assumption for 32bpp surfaces
#define UNPACK_PIXEL_32(p, fmt, r, g, b) \
do { \
(r) = ((p) >> (fmt)->Rshift) & 0xff; \
(g) = ((p) >> (fmt)->Gshift) & 0xff; \
(b) = ((p) >> (fmt)->Bshift) & 0xff; \
} while (0)
// Assumes the channels already clipped to 8 bits
static inline Uint32
PACK_PIXEL_32(const SDL_PixelFormat *fmt,
Uint8 r, Uint8 g, Uint8 b)
{
return ((Uint32)r << fmt->Rshift) | ((Uint32)g << fmt->Gshift)
| ((Uint32)b << fmt->Bshift);
}
static void
renderpixel_additive(SDL_Surface *surface, int x, int y, Uint32 pixel,
int factor)
{
const SDL_PixelFormat *fmt = surface->format;
Uint32 *p;
Uint32 sp;
Uint8 sr, sg, sb;
int r, g, b;
p = (Uint32 *) ((Uint8 *)surface->pixels + y * surface->pitch + x * 4);
sp = *p;
UNPACK_PIXEL_32(sp, fmt, sr, sg, sb);
UNPACK_PIXEL_32(pixel, fmt, r, g, b);
// TODO: We may need a special case for factor == -ADDITIVE_FACTOR_1 too,
// but it is not important enough right now to care ;)
if (factor == ADDITIVE_FACTOR_1)
{ // no need to modulate the 'pixel', and modulation does not
// work correctly with factor==255 anyway
sr = clip_channel(sr + r);
sg = clip_channel(sg + g);
sb = clip_channel(sb + b);
}
else
{
sr = modulated_sum(sr, r, factor);
sg = modulated_sum(sg, g, factor);
sb = modulated_sum(sb, b, factor);
}
*p = PACK_PIXEL_32(fmt, sr, sg, sb);
}
static void
renderpixel_alpha(SDL_Surface *surface, int x, int y, Uint32 pixel,
int factor)
{
const SDL_PixelFormat *fmt = surface->format;
Uint32 *p;
Uint32 sp;
Uint8 sr, sg, sb;
int r, g, b;
if (factor == FULLY_OPAQUE_ALPHA)
{ // alpha == 255 is equivalent to 'replace' and blending does not
// work correctly anyway because we use >> 8 instead of / 255
putpixel_32(surface, x, y, pixel);
return;
}
p = (Uint32 *) ((Uint8 *)surface->pixels + y * surface->pitch + x * 4);
sp = *p;
UNPACK_PIXEL_32(sp, fmt, sr, sg, sb);
UNPACK_PIXEL_32(pixel, fmt, r, g, b);
sr = alpha_blend(sr, r, factor);
sg = alpha_blend(sg, g, factor);
sb = alpha_blend(sb, b, factor);
*p = PACK_PIXEL_32(fmt, sr, sg, sb);
}
RenderPixelFn
renderpixel_for(SDL_Surface *surface, RenderKind kind)
{
const SDL_PixelFormat *fmt = surface->format;
// The only supported rendering is to 32bpp surfaces
if (fmt->BytesPerPixel != 4)
return NULL;
// Rendering other than REPLACE is not supported on RGBA surfaces
if (fmt->Amask != 0 && kind != renderReplace)
return NULL;
switch (kind)
{
case renderReplace:
return &renderpixel_replace;
case renderAdditive:
return &renderpixel_additive;
case renderAlpha:
return &renderpixel_alpha;
}
// should not ever get here
return NULL;
}
/* Line drawing routine
* Adapted from Paul Heckbert's implementation of Bresenham's algorithm,
* 3 Sep 85; taken from Graphics Gems I */
void
line_prim(int x1, int y1, int x2, int y2, Uint32 color, RenderPixelFn plot,
int factor, SDL_Surface *dst)
{
int d, x, y, ax, ay, sx, sy, dx, dy;
SDL_Rect clip_r;
SDL_GetClipRect (dst, &clip_r);
if (!clip_line (&x1, &y1, &x2, &y2, &clip_r))
return; // line is completely outside clipping rectangle
dx = x2-x1;
ax = ((dx < 0) ? -dx : dx) << 1;
sx = (dx < 0) ? -1 : 1;
dy = y2-y1;
ay = ((dy < 0) ? -dy : dy) << 1;
sy = (dy < 0) ? -1 : 1;
x = x1;
y = y1;
if (ax > ay) {
d = ay - (ax >> 1);
for (;;) {
(*plot)(dst, x, y, color, factor);
if (x == x2)
return;
if (d >= 0) {
y += sy;
d -= ax;
}
x += sx;
d += ay;
}
} else {
d = ax - (ay >> 1);
for (;;) {
(*plot)(dst, x, y, color, factor);
if (y == y2)
return;
if (d >= 0) {
x += sx;
d -= ay;
}
y += sy;
d += ax;
}
}
}
// Clips line against rectangle using Cohen-Sutherland algorithm
enum {C_TOP = 0x1, C_BOTTOM = 0x2, C_RIGHT = 0x4, C_LEFT = 0x8};
static int
compute_code (float x, float y, float xmin, float ymin, float xmax, float ymax)
{
int c = 0;
if (y > ymax)
c |= C_TOP;
else if (y < ymin)
c |= C_BOTTOM;
if (x > xmax)
c |= C_RIGHT;
else if (x < xmin)
c |= C_LEFT;
return c;
}
int
clip_line (int *lx1, int *ly1, int *lx2, int *ly2, const SDL_Rect *r)
{
int C0, C1, C;
float x, y, x0, y0, x1, y1, xmin, ymin, xmax, ymax;
x0 = (float)*lx1;
y0 = (float)*ly1;
x1 = (float)*lx2;
y1 = (float)*ly2;
xmin = (float)r->x;
ymin = (float)r->y;
xmax = (float)r->x + r->w - 1;
ymax = (float)r->y + r->h - 1;
C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax);
C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax);
for (;;) {
/* trivial accept: both ends in rectangle */
if ((C0 | C1) == 0)
{
*lx1 = (int)x0;
*ly1 = (int)y0;
*lx2 = (int)x1;
*ly2 = (int)y1;
return 1;
}
/* trivial reject: both ends on the external side of the rectangle */
if ((C0 & C1) != 0)
return 0;
/* normal case: clip end outside rectangle */
C = C0 ? C0 : C1;
if (C & C_TOP)
{
x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0);
y = ymax;
}
else if (C & C_BOTTOM)
{
x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0);
y = ymin;
}
else if (C & C_RIGHT)
{
x = xmax;
y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0);
}
else
{
x = xmin;
y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0);
}
/* set new end point and iterate */
if (C == C0)
{
x0 = x; y0 = y;
C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax);
}
else
{
x1 = x; y1 = y;
C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax);
}
}
}
void
fillrect_prim(SDL_Rect r, Uint32 color, RenderPixelFn plot, int factor,
SDL_Surface *dst)
{
int x, y;
int x1, y1;
SDL_Rect clip_r;
SDL_GetClipRect (dst, &clip_r);
if (!clip_rect (&r, &clip_r))
return; // rect is completely outside clipping rectangle
// TODO: calculate destination pointer directly instead of
// using the plot(x,y) version
x1 = r.x + r.w;
y1 = r.y + r.h;
for (y = r.y; y < y1; ++y)
{
for (x = r.x; x < x1; ++x)
plot(dst, x, y, color, factor);
}
}
// clip the rectangle against the clip rectangle
int
clip_rect(SDL_Rect *r, const SDL_Rect *clip_r)
{
// NOTE: the following clipping code is copied in part
// from SDL-1.2.4 sources
int dx, dy;
int w = r->w;
int h = r->h;
// SDL_Rect.w and .h are unsigned, we need signed
dx = clip_r->x - r->x;
if (dx > 0)
{
w -= dx;
r->x += dx;
}
dx = r->x + w - clip_r->x - clip_r->w;
if (dx > 0)
w -= dx;
dy = clip_r->y - r->y;
if (dy > 0)
{
h -= dy;
r->y += dy;
}
dy = r->y + h - clip_r->y - clip_r->h;
if (dy > 0)
h -= dy;
if (w <= 0 || h <= 0)
{
r->w = 0;
r->h = 0;
return 0;
}
r->w = w;
r->h = h;
return 1;
}
void
blt_prim(SDL_Surface *src, SDL_Rect src_r, RenderPixelFn plot, int factor,
SDL_Surface *dst, SDL_Rect dst_r)
{
SDL_PixelFormat *srcfmt = src->format;
SDL_Palette *srcpal = srcfmt->palette;
SDL_PixelFormat *dstfmt = dst->format;
Uint32 mask = 0;
Uint32 key = ~0;
GetPixelFn getpix = getpixel_for(src);
SDL_Rect clip_r;
int x, y;
SDL_GetClipRect (dst, &clip_r);
if (!clip_blt_rects (&src_r, &dst_r, &clip_r))
return; // rect is completely outside clipping rectangle
if (src_r.x >= src->w || src_r.y >= src->h)
return; // rect is completely outside source bounds
if (src_r.x + src_r.w > src->w)
src_r.w = src->w - src_r.x;
if (src_r.y + src_r.h > src->h)
src_r.h = src->h - src_r.y;
// use colorkeys where appropriate
if (srcfmt->Amask)
{ // alpha transparency
mask = srcfmt->Amask;
key = 0;
}
else if (src->flags & SDL_SRCCOLORKEY)
{ // colorkey transparency
mask = ~srcfmt->Amask;
key = srcfmt->colorkey & mask;
}
// TODO: calculate the source and destination pointers directly
// instead of using the plot(x,y) version
for (y = 0; y < src_r.h; ++y)
{
for (x = 0; x < src_r.w; ++x)
{
Uint8 r, g, b, a;
Uint32 p;
p = getpix(src, src_r.x + x, src_r.y + y);
if (srcpal)
{ // source is paletted, colorkey does not use mask
if (p == key)
continue; // transparent pixel
}
else
{ // source is RGB(A), colorkey uses mask
if ((p & mask) == key)
continue; // transparent pixel
}
// convert pixel format to destination
SDL_GetRGBA(p, srcfmt, &r, &g, &b, &a);
// TODO: handle source pixel alpha; plot() should probably
// get a source alpha parameter
p = SDL_MapRGBA(dstfmt, r, g, b, a);
plot(dst, dst_r.x + x, dst_r.y + y, p, factor);
}
}
}
// clip the source and destination rectangles against the clip rectangle
int
clip_blt_rects(SDL_Rect *src_r, SDL_Rect *dst_r, const SDL_Rect *clip_r)
{
// NOTE: the following clipping code is copied in part
// from SDL-1.2.4 sources
int w, h;
int dx, dy;
// clip the source rectangle to the source surface
w = src_r->w;
if (src_r->x < 0)
{
w += src_r->x;
dst_r->x -= src_r->x;
src_r->x = 0;
}
h = src_r->h;
if (src_r->y < 0)
{
h += src_r->y;
dst_r->y -= src_r->y;
src_r->y = 0;
}
// clip the destination rectangle against the clip rectangle,
// minding the source rectangle in the process
dx = clip_r->x - dst_r->x;
if (dx > 0)
{
w -= dx;
dst_r->x += dx;
src_r->x += dx;
}
dx = dst_r->x + w - clip_r->x - clip_r->w;
if (dx > 0)
w -= dx;
dy = clip_r->y - dst_r->y;
if (dy > 0)
{
h -= dy;
dst_r->y += dy;
src_r->y += dy;
}
dy = dst_r->y + h - clip_r->y - clip_r->h;
if (dy > 0)
h -= dy;
if (w <= 0 || h <= 0)
{
src_r->w = 0;
src_r->h = 0;
return 0;
}
src_r->w = w;
src_r->h = h;
return 1;
}

View File

@@ -1,62 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef PRIMITIVES_H
#define PRIMITIVES_H
/* Function types for the pixel functions */
typedef Uint32 (*GetPixelFn)(SDL_Surface *, int x, int y);
// 'pixel' is in destination surface format
typedef void (*PutPixelFn)(SDL_Surface *, int x, int y, Uint32 pixel);
GetPixelFn getpixel_for(SDL_Surface *surface);
PutPixelFn putpixel_for(SDL_Surface *surface);
// This currently matches gfxlib.h:DrawKind for simplicity
typedef enum
{
renderReplace = 0,
renderAdditive,
renderAlpha,
} RenderKind;
#define FULLY_OPAQUE_ALPHA 255
#define ADDITIVE_FACTOR_1 255
// 'pixel' is in destination surface format
// See gfxlib.h:DrawKind for 'factor' spec
typedef void (*RenderPixelFn)(SDL_Surface *, int x, int y, Uint32 pixel,
int factor);
RenderPixelFn renderpixel_for(SDL_Surface *surface, RenderKind);
void line_prim(int x1, int y1, int x2, int y2, Uint32 color,
RenderPixelFn plot, int factor, SDL_Surface *dst);
void fillrect_prim(SDL_Rect r, Uint32 color,
RenderPixelFn plot, int factor, SDL_Surface *dst);
void blt_prim(SDL_Surface *src, SDL_Rect src_r,
RenderPixelFn plot, int factor,
SDL_Surface *dst, SDL_Rect dst_r);
int clip_line(int *lx1, int *ly1, int *lx2, int *ly2, const SDL_Rect *clip_r);
int clip_rect(SDL_Rect *r, const SDL_Rect *clip_r);
int clip_blt_rects(SDL_Rect *src_r, SDL_Rect *dst_r, const SDL_Rect *clip_r);
#endif /* PRIMITIVES_H */

View File

@@ -1,484 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "pure.h"
#include "libs/graphics/bbox.h"
#include "scalers.h"
#include "libs/log.h"
static SDL_Surface *fade_color_surface = NULL;
static SDL_Surface *fade_temp = NULL;
static SDL_Surface *scaled_display = NULL;
static TFB_ScaleFunc scaler = NULL;
static Uint32 fade_color;
static void TFB_Pure_Scaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount);
static void TFB_Pure_Scaled_Postprocess (void);
static void TFB_Pure_Unscaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount);
static void TFB_Pure_Unscaled_Postprocess (void);
static void TFB_Pure_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect);
static void TFB_Pure_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect);
static TFB_GRAPHICS_BACKEND pure_scaled_backend = {
TFB_Pure_Scaled_Preprocess,
TFB_Pure_Scaled_Postprocess,
TFB_Pure_ScreenLayer,
TFB_Pure_ColorLayer };
static TFB_GRAPHICS_BACKEND pure_unscaled_backend = {
TFB_Pure_Unscaled_Preprocess,
TFB_Pure_Unscaled_Postprocess,
TFB_Pure_ScreenLayer,
TFB_Pure_ColorLayer };
static SDL_Surface *
Create_Screen (SDL_Surface *template, int w, int h)
{
SDL_Surface *newsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
template->format->BitsPerPixel,
template->format->Rmask, template->format->Gmask,
template->format->Bmask, 0);
if (newsurf == 0) {
log_add (log_Error, "Couldn't create screen buffers: %s",
SDL_GetError());
}
return newsurf;
}
static int
ReInit_Screen (SDL_Surface **screen, SDL_Surface *template, int w, int h)
{
if (*screen)
SDL_FreeSurface (*screen);
*screen = Create_Screen (template, w, h);
return *screen == 0 ? -1 : 0;
}
// We cannot rely on SDL_DisplayFormatAlpha() anymore. It can return
// formats that we do not expect (SDL v1.2.14 on Mac OSX). Mac likes
// ARGB surfaces, but SDL_DisplayFormatAlpha thinks that only RGBA are fast.
// This is a generic replacement that gives what we want.
static void
CalcAlphaFormat (const SDL_PixelFormat* video, SDL_PixelFormat* ours)
{
int valid = 0;
// We use 32-bit surfaces internally
ours->BitsPerPixel = 32;
// Try to get as close to the video format as possible
if (video->BitsPerPixel == 15 || video->BitsPerPixel == 16)
{ // At least match the channel order
ours->Rshift = video->Rshift / 5 * 8;
ours->Gshift = video->Gshift / 5 * 8;
ours->Bshift = video->Bshift / 5 * 8;
valid = 1;
}
else if (video->BitsPerPixel == 24 || video->BitsPerPixel == 32)
{
// We can only use channels aligned on byte boundary
if (video->Rshift % 8 == 0 && video->Gshift % 8 == 0
&& video->Bshift % 8 == 0)
{ // Match RGB in video
ours->Rshift = video->Rshift;
ours->Gshift = video->Gshift;
ours->Bshift = video->Bshift;
valid = 1;
}
}
if (valid)
{ // For alpha, use the unoccupied byte
ours->Ashift = 48 - (ours->Rshift + ours->Gshift + ours->Bshift);
// Set channels according to byte positions
ours->Rmask = 0xff << ours->Rshift;
ours->Gmask = 0xff << ours->Gshift;
ours->Bmask = 0xff << ours->Bshift;
ours->Amask = 0xff << ours->Ashift;
return;
}
// Fallback case. It does not matter what we set, but SDL likes
// Alpha to be the highest.
ours->Rmask = 0x000000ff;
ours->Gmask = 0x0000ff00;
ours->Bmask = 0x00ff0000;
ours->Amask = 0xff000000;
}
int
TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height, int togglefullscreen)
{
int i, videomode_flags;
SDL_PixelFormat conv_fmt;
int BPP = 32;
GraphicsDriver = driver;
// must use SDL_SWSURFACE, HWSURFACE doesn't work properly
// with fades/scaling
if (width == 320 && height == 240)
{
videomode_flags = SDL_SWSURFACE;
ScreenWidthActual = 320;
ScreenHeightActual = 240;
graphics_backend = &pure_unscaled_backend;
}
else
{
videomode_flags = SDL_SWSURFACE;
ScreenWidthActual = 640;
ScreenHeightActual = 480;
graphics_backend = &pure_scaled_backend;
if (width != 640 || height != 480)
log_add (log_Error, "Screen resolution of %dx%d not supported "
"under pure SDL, using 640x480", width, height);
}
#ifdef ANDROID
videomode_flags = SDL_SWSURFACE;
ScreenWidthActual = 320;
ScreenHeightActual = 240;
graphics_backend = &pure_unscaled_backend;
BPP = 16;
#endif
videomode_flags |= SDL_ANYFORMAT;
if (flags & TFB_GFXFLAGS_FULLSCREEN)
videomode_flags |= SDL_FULLSCREEN;
/* We'll ask for a 32bpp frame, but it doesn't really matter, because we've set
SDL_ANYFORMAT */
SDL_Video = SDL_SetVideoMode (ScreenWidthActual, ScreenHeightActual,
BPP, videomode_flags);
if (SDL_Video == NULL)
{
log_add (log_Error, "Couldn't set %ix%i video mode: %s",
ScreenWidthActual, ScreenHeightActual,
SDL_GetError ());
return -1;
}
else
{
const SDL_Surface *video = SDL_GetVideoSurface ();
const SDL_PixelFormat* fmt = video->format;
ScreenColorDepth = fmt->BitsPerPixel;
log_add (log_Info, "Set the resolution to: %ix%ix%i",
video->w, video->h, ScreenColorDepth);
log_add (log_Info, " Video: R %08x, G %08x, B %08x, A %08x",
fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
if (togglefullscreen)
{
// NOTE: We cannot change the format_conv_surf now because we
// have already loaded lots of graphics and changing it now
// will only lead to chaos.
// Just check if channel order has changed significantly
CalcAlphaFormat (fmt, &conv_fmt);
fmt = format_conv_surf->format;
if (conv_fmt.Rmask != fmt->Rmask || conv_fmt.Bmask != fmt->Bmask)
log_add (log_Warning, "Warning: pixel format has changed "
"significantly. Rendering will be slow.");
return 0;
}
}
// Create a 32bpp surface in a compatible format which will supply
// the format information to all other surfaces used in the game
if (format_conv_surf)
{
SDL_FreeSurface (format_conv_surf);
format_conv_surf = NULL;
}
CalcAlphaFormat (SDL_Video->format, &conv_fmt);
format_conv_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, 0, 0,
conv_fmt.BitsPerPixel, conv_fmt.Rmask, conv_fmt.Gmask,
conv_fmt.Bmask, conv_fmt.Amask);
if (!format_conv_surf)
{
log_add (log_Error, "Couldn't create format_conv_surf: %s",
SDL_GetError());
return -1;
}
else
{
const SDL_PixelFormat* fmt = format_conv_surf->format;
log_add (log_Info, " Internal: R %08x, G %08x, B %08x, A %08x",
fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
}
for (i = 0; i < TFB_GFX_NUMSCREENS; i++)
{
if (0 != ReInit_Screen (&SDL_Screens[i], format_conv_surf,
ScreenWidth, ScreenHeight))
return -1;
}
SDL_Screen = SDL_Screens[0];
TransitionScreen = SDL_Screens[2];
if (0 != ReInit_Screen (&fade_color_surface, format_conv_surf,
ScreenWidth, ScreenHeight))
return -1;
fade_color = SDL_MapRGB (fade_color_surface->format, 0, 0, 0);
SDL_FillRect (fade_color_surface, NULL, fade_color);
if (0 != ReInit_Screen (&fade_temp, format_conv_surf,
ScreenWidth, ScreenHeight))
return -1;
if (ScreenWidthActual > ScreenWidth || ScreenHeightActual > ScreenHeight)
{
if (0 != ReInit_Screen (&scaled_display, format_conv_surf,
ScreenWidthActual, ScreenHeightActual))
return -1;
scaler = Scale_PrepPlatform (flags, SDL_Screen->format);
}
else
{ // no need to scale
scaler = NULL;
}
return 0;
}
int
TFB_Pure_InitGraphics (int driver, int flags, int width, int height)
{
char VideoName[256];
log_add (log_Info, "Initializing Pure-SDL graphics.");
SDL_VideoDriverName (VideoName, sizeof (VideoName));
log_add (log_Info, "SDL driver used: %s", VideoName);
// Set the environment variable SDL_VIDEODRIVER to override
// For Linux: x11 (default), dga, fbcon, directfb, svgalib,
// ggi, aalib
// For Windows: directx (default), windib
log_add (log_Info, "SDL initialized.");
log_add (log_Info, "Initializing Screen.");
ScreenWidth = 320;
ScreenHeight = 240;
if (TFB_Pure_ConfigureVideo (driver, flags, width, height, 0))
{
log_add (log_Fatal, "Could not initialize video: "
"no fallback at start of program!");
exit (EXIT_FAILURE);
}
// Initialize scalers (let them precompute whatever)
Scale_Init ();
return 0;
}
static void
ScanLines (SDL_Surface *dst, SDL_Rect *r)
{
const int rw = r->w * 2;
const int rh = r->h * 2;
SDL_PixelFormat *fmt = dst->format;
const int pitch = dst->pitch;
const int len = pitch / fmt->BytesPerPixel;
int ddst;
Uint32 *p = (Uint32 *) dst->pixels;
int x, y;
p += len * (r->y * 2) + (r->x * 2);
ddst = len + len - rw;
for (y = rh; y; y -= 2, p += ddst)
{
for (x = rw; x; --x, ++p)
{
// we ignore the lower bits as the difference
// of 1 in 255 is negligible
*p = ((*p >> 1) & 0x7f7f7f7f) + ((*p >> 2) & 0x3f3f3f3f);
}
}
}
static SDL_Surface *backbuffer = NULL, *scalebuffer = NULL;
static SDL_Rect updated;
static void
TFB_Pure_Scaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount)
{
if (force_full_redraw != TFB_REDRAW_NO)
{
updated.x = updated.y = 0;
updated.w = ScreenWidth;
updated.h = ScreenHeight;
}
else
{
updated.x = TFB_BBox.region.corner.x;
updated.y = TFB_BBox.region.corner.y;
updated.w = TFB_BBox.region.extent.width;
updated.h = TFB_BBox.region.extent.height;
}
if (transition_amount == 255 && fade_amount == 255)
backbuffer = SDL_Screens[TFB_SCREEN_MAIN];
else
backbuffer = fade_temp;
// we can scale directly onto SDL_Video if video is compatible
if (SDL_Video->format->BitsPerPixel == SDL_Screen->format->BitsPerPixel
&& SDL_Video->format->Rmask == SDL_Screen->format->Rmask
&& SDL_Video->format->Bmask == SDL_Screen->format->Bmask)
scalebuffer = SDL_Video;
else
scalebuffer = scaled_display;
}
static void
TFB_Pure_Unscaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount)
{
if (force_full_redraw != TFB_REDRAW_NO)
{
updated.x = updated.y = 0;
updated.w = ScreenWidth;
updated.h = ScreenHeight;
}
else
{
updated.x = TFB_BBox.region.corner.x;
updated.y = TFB_BBox.region.corner.y;
updated.w = TFB_BBox.region.extent.width;
updated.h = TFB_BBox.region.extent.height;
}
backbuffer = SDL_Video;
(void)transition_amount;
(void)fade_amount;
}
static void
TFB_Pure_Scaled_Postprocess (void)
{
SDL_LockSurface (scalebuffer);
SDL_LockSurface (backbuffer);
if (scaler)
scaler (backbuffer, scalebuffer, &updated);
if (GfxFlags & TFB_GFXFLAGS_SCANLINES)
ScanLines (scalebuffer, &updated);
SDL_UnlockSurface (backbuffer);
SDL_UnlockSurface (scalebuffer);
updated.x *= 2;
updated.y *= 2;
updated.w *= 2;
updated.h *= 2;
if (scalebuffer != SDL_Video)
SDL_BlitSurface (scalebuffer, &updated, SDL_Video, &updated);
SDL_UpdateRects (SDL_Video, 1, &updated);
}
static void
TFB_Pure_Unscaled_Postprocess (void)
{
SDL_UpdateRect (SDL_Video, updated.x, updated.y,
updated.w, updated.h);
}
static void
TFB_Pure_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect)
{
if (SDL_Screens[screen] == backbuffer)
return;
SDL_SetAlpha (SDL_Screens[screen], SDL_SRCALPHA, a);
SDL_BlitSurface (SDL_Screens[screen], rect, backbuffer, rect);
}
static void
TFB_Pure_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect)
{
Uint32 col = SDL_MapRGB (fade_color_surface->format, r, g, b);
if (col != fade_color)
{
fade_color = col;
SDL_FillRect (fade_color_surface, NULL, fade_color);
}
SDL_SetAlpha (fade_color_surface, SDL_SRCALPHA, a);
SDL_BlitSurface (fade_color_surface, rect, backbuffer, rect);
}
void
Scale_PerfTest (void)
{
TimeCount TimeStart, TimeIn;
TimeCount Now = 0;
SDL_Rect updated = {0, 0, ScreenWidth, ScreenHeight};
int i;
if (!scaler)
{
log_add (log_Error, "No scaler configured! "
"Run with larger resolution, please");
return;
}
if (!scaled_display)
{
log_add (log_Error, "Run scaler performance tests "
"in Pure mode, please");
return;
}
SDL_LockSurface (SDL_Screen);
SDL_LockSurface (scaled_display);
TimeStart = TimeIn = SDL_GetTicks ();
for (i = 1; i < 1001; ++i) // run for 1000 frames
{
scaler (SDL_Screen, scaled_display, &updated);
if (GfxFlags & TFB_GFXFLAGS_SCANLINES)
ScanLines (scaled_display, &updated);
if (i % 100 == 0)
{
Now = SDL_GetTicks ();
log_add (log_Debug, "%03d(%04u) ", 100*1000 / (Now - TimeIn),
Now - TimeIn);
TimeIn = Now;
}
}
log_add (log_Debug, "Full frames scaled: %d; over %u ms; %d fps\n",
(i - 1), Now - TimeStart, i * 1000 / (Now - TimeStart));
SDL_UnlockSurface (scaled_display);
SDL_UnlockSurface (SDL_Screen);
}

View File

@@ -1,28 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef PURE_H
#define PURE_H
#include "libs/graphics/sdl/sdl_common.h"
int TFB_Pure_InitGraphics (int driver, int flags, int width, int height);
int TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height, int togglefullscreen);
void Scale_PerfTest (void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,96 +0,0 @@
/*
rotozoom.h - rotozoomer for 32bit or 8bit surfaces
LGPL (c) A. Schiffler
Note by sc2 developers:
Taken from SDL_gfx library and modified, original code can be downloaded
from http://www.ferzkopp.net/Software/SDL_gfx-2.0/
*/
#ifndef ROTOZOOM_H
#define ROTOZOOM_H
#include <math.h>
#ifndef M_PI
#define M_PI 3.141592654
#endif
#include "port.h"
#include SDL_INCLUDE(SDL.h)
/* ---- Defines */
#define SMOOTHING_OFF 0
#define SMOOTHING_ON 1
/* ---- Structures */
typedef struct tColorRGBA {
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
} tColorRGBA;
typedef struct tColorY {
Uint8 y;
} tColorY;
/* ---- Prototypes */
/*
zoomSurfaceRGBA()
Zoom the src surface into dst. The zoom amount is determined
by the dimensions of src and dst
*/
int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth);
/*
rotozoomSurface()
Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom,
int smooth);
int rotateSurface(SDL_Surface * src, SDL_Surface * dst, double angle,
int smooth);
/* Returns the size of the target surface for a rotozoomSurface() call */
void rotozoomSurfaceSize(int width, int height, double angle, double zoom,
int *dstwidth, int *dstheight);
/*
zoomSurface()
Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy,
int smooth);
/* Returns the size of the target surface for a zoomSurface() call */
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy,
int *dstwidth, int *dstheight);
#endif

View File

@@ -1,433 +0,0 @@
/*
* Copyright (C) 2005 Alex Volkov (codepro@usa.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Scalers Internals
#ifndef SCALEINT_H_
#define SCALEINT_H_
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
// Plain C names
#define SCALE_(name) Scale ## _ ## name
// These are defaults
#define SCALE_GETPIX(p) ( *(Uint32 *)(p) )
#define SCALE_SETPIX(p, c) ( *(Uint32 *)(p) = (c) )
// Plain C defaults
#define SCALE_CMPRGB(p1, p2) \
SCALE_(GetRGBDelta) (fmt, p1, p2)
#define SCALE_TOYUV(p) \
SCALE_(RGBtoYUV) (fmt, p)
#define SCALE_CMPYUV(p1, p2, toler) \
SCALE_(CmpYUV) (fmt, p1, p2, toler)
#define SCALE_DIFFYUV(p1, p2) \
SCALE_(DiffYUV) (p1, p2)
#define SCALE_DIFFYUV_TY 0x40
#define SCALE_DIFFYUV_TU 0x12
#define SCALE_DIFFYUV_TV 0x0c
#define SCALE_GETY(p) \
SCALE_(GetPixY) (fmt, p)
#define SCALE_BILINEAR_BLEND4(r0, r1, dst, dlen) \
SCALE_(Blend_bilinear) (r0, r1, dst, dlen)
#define NO_PREFETCH 0
#define INTEL_PREFETCH 1
#define AMD_PREFETCH 2
typedef enum
{
YUV_XFORM_R = 0,
YUV_XFORM_G = 1,
YUV_XFORM_B = 2,
YUV_XFORM_Y = 0,
YUV_XFORM_U = 1,
YUV_XFORM_V = 2
} RGB_YUV_INDEX;
extern const int YUV_matrix[3][3];
// pre-computed transformations for 8 bits per channel
extern int RGB_to_YUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 256];
extern sint16 dRGB_to_dYUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 512];
typedef Uint32 YUV_VECTOR;
// pre-computed transformations for RGB555
extern YUV_VECTOR RGB15_to_YUV[0x8000];
// Platform+Scaler function lookups
//
typedef struct
{
int flag;
TFB_ScaleFunc func;
} Scale_FuncDef_t;
// expands the given rectangle in all directions by 'expansion'
// guarded by 'limits'
extern void Scale_ExpandRect (SDL_Rect* rect, int expansion,
const SDL_Rect* limits);
// Standard plain C versions of support functions
// Initialize various platform-specific features
static inline void
SCALE_(PlatInit) (void)
{
}
// Finish with various platform-specific features
static inline void
SCALE_(PlatDone) (void)
{
}
#if 0
static inline void
SCALE_(Prefetch) (const void* p)
{
/* no-op in pure C */
(void)p;
}
#else
# define Scale_Prefetch(p)
#endif
// compute the RGB distance squared between 2 pixels
// Plain C version
static inline int
SCALE_(GetRGBDelta) (const SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2)
{
int c;
int delta;
c = ((pix1 >> fmt->Rshift) & 0xff) - ((pix2 >> fmt->Rshift) & 0xff);
delta = c * c;
c = ((pix1 >> fmt->Gshift) & 0xff) - ((pix2 >> fmt->Gshift) & 0xff);
delta += c * c;
c = ((pix1 >> fmt->Bshift) & 0xff) - ((pix2 >> fmt->Bshift) & 0xff);
delta += c * c;
return delta;
}
// retrieve the Y (intensity) component of pixel's YUV
// Plain C version
static inline int
SCALE_(GetPixY) (const SDL_PixelFormat* fmt, Uint32 pix)
{
Uint32 r, g, b;
r = (pix >> fmt->Rshift) & 0xff;
g = (pix >> fmt->Gshift) & 0xff;
b = (pix >> fmt->Bshift) & 0xff;
return RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r]
+ RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g]
+ RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b];
}
static inline YUV_VECTOR
SCALE_(RGBtoYUV) (const SDL_PixelFormat* fmt, Uint32 pix)
{
return RGB15_to_YUV[
(((pix >> (fmt->Rshift + 3)) & 0x1f) << 10) |
(((pix >> (fmt->Gshift + 3)) & 0x1f) << 5) |
(((pix >> (fmt->Bshift + 3)) & 0x1f) )
];
}
// compare 2 pixels with respect to their YUV representations
// tolerance set by toler arg
// returns true: close; false: distant (-gt toler)
// Plain C version
static inline bool
SCALE_(CmpYUV) (const SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2, int toler)
#if 1
{
int dr, dg, db;
int delta;
dr = ((pix1 >> fmt->Rshift) & 0xff) - ((pix2 >> fmt->Rshift) & 0xff) + 255;
dg = ((pix1 >> fmt->Gshift) & 0xff) - ((pix2 >> fmt->Gshift) & 0xff) + 255;
db = ((pix1 >> fmt->Bshift) & 0xff) - ((pix2 >> fmt->Bshift) & 0xff) + 255;
// compute Y delta
delta = abs (dRGB_to_dYUV [YUV_XFORM_R][YUV_XFORM_Y][dr]
+ dRGB_to_dYUV [YUV_XFORM_G][YUV_XFORM_Y][dg]
+ dRGB_to_dYUV [YUV_XFORM_B][YUV_XFORM_Y][db]);
if (delta > toler)
return false;
// compute U delta
delta += abs (dRGB_to_dYUV [YUV_XFORM_R][YUV_XFORM_U][dr]
+ dRGB_to_dYUV [YUV_XFORM_G][YUV_XFORM_U][dg]
+ dRGB_to_dYUV [YUV_XFORM_B][YUV_XFORM_U][db]);
if (delta > toler)
return false;
// compute V delta
delta += abs (dRGB_to_dYUV [YUV_XFORM_R][YUV_XFORM_V][dr]
+ dRGB_to_dYUV [YUV_XFORM_G][YUV_XFORM_V][dg]
+ dRGB_to_dYUV [YUV_XFORM_B][YUV_XFORM_V][db]);
return delta <= toler;
}
#else
{
int delta;
Uint32 yuv1, yuv2;
yuv1 = RGB15_to_YUV[
(((pix1 >> (fmt->Rshift + 3)) & 0x1f) << 10) |
(((pix1 >> (fmt->Gshift + 3)) & 0x1f) << 5) |
(((pix1 >> (fmt->Bshift + 3)) & 0x1f) )
];
yuv2 = RGB15_to_YUV[
(((pix2 >> (fmt->Rshift + 3)) & 0x1f) << 10) |
(((pix2 >> (fmt->Gshift + 3)) & 0x1f) << 5) |
(((pix2 >> (fmt->Bshift + 3)) & 0x1f) )
];
// compute Y delta
delta = abs ((yuv1 & 0xff0000) - (yuv2 & 0xff0000)) >> 16;
if (delta > toler)
return false;
// compute U delta
delta += abs ((yuv1 & 0x00ff00) - (yuv2 & 0x00ff00)) >> 8;
if (delta > toler)
return false;
// compute V delta
delta += abs ((yuv1 & 0x0000ff) - (yuv2 & 0x0000ff));
return delta <= toler;
}
#endif
// Check if 2 pixels are different with respect to their
// YUV representations
// returns 0: close; ~0: distant
static inline int
SCALE_(DiffYUV) (Uint32 yuv1, Uint32 yuv2)
{
// non-branching version -- assumes 2's complement integers
// delta math only needs 25 bits and we have 32 available;
// only interested in the sign bits after subtraction
sint32 delta, ret;
if (yuv1 == yuv2)
return 0;
// compute Y delta
delta = abs ((yuv1 & 0xff0000) - (yuv2 & 0xff0000));
ret = (SCALE_DIFFYUV_TY << 16) - delta; // save sign bit
// compute U delta
delta = abs ((yuv1 & 0x00ff00) - (yuv2 & 0x00ff00));
ret |= (SCALE_DIFFYUV_TU << 8) - delta; // save sign bit
// compute V delta
delta = abs ((yuv1 & 0x0000ff) - (yuv2 & 0x0000ff));
ret |= SCALE_DIFFYUV_TV - delta; // save sign bit
return (ret >> 31);
}
// blends two pixels with 1:1 ratio
static inline Uint32
SCALE_(Blend_11) (Uint32 pix1, Uint32 pix2)
{
/* (pix1 + pix2) >> 1 */
return
/* lower bits can be safely ignored - the error is minimal
expression that calcs them is left for posterity
(pix1 & pix2 & low_mask) +
*/
((pix1 & 0xfefefefe) >> 1) + ((pix2 & 0xfefefefe) >> 1);
}
// blends four pixels with 1:1:1:1 ratio
static inline Uint32
SCALE_(Blend_1111) (Uint32 pix1, Uint32 pix2,
Uint32 pix3, Uint32 pix4)
{
/* (pix1 + pix2 + pix3 + pix4) >> 2 */
return
/* lower bits can be safely ignored - the error is minimal
expression that calcs them is left for posterity
((((pix1 & low_mask) + (pix2 & low_mask) +
(pix3 & low_mask) + (pix4 & low_mask)
) >> 2) & low_mask) +
*/
((pix1 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xfcfcfcfc) >> 2) +
((pix3 & 0xfcfcfcfc) >> 2) + ((pix4 & 0xfcfcfcfc) >> 2);
}
// blends pixels with 3:1 ratio
static inline Uint32
Scale_Blend_31 (Uint32 pix1, Uint32 pix2)
{
/* (pix1 * 3 + pix2) / 4 */
/* lower bits can be safely ignored - the error is minimal */
return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xfcfcfcfc) >> 2) +
((pix2 & 0xfcfcfcfc) >> 2);
}
// blends pixels with 2:1:1 ratio
static inline Uint32
Scale_Blend_211 (Uint32 pix1, Uint32 pix2, Uint32 pix3)
{
/* (pix1 * 2 + pix2 + pix3) / 4 */
/* lower bits can be safely ignored - the error is minimal */
return ((pix1 & 0xfefefefe) >> 1) +
((pix2 & 0xfcfcfcfc) >> 2) +
((pix3 & 0xfcfcfcfc) >> 2);
}
// blends pixels with 5:2:1 ratio
static inline Uint32
Scale_Blend_521 (Uint32 pix1, Uint32 pix2, Uint32 pix3)
{
/* (pix1 * 5 + pix2 * 2 + pix3) / 8 */
/* lower bits can be safely ignored - the error is minimal */
return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xf8f8f8f8) >> 3) +
((pix2 & 0xfcfcfcfc) >> 2) +
((pix3 & 0xf8f8f8f8) >> 3) +
0x02020202 /* half-error */;
}
// blends pixels with 6:1:1 ratio
static inline Uint32
Scale_Blend_611 (Uint32 pix1, Uint32 pix2, Uint32 pix3)
{
/* (pix1 * 6 + pix2 + pix3) / 8 */
/* lower bits can be safely ignored - the error is minimal */
return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xfcfcfcfc) >> 2) +
((pix2 & 0xf8f8f8f8) >> 3) +
((pix3 & 0xf8f8f8f8) >> 3) +
0x02020202 /* half-error */;
}
// blends pixels with 2:3:3 ratio
static inline Uint32
Scale_Blend_233 (Uint32 pix1, Uint32 pix2, Uint32 pix3)
{
/* (pix1 * 2 + pix2 * 3 + pix3 * 3) / 8 */
/* lower bits can be safely ignored - the error is minimal */
return ((pix1 & 0xfcfcfcfc) >> 2) +
((pix2 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xf8f8f8f8) >> 3) +
((pix3 & 0xfcfcfcfc) >> 2) + ((pix3 & 0xf8f8f8f8) >> 3) +
0x02020202 /* half-error */;
}
// blends pixels with 14:1:1 ratio
static inline Uint32
Scale_Blend_e11 (Uint32 pix1, Uint32 pix2, Uint32 pix3)
{
/* (pix1 * 14 + pix2 + pix3) >> 4 */
/* lower bits can be safely ignored - the error is minimal */
return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xfcfcfcfc) >> 2) +
((pix1 & 0xf8f8f8f8) >> 3) +
((pix2 & 0xf0f0f0f0) >> 4) +
((pix3 & 0xf0f0f0f0) >> 4) +
0x03030303 /* half-error */;
}
// Halfs the pixel's intensity
static inline Uint32
SCALE_(HalfPixel) (Uint32 pix)
{
return ((pix & 0xfefefefe) >> 1);
}
// Bilinear weighted blend of four pixels
// Function produces 4 blended pixels and writes them
// out to the surface (in 2x2 matrix)
// Pixels are computed using expanded weight matrix like so:
// ('sp' - source pixel, 'dp' - destination pixel)
// dp[0] = (9*sp[0] + 3*sp[1] + 3*sp[2] + 1*sp[3]) / 16
// dp[1] = (3*sp[0] + 9*sp[1] + 1*sp[2] + 3*sp[3]) / 16
// dp[2] = (3*sp[0] + 1*sp[1] + 9*sp[2] + 3*sp[3]) / 16
// dp[3] = (1*sp[0] + 3*sp[1] + 3*sp[2] + 9*sp[3]) / 16
static inline void
SCALE_(Blend_bilinear) (const Uint32* row0, const Uint32* row1,
Uint32* dst_p, Uint32 dlen)
{
// We loose some lower bits here and try to compensate for
// that by adding half-error values.
// In general, the error is minimal (+-7)
// The >>4 reduction is achieved gradually
# define BL_PACKED_HALF(p) \
(((p) & 0xfefefefe) >> 1)
# define BL_SUM(p1, p2) \
(BL_PACKED_HALF(p1) + BL_PACKED_HALF(p2))
# define BL_HALF_ERR 0x01010101
# define BL_SUM_WERR(p1, p2) \
(BL_PACKED_HALF(p1) + BL_PACKED_HALF(p2) + BL_HALF_ERR)
Uint32 sum1111, sum1331, sum3113;
// cache p[0] + 3*(p[1] + p[2]) + p[3] in sum1331
// cache p[1] + 3*(p[0] + p[3]) + p[2] in sum3113
sum1331 = BL_SUM (row0[1], row1[0]);
sum3113 = BL_SUM (row0[0], row1[1]);
// cache p[0] + p[1] + p[2] + p[3] in sum1111
sum1111 = BL_SUM_WERR (sum1331, sum3113);
sum1331 = BL_SUM_WERR (sum1331, sum1111);
sum1331 = BL_PACKED_HALF (sum1331);
sum3113 = BL_SUM_WERR (sum3113, sum1111);
sum3113 = BL_PACKED_HALF (sum3113);
// pixel 0 math -- (9*p[0] + 3*(p[1] + p[2]) + p[3]) / 16
dst_p[0] = BL_PACKED_HALF (row0[0]) + sum1331;
// pixel 1 math -- (9*p[1] + 3*(p[0] + p[3]) + p[2]) / 16
dst_p[1] = BL_PACKED_HALF (row0[1]) + sum3113;
// pixel 2 math -- (9*p[2] + 3*(p[0] + p[3]) + p[1]) / 16
dst_p[dlen] = BL_PACKED_HALF (row1[0]) + sum3113;
// pixel 3 math -- (9*p[3] + 3*(p[1] + p[2]) + p[0]) / 16
dst_p[dlen + 1] = BL_PACKED_HALF (row1[1]) + sum1331;
# undef BL_PACKED_HALF
# undef BL_SUM
# undef BL_HALF_ERR
# undef BL_SUM_WERR
}
#endif /* SCALEINT_H_ */

View File

@@ -1,793 +0,0 @@
/*
* Copyright (C) 2005 Alex Volkov (codepro@usa.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef SCALEMMX_H_
#define SCALEMMX_H_
#if !defined(SCALE_)
# error Please define SCALE_(name) before including scalemmx.h
#endif
#if !defined(MSVC_ASM) && !defined(GCC_ASM)
# error Please define target assembler (MSVC_ASM, GCC_ASM) before including scalemmx.h
#endif
// MMX defaults (no Format param)
#undef SCALE_CMPRGB
#define SCALE_CMPRGB(p1, p2) \
SCALE_(GetRGBDelta) (p1, p2)
#undef SCALE_TOYUV
#define SCALE_TOYUV(p) \
SCALE_(RGBtoYUV) (p)
#undef SCALE_CMPYUV
#define SCALE_CMPYUV(p1, p2, toler) \
SCALE_(CmpYUV) (p1, p2, toler)
#undef SCALE_GETY
#define SCALE_GETY(p) \
SCALE_(GetPixY) (p)
// MMX transformation multipliers
extern Uint64 mmx_888to555_mult;
extern Uint64 mmx_Y_mult;
extern Uint64 mmx_U_mult;
extern Uint64 mmx_V_mult;
extern Uint64 mmx_YUV_threshold;
#define USE_YUV_LOOKUP
#if defined(MSVC_ASM)
// MSVC inline assembly versions
#if defined(USE_MOVNTQ)
# define MOVNTQ(addr, val) movntq [addr], val
#else
# define MOVNTQ(addr, val) movq [addr], val
#endif
#if USE_PREFETCH == INTEL_PREFETCH
// using Intel SSE non-temporal prefetch
# define PREFETCH(addr) prefetchnta [addr]
# define HAVE_PREFETCH
#elif USE_PREFETCH == AMD_PREFETCH
// using AMD 3DNOW! prefetch
# define PREFETCH(addr) prefetch [addr]
# define HAVE_PREFETCH
#else
// no prefetch -- too bad for poor MMX-only souls
# define PREFETCH(addr)
# undef HAVE_PREFETCH
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
# pragma warning( disable : 4799 )
#endif
static inline void
SCALE_(PlatInit) (void)
{
__asm
{
// mm0 will be kept == 0 throughout
// 0 is needed for bytes->words unpack instructions
pxor mm0, mm0
}
}
static inline void
SCALE_(PlatDone) (void)
{
// finish with MMX registers and yield them to FPU
__asm
{
emms
}
}
#if defined(HAVE_PREFETCH)
static inline void
SCALE_(Prefetch) (const void* p)
{
__asm
{
mov eax, p
PREFETCH (eax)
}
}
#else /* Not HAVE_PREFETCH */
static inline void
SCALE_(Prefetch) (const void* p)
{
(void)p; // silence compiler
/* no-op */
}
#endif /* HAVE_PREFETCH */
// compute the RGB distance squared between 2 pixels
static inline int
SCALE_(GetRGBDelta) (Uint32 pix1, Uint32 pix2)
{
__asm
{
// load pixels
movd mm1, pix1
punpcklbw mm1, mm0
movd mm2, pix2
punpcklbw mm2, mm0
// get the difference between RGBA components
psubw mm1, mm2
// squared and sumed
pmaddwd mm1, mm1
// finish suming the squares
movq mm2, mm1
punpckhdq mm2, mm0
paddd mm1, mm2
// store result
movd eax, mm1
}
}
// retrieve the Y (intensity) component of pixel's YUV
static inline int
SCALE_(GetPixY) (Uint32 pix)
{
__asm
{
// load pixel
movd mm1, pix
punpcklbw mm1, mm0
// process
pmaddwd mm1, mmx_Y_mult // RGB * Yvec
movq mm2, mm1 // finish suming
punpckhdq mm2, mm0 // ditto
paddd mm1, mm2 // ditto
// store result
movd eax, mm1
shr eax, 14
}
}
#ifdef USE_YUV_LOOKUP
// convert pixel RGB vector into YUV representation vector
static inline YUV_VECTOR
SCALE_(RGBtoYUV) (Uint32 pix)
{
__asm
{
// convert RGB888 to 555
movd mm1, pix
punpcklbw mm1, mm0
psrlw mm1, 3 // 8->5 bit
pmaddwd mm1, mmx_888to555_mult // shuffle into the right channel order
movq mm2, mm1 // finish shuffling
punpckhdq mm2, mm0 // ditto
por mm1, mm2 // ditto
// lookup the YUV vector
movd eax, mm1
mov eax, [RGB15_to_YUV + eax * 4]
}
}
// compare 2 pixels with respect to their YUV representations
// tolerance set by toler arg
// returns true: close; false: distant (-gt toler)
static inline bool
SCALE_(CmpYUV) (Uint32 pix1, Uint32 pix2, int toler)
{
__asm
{
// convert RGB888 to 555
movd mm1, pix1
punpcklbw mm1, mm0
psrlw mm1, 3 // 8->5 bit
movd mm3, pix2
punpcklbw mm3, mm0
psrlw mm3, 3 // 8->5 bit
pmaddwd mm1, mmx_888to555_mult // shuffle into the right channel order
movq mm2, mm1 // finish shuffling
pmaddwd mm3, mmx_888to555_mult // shuffle into the right channel order
movq mm4, mm3 // finish shuffling
punpckhdq mm2, mm0 // ditto
por mm1, mm2 // ditto
punpckhdq mm4, mm0 // ditto
por mm3, mm4 // ditto
// lookup the YUV vector
movd eax, mm1
movd edx, mm3
movd mm1, [RGB15_to_YUV + eax * 4]
movq mm4, mm1
movd mm2, [RGB15_to_YUV + edx * 4]
// get abs difference between YUV components
#ifdef USE_PSADBW
// we can use PSADBW and save us some grief
psadbw mm1, mm2
movd edx, mm1
#else
// no PSADBW -- have to do it the hard way
psubusb mm1, mm2
psubusb mm2, mm4
por mm1, mm2
// sum the differences
// XXX: technically, this produces a MAX diff of 510
// but we do not need anything bigger, currently
movq mm2, mm1
psrlq mm2, 8
paddusb mm1, mm2
psrlq mm2, 8
paddusb mm1, mm2
movd edx, mm1
and edx, 0xff
#endif /* USE_PSADBW */
xor eax, eax
shl edx, 1
cmp edx, toler
// store result
setle al
}
}
#else /* Not USE_YUV_LOOKUP */
// convert pixel RGB vector into YUV representation vector
static inline YUV_VECTOR
SCALE_(RGBtoYUV) (Uint32 pix)
{
__asm
{
movd mm1, pix
punpcklbw mm1, mm0
movq mm2, mm1
// Y vector multiply
pmaddwd mm1, mmx_Y_mult
movq mm4, mm1
punpckhdq mm4, mm0
punpckldq mm1, mm0 // clear out the high dword
paddd mm1, mm4
psrad mm1, 15
movq mm3, mm2
// U vector multiply
pmaddwd mm2, mmx_U_mult
psrad mm2, 10
// V vector multiply
pmaddwd mm3, mmx_V_mult
psrad mm3, 10
// load (1|1|1|1) into mm4
pcmpeqw mm4, mm4
psrlw mm4, 15
packssdw mm3, mm2
pmaddwd mm3, mm4
psrad mm3, 5
// load (64|64) into mm4
punpcklwd mm4, mm0
pslld mm4, 6
paddd mm3, mm4
packssdw mm3, mm1
packuswb mm3, mm0
movd eax, mm3
}
}
// compare 2 pixels with respect to their YUV representations
// tolerance set by toler arg
// returns true: close; false: distant (-gt toler)
static inline bool
SCALE_(CmpYUV) (Uint32 pix1, Uint32 pix2, int toler)
{
__asm
{
movd mm1, pix1
punpcklbw mm1, mm0
movd mm2, pix2
punpcklbw mm2, mm0
psubw mm1, mm2
movq mm2, mm1
// Y vector multiply
pmaddwd mm1, mmx_Y_mult
movq mm4, mm1
punpckhdq mm4, mm0
paddd mm1, mm4
// abs()
movq mm4, mm1
psrad mm4, 31
pxor mm4, mm1
psubd mm1, mm4
movq mm3, mm2
// U vector multiply
pmaddwd mm2, mmx_U_mult
movq mm4, mm2
punpckhdq mm4, mm0
paddd mm2, mm4
// abs()
movq mm4, mm2
psrad mm4, 31
pxor mm4, mm2
psubd mm2, mm4
paddd mm1, mm2
// V vector multiply
pmaddwd mm3, mmx_V_mult
movq mm4, mm3
punpckhdq mm3, mm0
paddd mm3, mm4
// abs()
movq mm4, mm3
psrad mm4, 31
pxor mm4, mm3
psubd mm3, mm4
paddd mm1, mm3
movd edx, mm1
xor eax, eax
shr edx, 14
cmp edx, toler
// store result
setle al
}
}
#endif /* USE_YUV_LOOKUP */
// Check if 2 pixels are different with respect to their
// YUV representations
// returns 0: close; ~0: distant
static inline int
SCALE_(DiffYUV) (Uint32 yuv1, Uint32 yuv2)
{
__asm
{
// load YUV pixels
movd mm1, yuv1
movq mm4, mm1
movd mm2, yuv2
// abs difference between channels
psubusb mm1, mm2
psubusb mm2, mm4
por mm1, mm2
// compare to threshold
psubusb mm1, mmx_YUV_threshold
movd edx, mm1
// transform eax to 0 or ~0
xor eax, eax
or edx, edx
setz al
dec eax
}
}
// bilinear weighted blend of four pixels
// MSVC asm version
static inline void
SCALE_(Blend_bilinear) (const Uint32* row0, const Uint32* row1,
Uint32* dst_p, Uint32 dlen)
{
__asm
{
// EL0: setup vars
mov ebx, row0 // EL0
// EL0: load pixels
movq mm1, [ebx] // EL0
movq mm2, mm1 // EL0: p[1] -> mm2
PREFETCH (ebx + 0x80)
punpckhbw mm2, mm0 // EL0: p[1] -> mm2
mov ebx, row1
punpcklbw mm1, mm0 // EL0: p[0] -> mm1
movq mm3, [ebx]
movq mm4, mm3 // EL0: p[3] -> mm4
movq mm6, mm2 // EL1.1: p[1] -> mm6
PREFETCH (ebx + 0x80)
punpcklbw mm3, mm0 // EL0: p[2] -> mm3
movq mm5, mm1 // EL1.1: p[0] -> mm5
punpckhbw mm4, mm0 // EL0: p[3] -> mm4
mov edi, dst_p // EL0
// EL1: cache p[0] + 3*(p[1] + p[2]) + p[3] in mm6
paddw mm6, mm3 // EL1.2: p[1] + p[2] -> mm6
// EL1: cache p[0] + p[1] + p[2] + p[3] in mm7
movq mm7, mm6 // EL1.3: p[1] + p[2] -> mm7
// EL1: cache p[1] + 3*(p[0] + p[3]) + p[2] in mm5
paddw mm5, mm4 // EL1.2: p[0] + p[3] -> mm5
psllw mm6, 1 // EL1.4: 2*(p[1] + p[2]) -> mm6
paddw mm7, mm5 // EL1.4: sum(p[]) -> mm7
psllw mm5, 1 // EL1.5: 2*(p[0] + p[3]) -> mm5
paddw mm6, mm7 // EL1.5: p[0] + 3*(p[1] + p[2]) + p[3] -> mm6
paddw mm5, mm7 // EL1.6: p[1] + 3*(p[0] + p[3]) + p[2] -> mm5
// EL2: pixel 0 math -- (9*p[0] + 3*(p[1] + p[2]) + p[3]) / 16
psllw mm1, 3 // EL2.1: 8*p[0] -> mm1
paddw mm1, mm6 // EL2.2: 9*p[0] + 3*(p[1] + p[2]) + p[3] -> mm1
psrlw mm1, 4 // EL2.3: sum[0]/16 -> mm1
mov edx, dlen // EL0
// EL3: pixel 1 math -- (9*p[1] + 3*(p[0] + p[3]) + p[2]) / 16
psllw mm2, 3 // EL3.1: 8*p[1] -> mm2
paddw mm2, mm5 // EL3.2: 9*p[1] + 3*(p[0] + p[3]) + p[2] -> mm2
psrlw mm2, 4 // EL3.3: sum[1]/16 -> mm5
// EL2/3: store pixels 0 & 1
packuswb mm1, mm2 // EL2/3: pack into bytes
MOVNTQ (edi, mm1) // EL2/3: store 2 pixels
// EL4: pixel 2 math -- (9*p[2] + 3*(p[0] + p[3]) + p[1]) / 16
psllw mm3, 3 // EL4.1: 8*p[2] -> mm3
paddw mm3, mm5 // EL4.2: 9*p[2] + 3*(p[0] + p[3]) + p[1] -> mm3
psrlw mm3, 4 // EL4.3: sum[2]/16 -> mm3
// EL5: pixel 3 math -- (9*p[3] + 3*(p[1] + p[2]) + p[0]) / 16
psllw mm4, 3 // EL5.1: 8*p[3] -> mm4
paddw mm4, mm6 // EL5.2: 9*p[3] + 3*(p[1] + p[2]) + p[0] -> mm4
psrlw mm4, 4 // EL5.3: sum[3]/16 -> mm4
// EL4/5: store pixels 2 & 3
packuswb mm3, mm4 // EL4/5: pack into bytes
MOVNTQ (edi + edx*4, mm3) // EL4/5: store 2 pixels
}
}
// End MSVC_ASM
#elif defined(GCC_ASM)
// GCC inline assembly versions
#if defined(USE_MOVNTQ)
# define MOVNTQ(val, addr) "movntq " #val "," #addr
#else
# define MOVNTQ(val, addr) "movq " #val "," #addr
#endif
#if USE_PREFETCH == INTEL_PREFETCH
// using Intel SSE non-temporal prefetch
# define PREFETCH(addr) "prefetchnta " #addr
#elif USE_PREFETCH == AMD_PREFETCH
// using AMD 3DNOW! prefetch
# define PREFETCH(addr) "prefetch " #addr
#else
// no prefetch -- too bad for poor MMX-only souls
# define PREFETCH(addr)
#endif
#if defined(__x86_64__)
# define A_REG "rax"
# define D_REG "rdx"
# define CLR_UPPER32(r) "xor " "%%" r "," "%%" r
#else
# define A_REG "eax"
# define D_REG "edx"
# define CLR_UPPER32(r)
#endif
static inline void
SCALE_(PlatInit) (void)
{
__asm__ (
// mm0 will be kept == 0 throughout
// 0 is needed for bytes->words unpack instructions
"pxor %%mm0, %%mm0 \n\t"
: /* nothing */
: /* nothing */
);
}
static inline void
SCALE_(PlatDone) (void)
{
// finish with MMX registers and yield them to FPU
__asm__ (
"emms \n\t"
: /* nothing */ : /* nothing */
);
}
static inline void
SCALE_(Prefetch) (const void* p)
{
__asm__ __volatile__ ("" PREFETCH (%0) : /*nothing*/ : "m" (p) );
}
// compute the RGB distance squared between 2 pixels
static inline int
SCALE_(GetRGBDelta) (Uint32 pix1, Uint32 pix2)
{
int res;
__asm__ (
// load pixels
"movd %1, %%mm1 \n\t"
"punpcklbw %%mm0, %%mm1 \n\t"
"movd %2, %%mm2 \n\t"
"punpcklbw %%mm0, %%mm2 \n\t"
// get the difference between RGBA components
"psubw %%mm2, %%mm1 \n\t"
// squared and sumed
"pmaddwd %%mm1, %%mm1 \n\t"
// finish suming the squares
"movq %%mm1, %%mm2 \n\t"
"punpckhdq %%mm0, %%mm2 \n\t"
"paddd %%mm2, %%mm1 \n\t"
// store result
"movd %%mm1, %0 \n\t"
: /*0*/"=rm" (res)
: /*1*/"rm" (pix1), /*2*/"rm" (pix2)
);
return res;
}
// retrieve the Y (intensity) component of pixel's YUV
static inline int
SCALE_(GetPixY) (Uint32 pix)
{
int ret;
__asm__ (
// load pixel
"movd %1, %%mm1 \n\t"
"punpcklbw %%mm0, %%mm1 \n\t"
// process
"pmaddwd %2, %%mm1 \n\t" // R,G,B * Yvec
"movq %%mm1, %%mm2 \n\t" // finish suming
"punpckhdq %%mm0, %%mm2 \n\t" // ditto
"paddd %%mm2, %%mm1 \n\t" // ditto
// store index
"movd %%mm1, %0 \n\t"
: /*0*/"=r" (ret)
: /*1*/"rm" (pix), /*2*/"m" (mmx_Y_mult)
);
return ret >> 14;
}
#ifdef USE_YUV_LOOKUP
// convert pixel RGB vector into YUV representation vector
static inline YUV_VECTOR
SCALE_(RGBtoYUV) (Uint32 pix)
{
int i;
__asm__ (
// convert RGB888 to 555
"movd %1, %%mm1 \n\t"
"punpcklbw %%mm0, %%mm1 \n\t"
"psrlw $3, %%mm1 \n\t" // 8->5 bit
"pmaddwd %2, %%mm1 \n\t" // shuffle into the right channel order
"movq %%mm1, %%mm2 \n\t" // finish shuffling
"punpckhdq %%mm0, %%mm2 \n\t" // ditto
"por %%mm2, %%mm1 \n\t" // ditto
"movd %%mm1, %0 \n\t"
: /*0*/"=rm" (i)
: /*1*/"rm" (pix), /*2*/"m" (mmx_888to555_mult)
);
return RGB15_to_YUV[i];
}
// compare 2 pixels with respect to their YUV representations
// tolerance set by toler arg
// returns true: close; false: distant (-gt toler)
static inline bool
SCALE_(CmpYUV) (Uint32 pix1, Uint32 pix2, int toler)
{
int delta;
__asm__ (
"movd %1, %%mm1 \n\t"
"movd %2, %%mm3 \n\t"
// convert RGB888 to 555
// this is somewhat parallelized
"punpcklbw %%mm0, %%mm1 \n\t"
CLR_UPPER32 (A_REG) "\n\t"
"psrlw $3, %%mm1 \n\t" // 8->5 bit
"punpcklbw %%mm0, %%mm3 \n\t"
"psrlw $3, %%mm3 \n\t" // 8->5 bit
"pmaddwd %4, %%mm1 \n\t" // shuffle into the right channel order
"movq %%mm1, %%mm2 \n\t" // finish shuffling
"pmaddwd %4, %%mm3 \n\t" // shuffle into the right channel order
CLR_UPPER32 (D_REG) "\n\t"
"movq %%mm3, %%mm4 \n\t" // finish shuffling
"punpckhdq %%mm0, %%mm2 \n\t" // ditto
"por %%mm2, %%mm1 \n\t" // ditto
"punpckhdq %%mm0, %%mm4 \n\t" // ditto
"por %%mm4, %%mm3 \n\t" // ditto
// lookup the YUV vector
"movd %%mm1, %%eax \n\t"
"movd %%mm3, %%edx \n\t"
"movd (%3, %%" A_REG ", 4), %%mm1 \n\t"
"movq %%mm1, %%mm4 \n\t"
"movd (%3, %%" D_REG ", 4), %%mm2 \n\t"
// get abs difference between YUV components
#ifdef USE_PSADBW
// we can use PSADBW and save us some grief
"psadbw %%mm2, %%mm1 \n\t"
"movd %%mm1, %0 \n\t"
#else
// no PSADBW -- have to do it the hard way
"psubusb %%mm2, %%mm1 \n\t"
"psubusb %%mm4, %%mm2 \n\t"
"por %%mm2, %%mm1 \n\t"
// sum the differences
// technically, this produces a MAX diff of 510
// but we do not need anything bigger, currently
"movq %%mm1, %%mm2 \n\t"
"psrlq $8, %%mm2 \n\t"
"paddusb %%mm2, %%mm1 \n\t"
"psrlq $8, %%mm2 \n\t"
"paddusb %%mm2, %%mm1 \n\t"
// store intermediate delta
"movd %%mm1, %0 \n\t"
"andl $0xff, %0 \n\t"
#endif /* USE_PSADBW */
: /*0*/"=rm" (delta)
: /*1*/"rm" (pix1), /*2*/"rm" (pix2),
/*3*/ "r" (RGB15_to_YUV),
/*4*/"m" (mmx_888to555_mult)
: "%" A_REG, "%" D_REG, "cc"
);
return (delta << 1) <= toler;
}
#endif /* USE_YUV_LOOKUP */
// Check if 2 pixels are different with respect to their
// YUV representations
// returns 0: close; ~0: distant
static inline int
SCALE_(DiffYUV) (Uint32 yuv1, Uint32 yuv2)
{
sint32 ret;
__asm__ (
// load YUV pixels
"movd %1, %%mm1 \n\t"
"movq %%mm1, %%mm4 \n\t"
"movd %2, %%mm2 \n\t"
// abs difference between channels
"psubusb %%mm2, %%mm1 \n\t"
"psubusb %%mm4, %%mm2 \n\t"
CLR_UPPER32(D_REG) "\n\t"
"por %%mm2, %%mm1 \n\t"
// compare to threshold
"psubusb %3, %%mm1 \n\t"
"movd %%mm1, %%edx \n\t"
// transform eax to 0 or ~0
"xor %%" A_REG ", %%" A_REG "\n\t"
"or %%" D_REG ", %%" D_REG "\n\t"
"setz %%al \n\t"
"dec %%" A_REG " \n\t"
: /*0*/"=a" (ret)
: /*1*/"rm" (yuv1), /*2*/"rm" (yuv2),
/*3*/"m" (mmx_YUV_threshold)
: "%" D_REG, "cc"
);
return ret;
}
// Bilinear weighted blend of four pixels
// Function produces 4 blended pixels (in 2x2 matrix) and writes them
// out to the surface
// Last version
static inline void
SCALE_(Blend_bilinear) (const Uint32* row0, const Uint32* row1,
Uint32* dst_p, Uint32 dlen)
{
__asm__ (
// EL0: load pixels
"movq %0, %%mm1 \n\t" // EL0
"movq %%mm1, %%mm2 \n\t" // EL0: p[1] -> mm2
PREFETCH (0x80%0) "\n\t"
"punpckhbw %%mm0, %%mm2 \n\t" // EL0: p[1] -> mm2
"punpcklbw %%mm0, %%mm1 \n\t" // EL0: p[0] -> mm1
"movq %1, %%mm3 \n\t"
"movq %%mm3, %%mm4 \n\t" // EL0: p[3] -> mm4
"movq %%mm2, %%mm6 \n\t" // EL1.1: p[1] -> mm6
PREFETCH (0x80%1) "\n\t"
"punpcklbw %%mm0, %%mm3 \n\t" // EL0: p[2] -> mm3
"movq %%mm1, %%mm5 \n\t" // EL1.1: p[0] -> mm5
"punpckhbw %%mm0, %%mm4 \n\t" // EL0: p[3] -> mm4
// EL1: cache p[0] + 3*(p[1] + p[2]) + p[3] in mm6
"paddw %%mm3, %%mm6 \n\t" // EL1.2: p[1] + p[2] -> mm6
// EL1: cache p[0] + p[1] + p[2] + p[3] in mm7
"movq %%mm6, %%mm7 \n\t" // EL1.3: p[1] + p[2] -> mm7
// EL1: cache p[1] + 3*(p[0] + p[3]) + p[2] in mm5
"paddw %%mm4, %%mm5 \n\t" // EL1.2: p[0] + p[3] -> mm5
"psllw $1, %%mm6 \n\t" // EL1.4: 2*(p[1] + p[2]) -> mm6
"paddw %%mm5, %%mm7 \n\t" // EL1.4: sum(p[]) -> mm7
"psllw $1, %%mm5 \n\t" // EL1.5: 2*(p[0] + p[3]) -> mm5
"paddw %%mm7, %%mm6 \n\t" // EL1.5: p[0] + 3*(p[1] + p[2]) + p[3] -> mm6
"paddw %%mm7, %%mm5 \n\t" // EL1.6: p[1] + 3*(p[0] + p[3]) + p[2] -> mm5
// EL2: pixel 0 math -- (9*p[0] + 3*(p[1] + p[2]) + p[3]) / 16
"psllw $3, %%mm1 \n\t" // EL2.1: 8*p[0] -> mm1
"paddw %%mm6, %%mm1 \n\t" // EL2.2: 9*p[0] + 3*(p[1] + p[2]) + p[3] -> mm1
"psrlw $4, %%mm1 \n\t" // EL2.3: sum[0]/16 -> mm1
// EL3: pixel 1 math -- (9*p[1] + 3*(p[0] + p[3]) + p[2]) / 16
"psllw $3, %%mm2 \n\t" // EL3.1: 8*p[1] -> mm2
"paddw %%mm5, %%mm2 \n\t" // EL3.2: 9*p[1] + 3*(p[0] + p[3]) + p[2] -> mm5
"psrlw $4, %%mm2 \n\t" // EL3.3: sum[1]/16 -> mm5
// EL2/4: store pixels 0 & 1
"packuswb %%mm2, %%mm1 \n\t" // EL2/4: pack into bytes
MOVNTQ (%%mm1, (%2)) "\n\t" // EL2/4: store 2 pixels
// EL4: pixel 2 math -- (9*p[2] + 3*(p[0] + p[3]) + p[1]) / 16
"psllw $3, %%mm3 \n\t" // EL4.1: 8*p[2] -> mm3
"paddw %%mm5, %%mm3 \n\t" // EL4.2: 9*p[2] + 3*(p[0] + p[3]) + p[1] -> mm3
"psrlw $4, %%mm3 \n\t" // EL4.3: sum[2]/16 -> mm3
// EL5: pixel 3 math -- (9*p[3] + 3*(p[1] + p[2]) + p[0]) / 16
"psllw $3, %%mm4 \n\t" // EL5.1: 8*p[3] -> mm4
"paddw %%mm6, %%mm4 \n\t" // EL5.2: 9*p[3] + 3*(p[1] + p[2]) + p[0] -> mm4
"psrlw $4, %%mm4 \n\t" // EL5.3: sum[3]/16 -> mm4
// EL4/5: store pixels 2 & 3
"packuswb %%mm4, %%mm3 \n\t" // EL4/5: pack into bytes
MOVNTQ (%%mm3, (%2,%3,4)) "\n\t" // EL4/5: store 2 pixels
: /* nothing */
: /*0*/"m" (*row0), /*1*/"m" (*row1), /*2*/"r" (dst_p),
/*3*/"r" ((unsigned long)dlen) /* 'long' is for proper reg alloc on amd64 */
: "memory"
);
}
#undef A_REG
#undef D_REG
#undef CLR_UPPER32
#endif // GCC_ASM
#endif /* SCALEMMX_H_ */

View File

@@ -1,286 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "types.h"
#include "libs/graphics/sdl/sdl_common.h"
#include "libs/platform.h"
#include "libs/log.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
#ifdef USE_PLATFORM_ACCEL
# ifndef __APPLE__
// MacOS X framework has no SDL_cpuinfo.h for some reason
# include SDL_INCLUDE(SDL_cpuinfo.h)
# endif
# ifdef MMX_ASM
# include "2xscalers_mmx.h"
# endif /* MMX_ASM */
#endif /* USE_PLATFORM_ACCEL */
typedef enum
{
SCALEPLAT_NULL = PLATFORM_NULL,
SCALEPLAT_C = PLATFORM_C,
SCALEPLAT_MMX = PLATFORM_MMX,
SCALEPLAT_SSE = PLATFORM_SSE,
SCALEPLAT_3DNOW = PLATFORM_3DNOW,
SCALEPLAT_ALTIVEC = PLATFORM_ALTIVEC,
SCALEPLAT_C_RGBA,
SCALEPLAT_C_BGRA,
SCALEPLAT_C_ARGB,
SCALEPLAT_C_ABGR,
} Scale_PlatType_t;
// RGB -> YUV transformation
// the RGB vector is multiplied by the transformation matrix
// to get the YUV vector
#if 0
// original table -- not used
const int YUV_matrix[3][3] =
{
/* Y U V */
/* R */ {0.2989, -0.1687, 0.5000},
/* G */ {0.5867, -0.3312, -0.4183},
/* B */ {0.1144, 0.5000, -0.0816}
};
#else
// scaled up by a 2^14 factor, with Y doubled
const int YUV_matrix[3][3] =
{
/* Y U V */
/* R */ { 9794, -2764, 8192},
/* G */ {19224, -5428, -6853},
/* B */ { 3749, 8192, -1339}
};
#endif
// pre-computed transformations for 8 bits per channel
int RGB_to_YUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 256];
sint16 dRGB_to_dYUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 512];
// pre-computed transformations for RGB555
YUV_VECTOR RGB15_to_YUV[0x8000];
PLATFORM_TYPE force_platform = PLATFORM_NULL;
Scale_PlatType_t Scale_Platform = SCALEPLAT_NULL;
// pre-compute the RGB->YUV transformations
void
Scale_Init (void)
{
int i1, i2, i3;
for (i1 = 0; i1 < 3; i1++) // enum R,G,B
for (i2 = 0; i2 < 3; i2++) // enum Y,U,V
for (i3 = 0; i3 < 256; i3++) // enum possible channel vals
{
RGB_to_YUV[i1][i2][i3] =
(YUV_matrix[i1][i2] * i3) >> 14;
}
for (i1 = 0; i1 < 3; i1++) // enum R,G,B
for (i2 = 0; i2 < 3; i2++) // enum Y,U,V
for (i3 = -255; i3 < 256; i3++) // enum possible channel delta vals
{
dRGB_to_dYUV[i1][i2][i3 + 255] =
(YUV_matrix[i1][i2] * i3) >> 14;
}
for (i1 = 0; i1 < 32; ++i1)
for (i2 = 0; i2 < 32; ++i2)
for (i3 = 0; i3 < 32; ++i3)
{
int y, u, v;
// adding upper bits halved for error correction
int r = (i1 << 3) | (i1 >> 3);
int g = (i2 << 3) | (i2 >> 3);
int b = (i3 << 3) | (i3 >> 3);
y = ( r * YUV_matrix[YUV_XFORM_R][YUV_XFORM_Y]
+ g * YUV_matrix[YUV_XFORM_G][YUV_XFORM_Y]
+ b * YUV_matrix[YUV_XFORM_B][YUV_XFORM_Y]
) >> 15; // we dont need Y doubled, need Y to fit 8 bits
// U and V are half the importance of Y
u = 64+(( r * YUV_matrix[YUV_XFORM_R][YUV_XFORM_U]
+ g * YUV_matrix[YUV_XFORM_G][YUV_XFORM_U]
+ b * YUV_matrix[YUV_XFORM_B][YUV_XFORM_U]
) >> 15); // halved
v = 64+(( r * YUV_matrix[YUV_XFORM_R][YUV_XFORM_V]
+ g * YUV_matrix[YUV_XFORM_G][YUV_XFORM_V]
+ b * YUV_matrix[YUV_XFORM_B][YUV_XFORM_V]
) >> 15); // halved
RGB15_to_YUV[(i1 << 10) | (i2 << 5) | i3] = (y << 16) | (u << 8) | v;
}
}
// expands the given rectangle in all directions by 'expansion'
// guarded by 'limits'
void
Scale_ExpandRect (SDL_Rect* rect, int expansion, const SDL_Rect* limits)
{
if (rect->x - expansion >= limits->x)
{
rect->w += expansion;
rect->x -= expansion;
}
else
{
rect->w += rect->x - limits->x;
rect->x = limits->x;
}
if (rect->y - expansion >= limits->y)
{
rect->h += expansion;
rect->y -= expansion;
}
else
{
rect->h += rect->y - limits->y;
rect->y = limits->y;
}
if (rect->x + rect->w + expansion <= limits->w)
rect->w += expansion;
else
rect->w = limits->w - rect->x;
if (rect->y + rect->h + expansion <= limits->h)
rect->h += expansion;
else
rect->h = limits->h - rect->y;
}
// Platform+Scaler function lookups
typedef struct
{
Scale_PlatType_t platform;
const Scale_FuncDef_t* funcdefs;
} Scale_PlatDef_t;
static const Scale_PlatDef_t
Scale_PlatDefs[] =
{
#if defined(MMX_ASM)
{SCALEPLAT_SSE, Scale_SSE_Functions},
{SCALEPLAT_3DNOW, Scale_3DNow_Functions},
{SCALEPLAT_MMX, Scale_MMX_Functions},
#endif /* MMX_ASM */
// Default
{SCALEPLAT_NULL, Scale_C_Functions}
};
TFB_ScaleFunc
Scale_PrepPlatform (int flags, const SDL_PixelFormat* fmt)
{
const Scale_PlatDef_t* pdef;
const Scale_FuncDef_t* fdef;
(void)flags;
Scale_Platform = SCALEPLAT_NULL;
// first match wins
// add better platform techs to the top
#ifdef MMX_ASM
if ( (!force_platform && (SDL_HasSSE () || SDL_HasMMXExt ()))
|| force_platform == SCALEPLAT_SSE)
{
log_add (log_Info, "Screen scalers are using SSE/MMX-Ext/MMX code");
Scale_Platform = SCALEPLAT_SSE;
Scale_SSE_PrepPlatform (fmt);
}
else
if ( (!force_platform && SDL_HasAltiVec ())
|| force_platform == SCALEPLAT_ALTIVEC)
{
log_add (log_Info, "Screen scalers would use AltiVec code "
"if someone actually wrote it");
//Scale_Platform = SCALEPLAT_ALTIVEC;
}
else
if ( (!force_platform && SDL_Has3DNow ())
|| force_platform == SCALEPLAT_3DNOW)
{
log_add (log_Info, "Screen scalers are using 3DNow/MMX code");
Scale_Platform = SCALEPLAT_3DNOW;
Scale_3DNow_PrepPlatform (fmt);
}
else
if ( (!force_platform && SDL_HasMMX ())
|| force_platform == SCALEPLAT_MMX)
{
log_add (log_Info, "Screen scalers are using MMX code");
Scale_Platform = SCALEPLAT_MMX;
Scale_MMX_PrepPlatform (fmt);
}
#endif
if (Scale_Platform == SCALEPLAT_NULL)
{ // Plain C versions
if (fmt->Rmask == 0xff000000 && fmt->Bmask == 0x0000ff00)
Scale_Platform = SCALEPLAT_C_RGBA;
else if (fmt->Rmask == 0x00ff0000 && fmt->Bmask == 0x000000ff)
Scale_Platform = SCALEPLAT_C_ARGB;
else if (fmt->Rmask == 0x0000ff00 && fmt->Bmask == 0xff000000)
Scale_Platform = SCALEPLAT_C_BGRA;
else if (fmt->Rmask == 0x000000ff && fmt->Bmask == 0x00ff0000)
Scale_Platform = SCALEPLAT_C_ABGR;
else
{ // use slowest default
log_add (log_Warning, "Scale_PrepPlatform(): unknown masks "
"(Red %08x, Blue %08x)", fmt->Rmask, fmt->Bmask);
Scale_Platform = SCALEPLAT_C;
}
if (Scale_Platform == SCALEPLAT_C)
log_add (log_Info, "Screen scalers are using slow generic C code");
else
log_add (log_Info, "Screen scalers are using optimized C code");
}
// Lookup the scaling function
// First find the right platform
for (pdef = Scale_PlatDefs;
pdef->platform != Scale_Platform && pdef->platform != SCALEPLAT_NULL;
++pdef)
;
// Next find the right function
for (fdef = pdef->funcdefs;
(flags & fdef->flag) != fdef->flag;
++fdef)
;
return fdef->func;
}

View File

@@ -1,27 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef SCALERS_H_
#define SCALERS_H_
void Scale_Init (void);
typedef void (* TFB_ScaleFunc) (SDL_Surface *src, SDL_Surface *dst,
SDL_Rect *r);
TFB_ScaleFunc Scale_PrepPlatform (int flags, const SDL_PixelFormat* fmt);
#endif /* SCALERS_H_ */

View File

@@ -1,629 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "sdl_common.h"
#include "opengl.h"
#include "pure.h"
#include "primitives.h"
#include "options.h"
#include "uqmversion.h"
#include "libs/graphics/drawcmd.h"
#include "libs/graphics/dcqueue.h"
#include "libs/graphics/cmap.h"
#include "libs/input/sdl/input.h"
// for ProcessInputEvent()
#include "libs/graphics/bbox.h"
#include "port.h"
#include "libs/uio.h"
#include "libs/log.h"
#include "libs/memlib.h"
#include "libs/vidlib.h"
#include SDL_INCLUDE(SDL_thread.h)
SDL_Surface *SDL_Video;
SDL_Surface *SDL_Screen;
SDL_Surface *TransitionScreen;
SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS];
SDL_Surface *format_conv_surf = NULL;
static volatile BOOLEAN abortFlag = FALSE;
int GfxFlags = 0;
TFB_GRAPHICS_BACKEND *graphics_backend = NULL;
volatile int QuitPosted = 0;
volatile int GameActive = 1; // Track the SDL_ACTIVEEVENT state SDL_APPACTIVE
#ifdef ANDROID
extern void ResumeMusic (void);
extern void PauseMusic (void);
void AndroidGamePaused()
{
GameActive = 0;
SDL_ANDROID_PauseAudioPlayback();
PauseMusic();
}
void AndroidGameResumed()
{
GameActive = 1;
SDL_ANDROID_ResumeAudioPlayback();
ResumeMusic();
}
#endif
void
TFB_PreInit (void)
{
log_add (log_Info, "Initializing base SDL functionality.");
log_add (log_Info, "Using SDL version %d.%d.%d (compiled with "
"%d.%d.%d)", SDL_Linked_Version ()->major,
SDL_Linked_Version ()->minor, SDL_Linked_Version ()->patch,
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
#if 0
if (SDL_Linked_Version ()->major != SDL_MAJOR_VERSION ||
SDL_Linked_Version ()->minor != SDL_MINOR_VERSION ||
SDL_Linked_Version ()->patch != SDL_PATCHLEVEL) {
log_add (log_Warning, "The used SDL library is not the same version "
"as the one used to compile The Ur-Quan Masters with! "
"If you experience any crashes, this would be an excellent "
"suspect.");
}
#endif
if ((SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) == -1))
{
log_add (log_Fatal, "Could not initialize SDL: %s.", SDL_GetError ());
exit (EXIT_FAILURE);
}
#ifdef ANDROID
SDL_ANDROID_SetApplicationPutToBackgroundCallback(&AndroidGamePaused, &AndroidGameResumed);
#endif
}
int
TFB_ReInitGraphics (int driver, int flags, int width, int height)
{
int result;
int togglefullscreen = 0;
char caption[200];
if (GfxFlags == (flags ^ TFB_GFXFLAGS_FULLSCREEN) &&
driver == GraphicsDriver &&
width == ScreenWidthActual && height == ScreenHeightActual)
{
togglefullscreen = 1;
}
GfxFlags = flags;
if (driver == TFB_GFXDRIVER_SDL_OPENGL)
{
#ifdef HAVE_OPENGL
result = TFB_GL_ConfigureVideo (driver, flags, width, height,
togglefullscreen);
#else
driver = TFB_GFXDRIVER_SDL_PURE;
log_add (log_Warning, "OpenGL support not compiled in,"
" so using pure SDL driver");
result = TFB_Pure_ConfigureVideo (driver, flags, width, height,
togglefullscreen);
#endif
}
else
{
result = TFB_Pure_ConfigureVideo (driver, flags, width, height,
togglefullscreen);
}
sprintf (caption, "The Ur-Quan Masters v%d.%d.%d%s",
UQM_MAJOR_VERSION, UQM_MINOR_VERSION,
UQM_PATCH_VERSION, UQM_EXTRA_VERSION);
SDL_WM_SetCaption (caption, NULL);
if (flags & TFB_GFXFLAGS_FULLSCREEN)
SDL_ShowCursor (SDL_DISABLE);
else
SDL_ShowCursor (SDL_ENABLE);
return result;
}
int
TFB_InitGraphics (int driver, int flags, int width, int height)
{
int result, i;
char caption[200];
/* Null out screen pointers the first time */
for (i = 0; i < TFB_GFX_NUMSCREENS; i++)
{
SDL_Screens[i] = NULL;
}
GfxFlags = flags;
if (driver == TFB_GFXDRIVER_SDL_OPENGL)
{
#ifdef HAVE_OPENGL
result = TFB_GL_InitGraphics (driver, flags, width, height);
#else
driver = TFB_GFXDRIVER_SDL_PURE;
log_add (log_Warning, "OpenGL support not compiled in,"
" so using pure SDL driver");
result = TFB_Pure_InitGraphics (driver, flags, width, height);
#endif
}
else
{
result = TFB_Pure_InitGraphics (driver, flags, width, height);
}
sprintf (caption, "The Ur-Quan Masters v%d.%d.%d%s",
UQM_MAJOR_VERSION, UQM_MINOR_VERSION,
UQM_PATCH_VERSION, UQM_EXTRA_VERSION);
SDL_WM_SetCaption (caption, NULL);
if (flags & TFB_GFXFLAGS_FULLSCREEN)
SDL_ShowCursor (SDL_DISABLE);
Init_DrawCommandQueue ();
TFB_DrawCanvas_Initialize ();
atexit (TFB_UninitGraphics);
return 0;
}
void
TFB_UninitGraphics (void)
{
Uninit_DrawCommandQueue ();
// TODO: Uninit whatever the drivers have set up for us
SDL_Quit ();
}
void
TFB_ProcessEvents ()
{
SDL_Event Event;
while (SDL_PollEvent (&Event))
{
/* Run through the InputEvent filter. */
ProcessInputEvent (&Event);
/* Handle graphics and exposure events. */
switch (Event.type) {
case SDL_ACTIVEEVENT: /* Lose/gain visibility or focus */
/* Up to three different state changes can occur in one event. */
/* Here, disregard least significant change (mouse focus). */
#if 0 /* Currently disabled in mainline */
// This controls the automatic sleep/pause when minimized.
// On small displays (e.g. mobile devices), APPINPUTFOCUS would
// be an appropriate substitution for APPACTIVE:
// if (Event.active.state & SDL_APPINPUTFOCUS)
if (Event.active.state & SDL_APPACTIVE)
GameActive = Event.active.gain;
#endif
break;
case SDL_QUIT:
QuitPosted = 1;
break;
case SDL_VIDEORESIZE: /* User resized video mode */
// TODO
break;
case SDL_VIDEOEXPOSE: /* Screen needs to be redrawn */
TFB_SwapBuffers (TFB_REDRAW_EXPOSE);
break;
default:
break;
}
}
}
static BOOLEAN system_box_active = 0;
static SDL_Rect system_box;
void
SetSystemRect (const RECT *r)
{
system_box_active = TRUE;
system_box.x = r->corner.x;
system_box.y = r->corner.y;
system_box.w = r->extent.width;
system_box.h = r->extent.height;
}
void
ClearSystemRect (void)
{
system_box_active = FALSE;
}
void
TFB_SwapBuffers (int force_full_redraw)
{
static int last_fade_amount = 255, last_transition_amount = 255;
static int fade_amount = 255, transition_amount = 255;
fade_amount = GetFadeAmount ();
transition_amount = TransitionAmount;
if (force_full_redraw == TFB_REDRAW_NO && !TFB_BBox.valid &&
fade_amount == 255 && transition_amount == 255 &&
last_fade_amount == 255 && last_transition_amount == 255)
return;
if (force_full_redraw == TFB_REDRAW_NO &&
(fade_amount != 255 || transition_amount != 255 ||
last_fade_amount != 255 || last_transition_amount != 255))
force_full_redraw = TFB_REDRAW_FADING;
last_fade_amount = fade_amount;
last_transition_amount = transition_amount;
graphics_backend->preprocess (force_full_redraw, transition_amount,
fade_amount);
graphics_backend->screen (TFB_SCREEN_MAIN, 255, NULL);
if (transition_amount != 255)
{
SDL_Rect r;
r.x = TransitionClipRect.corner.x;
r.y = TransitionClipRect.corner.y;
r.w = TransitionClipRect.extent.width;
r.h = TransitionClipRect.extent.height;
graphics_backend->screen (TFB_SCREEN_TRANSITION,
255 - transition_amount, &r);
}
if (fade_amount != 255)
{
if (fade_amount < 255)
{
graphics_backend->color (0, 0, 0, 255 - fade_amount, NULL);
}
else
{
graphics_backend->color (255, 255, 255,
fade_amount - 255, NULL);
}
}
if (system_box_active)
{
graphics_backend->screen (TFB_SCREEN_MAIN, 255, &system_box);
}
graphics_backend->postprocess ();
}
/* Probably ought to clean this away at some point. */
SDL_Surface *
TFB_DisplayFormatAlpha (SDL_Surface *surface)
{
SDL_Surface* newsurf;
SDL_PixelFormat* dstfmt;
const SDL_PixelFormat* srcfmt = surface->format;
// figure out what format to use (alpha/no alpha)
if (surface->format->Amask)
dstfmt = format_conv_surf->format;
else
dstfmt = SDL_Screen->format;
if (srcfmt->BytesPerPixel == dstfmt->BytesPerPixel &&
srcfmt->Rmask == dstfmt->Rmask &&
srcfmt->Gmask == dstfmt->Gmask &&
srcfmt->Bmask == dstfmt->Bmask &&
srcfmt->Amask == dstfmt->Amask)
return surface; // no conversion needed
newsurf = SDL_ConvertSurface (surface, dstfmt, surface->flags);
// SDL_SRCCOLORKEY and SDL_SRCALPHA cannot work at the same time,
// so we need to disable one of them
if ((surface->flags & SDL_SRCCOLORKEY) && newsurf
&& (newsurf->flags & SDL_SRCCOLORKEY)
&& (newsurf->flags & SDL_SRCALPHA))
SDL_SetAlpha (newsurf, 0, 255);
return newsurf;
}
// This function should only be called from the graphics thread,
// like from a TFB_DrawCommand_Callback command.
TFB_Canvas
TFB_GetScreenCanvas (SCREEN screen)
{
return SDL_Screens[screen];
}
void
TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
SDL_Rect *dstrect, int blend_numer, int blend_denom)
{
BOOLEAN has_colorkey;
int x, y, x1, y1, x2, y2, dst_x2, dst_y2, nr, ng, nb;
int srcx, srcy, w, h;
Uint8 sr, sg, sb, dr, dg, db;
Uint32 src_pixval, dst_pixval, colorkey;
GetPixelFn src_getpix, dst_getpix;
PutPixelFn putpix;
SDL_Rect fulldst;
if (blend_numer == blend_denom)
{
// normal blit: dst = src
// log_add (log_Debug, "normal blit\n");
SDL_BlitSurface (src, srcrect, dst, dstrect);
return;
}
// NOTE: following clipping code is copied from SDL-1.2.4 sources
// If the destination rectangle is NULL, use the entire dest surface
if (dstrect == NULL)
{
fulldst.x = fulldst.y = 0;
dstrect = &fulldst;
}
// clip the source rectangle to the source surface
if (srcrect)
{
int maxw, maxh;
srcx = srcrect->x;
w = srcrect->w;
if (srcx < 0)
{
w += srcx;
dstrect->x -= srcx;
srcx = 0;
}
maxw = src->w - srcx;
if (maxw < w)
w = maxw;
srcy = srcrect->y;
h = srcrect->h;
if (srcy < 0)
{
h += srcy;
dstrect->y -= srcy;
srcy = 0;
}
maxh = src->h - srcy;
if (maxh < h)
h = maxh;
}
else
{
srcx = 0;
srcy = 0;
w = src->w;
h = src->h;
}
// clip the destination rectangle against the clip rectangle
{
SDL_Rect *clip = &dst->clip_rect;
int dx, dy;
dx = clip->x - dstrect->x;
if (dx > 0)
{
w -= dx;
dstrect->x += dx;
srcx += dx;
}
dx = dstrect->x + w - clip->x - clip->w;
if (dx > 0)
w -= dx;
dy = clip->y - dstrect->y;
if (dy > 0)
{
h -= dy;
dstrect->y += dy;
srcy += dy;
}
dy = dstrect->y + h - clip->y - clip->h;
if (dy > 0)
h -= dy;
}
dstrect->w = w;
dstrect->h = h;
if (w <= 0 || h <= 0)
return;
x1 = srcx;
y1 = srcy;
x2 = srcx + w;
y2 = srcy + h;
if (src->flags & SDL_SRCCOLORKEY)
{
has_colorkey = TRUE;
colorkey = src->format->colorkey;
}
else
{
has_colorkey = FALSE;
colorkey = 0; /* Satisfying compiler */
}
src_getpix = getpixel_for (src);
dst_getpix = getpixel_for (dst);
putpix = putpixel_for (dst);
if (blend_denom < 0)
{
// additive blit: dst = src + dst
#if 0
log_add (log_Debug, "additive blit %d %d, src %d %d %d %d dst %d %d,"
" srcbpp %d", blend_numer, blend_denom, x1, y1, x2, y2,
dstrect->x, dstrect->y, src->format->BitsPerPixel);
#endif
for (y = y1; y < y2; ++y)
{
dst_y2 = dstrect->y + (y - y1);
for (x = x1; x < x2; ++x)
{
dst_x2 = dstrect->x + (x - x1);
src_pixval = src_getpix (src, x, y);
if (has_colorkey && src_pixval == colorkey)
continue;
dst_pixval = dst_getpix (dst, dst_x2, dst_y2);
SDL_GetRGB (src_pixval, src->format, &sr, &sg, &sb);
SDL_GetRGB (dst_pixval, dst->format, &dr, &dg, &db);
nr = sr + dr;
ng = sg + dg;
nb = sb + db;
if (nr > 255)
nr = 255;
if (ng > 255)
ng = 255;
if (nb > 255)
nb = 255;
putpix (dst, dst_x2, dst_y2,
SDL_MapRGB (dst->format, nr, ng, nb));
}
}
}
else if (blend_numer < 0)
{
// subtractive blit: dst = src - dst
#if 0
log_add (log_Debug, "subtractive blit %d %d, src %d %d %d %d"
" dst %d %d, srcbpp %d", blend_numer, blend_denom,
x1, y1, x2, y2, dstrect->x, dstrect->y,
src->format->BitsPerPixel);
#endif
for (y = y1; y < y2; ++y)
{
dst_y2 = dstrect->y + (y - y1);
for (x = x1; x < x2; ++x)
{
dst_x2 = dstrect->x + (x - x1);
src_pixval = src_getpix (src, x, y);
if (has_colorkey && src_pixval == colorkey)
continue;
dst_pixval = dst_getpix (dst, dst_x2, dst_y2);
SDL_GetRGB (src_pixval, src->format, &sr, &sg, &sb);
SDL_GetRGB (dst_pixval, dst->format, &dr, &dg, &db);
nr = sr - dr;
ng = sg - dg;
nb = sb - db;
if (nr < 0)
nr = 0;
if (ng < 0)
ng = 0;
if (nb < 0)
nb = 0;
putpix (dst, dst_x2, dst_y2,
SDL_MapRGB (dst->format, nr, ng, nb));
}
}
}
else
{
// modulated blit: dst = src * (blend_numer / blend_denom)
float f = blend_numer / (float)blend_denom;
#if 0
log_add (log_Debug, "modulated blit %d %d, f %f, src %d %d %d %d"
" dst %d %d, srcbpp %d\n", blend_numer, blend_denom, f,
x1, y1, x2, y2, dstrect->x, dstrect->y,
src->format->BitsPerPixel);
#endif
for (y = y1; y < y2; ++y)
{
dst_y2 = dstrect->y + (y - y1);
for (x = x1; x < x2; ++x)
{
dst_x2 = dstrect->x + (x - x1);
src_pixval = src_getpix (src, x, y);
if (has_colorkey && src_pixval == colorkey)
continue;
SDL_GetRGB (src_pixval, src->format, &sr, &sg, &sb);
nr = (int)(sr * f);
ng = (int)(sg * f);
nb = (int)(sb * f);
if (nr > 255)
nr = 255;
if (ng > 255)
ng = 255;
if (nb > 255)
nb = 255;
putpix (dst, dst_x2, dst_y2,
SDL_MapRGB (dst->format, nr, ng, nb));
}
}
}
}
void
TFB_UploadTransitionScreen (void)
{
#ifdef HAVE_OPENGL
if (GraphicsDriver == TFB_GFXDRIVER_SDL_OPENGL)
{
TFB_GL_UploadTransitionScreen ();
}
#endif
}
void
TFB_SetGamma (float gamma)
{
if (SDL_SetGamma (gamma, gamma, gamma) == -1)
{
log_add (log_Warning, "Unable to set gamma correction.");
}
else
{
log_add (log_Info, "Gamma correction set to %1.4f.", gamma);
}
}

View File

@@ -1,51 +0,0 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef SDL_COMMON_H
#define SDL_COMMON_H
#include "port.h"
#include SDL_INCLUDE(SDL.h)
#include SDL_INCLUDE(SDL_byteorder.h)
#include SDL_IMAGE_INCLUDE(SDL_image.h)
#include "../gfxintrn.h"
#include "libs/graphics/tfb_draw.h"
#include "libs/graphics/gfx_common.h"
// The Graphics Backend vtable
typedef struct _tfb_graphics_backend {
void (*preprocess) (int force_redraw, int transition_amount, int fade_amount);
void (*postprocess) (void);
void (*screen) (SCREEN screen, Uint8 alpha, SDL_Rect *rect);
void (*color) (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect);
} TFB_GRAPHICS_BACKEND;
extern TFB_GRAPHICS_BACKEND *graphics_backend;
extern SDL_Surface *SDL_Video;
extern SDL_Surface *SDL_Screen;
extern SDL_Surface *TransitionScreen;
extern SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS];
extern SDL_Surface *format_conv_surf;
SDL_Surface* TFB_DisplayFormatAlpha (SDL_Surface *surface);
#endif

View File

@@ -1,133 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "sdluio.h"
#include "port.h"
#include "libs/uio.h"
#include SDL_INCLUDE(SDL.h)
#include SDL_INCLUDE(SDL_error.h)
#include SDL_INCLUDE(SDL_rwops.h)
#include SDL_IMAGE_INCLUDE(SDL_image.h)
#include "libs/memlib.h"
#include <errno.h>
#include <string.h>
static SDL_RWops *sdluio_makeRWops (uio_Stream *stream);
#if 0
// For use for initialisation, using structure assignment.
static SDL_RWops sdluio_templateRWops =
{
.seek = sdluio_seek,
.read = sdluio_read,
.write = sdluio_write,
.close = sdluio_close,
};
#endif
SDL_Surface *
sdluio_loadImage (uio_DirHandle *dir, const char *fileName) {
uio_Stream *stream;
SDL_RWops *rwops;
SDL_Surface *result;
stream = uio_fopen (dir, fileName, "rb");
if (stream == NULL)
{
SDL_SetError ("Couldn't open '%s': %s", fileName,
strerror(errno));
return NULL;
}
rwops = sdluio_makeRWops (stream);
result = IMG_Load_RW (rwops, 1);
return result;
}
int
sdluio_seek (SDL_RWops *context, int offset, int whence) {
if (uio_fseek ((uio_Stream *) context->hidden.unknown.data1, offset,
whence) == -1)
{
SDL_SetError ("Error seeking in uio_Stream: %s",
strerror(errno));
return -1;
}
return uio_ftell ((uio_Stream *) context->hidden.unknown.data1);
}
int
sdluio_read (SDL_RWops *context, void *ptr, int size, int maxnum) {
size_t numRead;
numRead = uio_fread (ptr, (size_t) size, (size_t) maxnum,
(uio_Stream *) context->hidden.unknown.data1);
if (numRead == 0 && uio_ferror ((uio_Stream *)
context->hidden.unknown.data1))
{
SDL_SetError ("Error reading from uio_Stream: %s",
strerror(errno));
return 0;
}
return (int) numRead;
}
int
sdluio_write (SDL_RWops *context, const void *ptr, int size, int num) {
size_t numWritten;
numWritten = uio_fwrite (ptr, (size_t) size, (size_t) num,
(uio_Stream *) context->hidden.unknown.data1);
if (numWritten == 0 && uio_ferror ((uio_Stream *)
context->hidden.unknown.data1))
{
SDL_SetError ("Error writing to uio_Stream: %s",
strerror(errno));
return 0;
}
return (size_t) numWritten;
}
int
sdluio_close (SDL_RWops *context) {
int result;
result = uio_fclose ((uio_Stream *) context->hidden.unknown.data1);
HFree (context);
return result;
}
static SDL_RWops *
sdluio_makeRWops (uio_Stream *stream) {
SDL_RWops *result;
result = HMalloc (sizeof (SDL_RWops));
#if 0
*(struct SDL_RWops *) result = sdluio_templateRWops;
// structure assignment
#endif
result->seek = sdluio_seek;
result->read = sdluio_read;
result->write = sdluio_write;
result->close = sdluio_close;
result->hidden.unknown.data1 = stream;
return result;
}

View File

@@ -1,33 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
#ifndef _SDLUIO_H
#define _SDLUIO_H
#include "port.h"
#include "libs/uio.h"
#include SDL_INCLUDE(SDL.h)
#include SDL_INCLUDE(SDL_rwops.h)
SDL_Surface *sdluio_loadImage (uio_DirHandle *dir, const char *fileName);
int sdluio_seek (SDL_RWops *context, int offset, int whence);
int sdluio_read (SDL_RWops *context, void *ptr, int size, int maxnum);
int sdluio_write (SDL_RWops *context, const void *ptr, int size, int num);
int sdluio_close (SDL_RWops *context);
#endif /* _SDLUIO_H */

View File

@@ -1,155 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*/
// Core algorithm of the Triscan screen scaler (based on Scale2x)
// (for scale2x please see http://scale2x.sf.net)
// Template
// When this file is built standalone is produces a plain C version
// Also #included by 2xscalers_mmx.c for an MMX version
#include "libs/graphics/sdl/sdl_common.h"
#include "types.h"
#include "scalers.h"
#include "scaleint.h"
#include "2xscalers.h"
// Triscan scaling to 2x
// derivative of scale2x -- scale2x.sf.net
// The name expands to either
// Scale_TriScanFilter (for plain C) or
// Scale_MMX_TriScanFilter (for MMX)
// [others when platforms are added]
void
SCALE_(TriScanFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r)
{
int x, y;
const int w = src->w, h = src->h;
int xend, yend;
int dsrc, ddst;
SDL_Rect *region = r;
SDL_Rect limits;
SDL_PixelFormat *fmt = dst->format;
const int sp = src->pitch, dp = dst->pitch;
const int bpp = fmt->BytesPerPixel;
const int slen = sp / bpp, dlen = dp / bpp;
// for clarity purposes, the 'pixels' array here is transposed
Uint32 pixels[3][3];
Uint32 *src_p = (Uint32 *)src->pixels;
Uint32 *dst_p = (Uint32 *)dst->pixels;
int prevline, nextline;
// these macros are for clarity; they make the current pixel (0,0)
// and allow to access pixels in all directions
#define PIX(x, y) (pixels[1 + (x)][1 + (y)])
#define TRISCAN_YUV_MED 100
// medium tolerance pixel comparison
#define TRISCAN_CMPYUV(p1, p2) \
(PIX p1 == PIX p2 || SCALE_CMPYUV (PIX p1, PIX p2, TRISCAN_YUV_MED))
SCALE_(PlatInit) ();
// expand updated region if necessary
// pixels neighbooring the updated region may
// change as a result of updates
limits.x = 0;
limits.y = 0;
limits.w = src->w;
limits.h = src->h;
Scale_ExpandRect (region, 1, &limits);
xend = region->x + region->w;
yend = region->y + region->h;
dsrc = slen - region->w;
ddst = (dlen - region->w) * 2;
// move ptrs to the first updated pixel
src_p += slen * region->y + region->x;
dst_p += (dlen * region->y + region->x) * 2;
for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc)
{
if (y > 0)
prevline = -slen;
else
prevline = 0;
if (y < h - 1)
nextline = slen;
else
nextline = 0;
// prime the (tiny) sliding-window pixel arrays
PIX( 1, 0) = src_p[0];
if (region->x > 0)
PIX( 0, 0) = src_p[-1];
else
PIX( 0, 0) = PIX( 1, 0);
for (x = region->x; x < xend; ++x, ++src_p, dst_p += 2)
{
// slide the window
PIX(-1, 0) = PIX( 0, 0);
PIX( 0, -1) = src_p[prevline];
PIX( 0, 0) = PIX( 1, 0);
PIX( 0, 1) = src_p[nextline];
if (x < w - 1)
PIX( 1, 0) = src_p[1];
else
PIX( 1, 0) = PIX( 0, 0);
if (!TRISCAN_CMPYUV (( 0, -1), ( 0, 1)) &&
!TRISCAN_CMPYUV ((-1, 0), ( 1, 0)))
{
if (TRISCAN_CMPYUV ((-1, 0), ( 0, -1)))
dst_p[0] = Scale_Blend_11 (PIX(-1, 0), PIX(0, -1));
else
dst_p[0] = PIX(0, 0);
if (TRISCAN_CMPYUV (( 1, 0), ( 0, -1)))
dst_p[1] = Scale_Blend_11 (PIX(1, 0), PIX(0, -1));
else
dst_p[1] = PIX(0, 0);
if (TRISCAN_CMPYUV ((-1, 0), ( 0, 1)))
dst_p[dlen] = Scale_Blend_11 (PIX(-1, 0), PIX(0, 1));
else
dst_p[dlen] = PIX(0, 0);
if (TRISCAN_CMPYUV (( 1, 0), ( 0, 1)))
dst_p[dlen+1] = Scale_Blend_11 (PIX(1, 0), PIX(0, 1));
else
dst_p[dlen+1] = PIX(0, 0);
}
else
{
dst_p[0] = PIX(0, 0);
dst_p[1] = PIX(0, 0);
dst_p[dlen] = PIX(0, 0);
dst_p[dlen+1] = PIX(0, 0);
}
}
}
SCALE_(PlatDone) ();
}

Some files were not shown because too many files have changed in this diff Show More