aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2003-06-22 11:55:40 +0000
committerMax Horn2003-06-22 11:55:40 +0000
commit11ff7fe9a347efe37e2bd8fefca7e8c130f81af0 (patch)
tree037c8edce6a559e5816b7733727305ff66cc49cf /common
parentfa184730af2f2be094aa9f37cd3abf58d10f79ea (diff)
downloadscummvm-rg350-11ff7fe9a347efe37e2bd8fefca7e8c130f81af0.tar.gz
scummvm-rg350-11ff7fe9a347efe37e2bd8fefca7e8c130f81af0.tar.bz2
scummvm-rg350-11ff7fe9a347efe37e2bd8fefca7e8c130f81af0.zip
Patch #757827: Aspect-ratio correction
svn-id: r8605
Diffstat (limited to 'common')
-rw-r--r--common/gameDetector.cpp56
-rw-r--r--common/gameDetector.h1
-rw-r--r--common/scaler.cpp102
-rw-r--r--common/scaler.h10
-rw-r--r--common/system.h5
5 files changed, 143 insertions, 31 deletions
diff --git a/common/gameDetector.cpp b/common/gameDetector.cpp
index 3cd1a742cb..a4841ed72b 100644
--- a/common/gameDetector.cpp
+++ b/common/gameDetector.cpp
@@ -50,38 +50,39 @@ static const char USAGE_STRING[] =
"Syntax:\n"
"\tscummvm [-v] [-d[<num>]] [-n] [-b<num>] [-t<num>] [-s<num>] [-p<path>] [-m<num>] [-f] game\n"
"Flags:\n"
- "\t-p<path> - look for game in <path>\n"
- "\t-x[<num>] - load this savegame (default: 0 - autosave)\n"
- "\t-f - fullscreen mode\n"
- "\t-g<mode> - graphics mode (normal,2x,3x,2xsai,super2xsai,supereagle,advmame2x,advmame3x,tv2x,dotmatrix)\n"
- "\t-e<mode> - set music engine (see README for details)\n"
- "\t-a - specify game is amiga version\n"
- "\t-q<lang> - specify language (en,de,fr,it,pt,es,jp,zh,kr,hb)\n"
+ "\t-p<path> - look for game in <path>\n"
+ "\t-x[<num>] - load this savegame (default: 0 - autosave)\n"
+ "\t-f - fullscreen mode\n"
+ "\t-g<mode> - graphics mode (normal,2x,3x,2xsai,super2xsai,supereagle,advmame2x,advmame3x,tv2x,dotmatrix)\n"
+ "\t-e<mode> - set music engine (see README for details)\n"
+ "\t-a - specify game is amiga version\n"
+ "\t-q<lang> - specify language (en,de,fr,it,pt,es,jp,zh,kr,hb)\n"
"\n"
- "\t-c<num> - use cdrom <num> for cd audio\n"
- "\t-m<num> - set music volume to <num> (0-255)\n"
- "\t-o<num> - set master volume to <num> (0-255)\n"
- "\t-s<num> - set sfx volume to <num> (0-255)\n"
- "\t-t<num> - set music tempo (50-200, default 100%%)\n"
+ "\t-c<num> - use cdrom <num> for cd audio\n"
+ "\t-m<num> - set music volume to <num> (0-255)\n"
+ "\t-o<num> - set master volume to <num> (0-255)\n"
+ "\t-s<num> - set sfx volume to <num> (0-255)\n"
+ "\t-t<num> - set music tempo (50-200, default 100%%)\n"
"\n"
- "\t-n - no subtitles for speech\n"
- "\t-y - set text speed (default: 60)\n"
+ "\t-n - no subtitles for speech\n"
+ "\t-y - set text speed (default: 60)\n"
"\n"
- "\t-l<file> - load config file instead of default\n"
+ "\t-l<file> - load config file instead of default\n"
#if defined(UNIX)
- "\t-w[<file>] - write to config file [~/.scummvmrc]\n"
+ "\t-w[<file>] - write to config file [~/.scummvmrc]\n"
#else
- "\t-w[<file>] - write to config file [scummvm.ini]\n"
+ "\t-w[<file>] - write to config file [scummvm.ini]\n"
#endif
- "\t-v - show version info and exit\n"
- "\t-z - display list of games\n"
+ "\t-v - show version info and exit\n"
+ "\t-z - display list of games\n"
"\n"
- "\t-b<num> - start in room <num>\n"
- "\t-d[<num>] - enable debug output (debug level [1])\n"
- "\t-u - dump scripts\n"
+ "\t-b<num> - start in room <num>\n"
+ "\t-d[<num>] - enable debug output (debug level [1])\n"
+ "\t-u - dump scripts\n"
"\n"
- "\t--multi-midi - enable combination Adlib and native MIDI\n"
- "\t--native-mt32 - true Roland MT-32 (disable GM emulation)\n"
+ "\t--multi-midi - enable combination Adlib and native MIDI\n"
+ "\t--native-mt32 - true Roland MT-32 (disable GM emulation)\n"
+ "\t--aspect-ratio - enable aspect ratio correction\n"
;
#endif
// This contains a pointer to a list of all supported games.
@@ -148,6 +149,7 @@ static int countVersions(const VersionSettings *v) {
GameDetector::GameDetector() {
_fullScreen = false;
+ _aspectRatio = false;
_use_adlib = false;
@@ -245,6 +247,7 @@ void GameDetector::updateconfig() {
}
_fullScreen = g_config->getBool("fullscreen", _fullScreen);
+ _aspectRatio = g_config->getBool("aspect_ratio", _aspectRatio);
if ((val = g_config->get("gfx_mode")))
if ((_gfx_mode = parseGraphicsMode(val)) == -1) {
@@ -453,6 +456,9 @@ void GameDetector::parseCommandLine(int argc, char **argv) {
} else if (!strcmp (s, "native-mt32")) {
_native_mt32 = true;
g_config->setBool ("native_mt32", true);
+ } else if (!strcmp (s, "aspect-ratio")) {
+ _aspectRatio = true;
+ g_config->setBool ("aspect_ratio", true);
} else {
goto ShowHelpAndExit;
}
@@ -673,7 +679,7 @@ OSystem *GameDetector::createSystem() {
return OSystem_PALMOS_create(_gfx_mode);
#else
/* SDL is the default driver for now */
- return OSystem_SDL_create(_gfx_mode, _fullScreen);
+ return OSystem_SDL_create(_gfx_mode, _fullScreen, _aspectRatio);
#endif
}
diff --git a/common/gameDetector.h b/common/gameDetector.h
index f73f20cd56..d9e5b104a5 100644
--- a/common/gameDetector.h
+++ b/common/gameDetector.h
@@ -110,6 +110,7 @@ public:
const String& getGameName(void);
bool _fullScreen;
+ bool _aspectRatio;
bool _use_adlib;
diff --git a/common/scaler.cpp b/common/scaler.cpp
index 1607fef214..0d952110c1 100644
--- a/common/scaler.cpp
+++ b/common/scaler.cpp
@@ -30,7 +30,9 @@ static uint32 lowPixelMask = 0x08210821;
static uint32 qcolorMask = 0xE79CE79C;
static uint32 qlowpixelMask = 0x18631863;
static uint32 redblueMask = 0xF81F;
-static uint32 greenMask = 0x7E0;
+static uint32 redMask = 0xF800;
+static uint32 greenMask = 0x07E0;
+static uint32 blueMask = 0x001F;
static const uint16 dotmatrix_565[16] = {
0x01E0, 0x0007, 0x3800, 0x0000,
@@ -53,7 +55,9 @@ int Init_2xSaI(uint32 BitFormat) {
qcolorMask = 0xE79CE79C;
qlowpixelMask = 0x18631863;
redblueMask = 0xF81F;
- greenMask = 0x7E0;
+ redMask = 0xF800;
+ greenMask = 0x07E0;
+ blueMask = 0x001F;
dotmatrix = dotmatrix_565;
} else if (BitFormat == 555) {
colorMask = 0x7BDE7BDE;
@@ -61,7 +65,9 @@ int Init_2xSaI(uint32 BitFormat) {
qcolorMask = 0x739C739C;
qlowpixelMask = 0x0C630C63;
redblueMask = 0x7C1F;
- greenMask = 0x3E0;
+ redMask = 0x7C00;
+ greenMask = 0x03E0;
+ blueMask = 0x001F;
dotmatrix = dotmatrix_555;
} else {
return 0;
@@ -634,3 +640,93 @@ void DotMatrix(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPi
q += nextlineDst << 1;
}
}
+
+
+static inline uint32 interpolate5(uint16 A, uint16 B, int scale) {
+ uint16 r = ((A & redMask) * scale + (B & redMask) * (5 - scale)) / 5;
+ uint16 g = ((A & greenMask) * scale + (B & greenMask) * (5 - scale)) / 5;
+ uint16 b = ((A & blueMask) * scale + (B & blueMask) * (5 - scale)) / 5;
+
+ return (r & redMask) | (g & greenMask) | (b & blueMask);
+}
+
+static inline void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int scale, int width) {
+#if 1
+ // Accurate but slightly slower code
+ while (width--) {
+ *dst++ = interpolate5(*srcA++, *srcB++, scale);
+ }
+#else
+ // Not fully accurate, but a bit faster
+ width /= 2;
+ const uint32 *sA = (const uint32 *)srcA;
+ const uint32 *sB = (const uint32 *)srcB;
+ uint32 *d = (uint32 *)dst;
+ if (scale == 1) {
+ while (width--) {
+ uint32 B = *sB++;
+ *d++ = Q_INTERPOLATE(*sA++, B, B, B);
+ }
+ } else {
+ while (width--) {
+ *d++ = INTERPOLATE(*sA++, *sB++);
+ }
+ }
+#endif
+}
+
+/**
+ * Stretch a 16bpp image vertically by factor 1.2. Used to correct the
+ * aspect-ratio in games using 320x200 pixel graphics with non-qudratic
+ * pixels. Applying this method effectively turns that into 320x240, which
+ * provides the correct aspect-ratio on modern displays.
+ *
+ * The image would normally have occupied y coordinates origSrcY through
+ * origSrcY + height - 1.
+ *
+ * However, we have already placed it at srcY - the aspect-corrected y
+ * coordinate - to allow in-place stretching.
+ *
+ * Therefore, the source image now occupies Y coordinates srcY through
+ * srcY + height - 1, and it should be stretched to Y coordinates srcY
+ * through real2Aspect(srcY + height - 1).
+ */
+int stretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY) {
+ int maxDstY = real2Aspect(origSrcY + height - 1);
+ int off = srcY - origSrcY;
+ int y;
+
+ uint8 *dstPtr = buf + srcX * 2 + maxDstY * pitch;
+
+ for (y = maxDstY; y >= srcY; y--) {
+ uint8 *srcPtr = buf + srcX * 2 + (aspect2Real(y) + off) * pitch;
+
+ if (srcPtr == dstPtr)
+ break;
+
+#if 0
+ // Don't use bilinear filtering, rather just duplicate pixel lines:
+ // a little bit faster, but looks ugly
+ memcpy(dstPtr, srcPtr, width * 2);
+#else
+ // Bilinear filter
+ switch (y % 6) {
+ case 0:
+ case 5:
+ memcpy(dstPtr, srcPtr, width * 2);
+ break;
+ case 1:
+ case 4:
+ interpolate5Line((uint16 *)dstPtr, (uint16 *)(srcPtr - pitch), (uint16 *)srcPtr, 1, width);
+ break;
+ case 2:
+ case 3:
+ interpolate5Line((uint16 *)dstPtr, (uint16 *)(srcPtr - pitch), (uint16 *)srcPtr, 2, width);
+ break;
+ }
+#endif
+ dstPtr -= pitch;
+ }
+
+ return 1 + maxDstY - srcY;
+}
diff --git a/common/scaler.h b/common/scaler.h
index e3246587c9..b8000ddccd 100644
--- a/common/scaler.h
+++ b/common/scaler.h
@@ -41,6 +41,15 @@ DECLARE_SCALER(Normal3x);
DECLARE_SCALER(TV2x);
DECLARE_SCALER(DotMatrix);
+FORCEINLINE int real2Aspect(int y) {
+ return y + (y + 1) / 5;
+}
+
+FORCEINLINE int aspect2Real(int y) {
+ return (y * 5 + 3) / 6;
+}
+
+extern int stretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY);
enum {
GFX_NORMAL = 0,
@@ -54,7 +63,6 @@ enum {
GFX_TV2X = 8,
GFX_DOTMATRIX = 9,
- GFX_ASPECTRATIO = 11, // OpenGL backend
GFX_BILINEAR = 12, // OpenGL backend
GFX_FLIPPING = 100, // Palmos
diff --git a/common/system.h b/common/system.h
index 68408a6a13..32e55e4879 100644
--- a/common/system.h
+++ b/common/system.h
@@ -94,7 +94,8 @@ public:
PROP_GET_SAMPLE_RATE = 6,
PROP_GET_FULLSCREEN = 7,
PROP_GET_FMOPL_ENV_BITS = 8,
- PROP_GET_FMOPL_EG_ENT = 9
+ PROP_GET_FMOPL_EG_ENT = 9,
+ PROP_TOGGLE_ASPECT_RATIO = 10
};
union Property {
const char *caption;
@@ -363,7 +364,7 @@ public:
/* Factory functions. This means we don't have to include the headers for
* all backends.
*/
-extern OSystem *OSystem_SDL_create(int gfx_driver, bool full_screen);
+extern OSystem *OSystem_SDL_create(int gfx_driver, bool full_screen, bool aspect_ratio);
extern OSystem *OSystem_NULL_create();
extern OSystem *OSystem_MorphOS_create(int game_id, int gfx_driver, bool full_screen);
extern OSystem *OSystem_Dreamcast_create();