diff options
| author | Max Horn | 2003-06-22 11:55:40 +0000 | 
|---|---|---|
| committer | Max Horn | 2003-06-22 11:55:40 +0000 | 
| commit | 11ff7fe9a347efe37e2bd8fefca7e8c130f81af0 (patch) | |
| tree | 037c8edce6a559e5816b7733727305ff66cc49cf | |
| parent | fa184730af2f2be094aa9f37cd3abf58d10f79ea (diff) | |
| download | scummvm-rg350-11ff7fe9a347efe37e2bd8fefca7e8c130f81af0.tar.gz scummvm-rg350-11ff7fe9a347efe37e2bd8fefca7e8c130f81af0.tar.bz2 scummvm-rg350-11ff7fe9a347efe37e2bd8fefca7e8c130f81af0.zip | |
Patch #757827: Aspect-ratio correction
svn-id: r8605
| -rw-r--r-- | README | 67 | ||||
| -rw-r--r-- | backends/sdl/sdl-common.cpp | 44 | ||||
| -rw-r--r-- | backends/sdl/sdl-common.h | 6 | ||||
| -rw-r--r-- | backends/sdl/sdl.cpp | 34 | ||||
| -rw-r--r-- | backends/sdl/sdl_gl.cpp | 53 | ||||
| -rw-r--r-- | common/gameDetector.cpp | 56 | ||||
| -rw-r--r-- | common/gameDetector.h | 1 | ||||
| -rw-r--r-- | common/scaler.cpp | 102 | ||||
| -rw-r--r-- | common/scaler.h | 10 | ||||
| -rw-r--r-- | common/system.h | 5 | 
10 files changed, 267 insertions, 111 deletions
| @@ -339,33 +339,36 @@ Command Line Options:          scummvm [OPTIONS] [GAME] -        [GAME]        - Short name of game to load. For example, 'monkey' for -                        Monkey Island. - -        -p<path>      - Path to where the game is installed. Default is Cwd. -        -x[<num>]     - Save game slot to load (default: autosave) -        -f            - Full-screen mode. -        -g<mode>      - Select graphics scaler. See below. -        -e<mode>      - Select sound engine. See below. -        -a            - Enable amiga pal conversion, for playing Amiga versions -        -q<lang>      - Select language. See below. -        -c<num>       - Drive to play cd audio from.  E.g., 0 is first drive. -        -m<num>       - Set the music volume, 0-255.  Default is '192' -        -o<num>       - Set the master volume, 0-255. Default is '192' -        -s<num>       - Set the sfx volume, 0-255.    Default is '192' -        -t<num>       - Set music tempo. 50-200. Default is '100' (percent) -        -n            - Disable subtitles. Use with games that have voice. -        -y            - Set talk speed ('yak option'). Default is '60' -        -l<file>      - Load alternate configuration file -        -w[<file>]    - Write configuration file -        -v            - Show version information and exit -        -z            - Display list of games -        -b<num>       - Start in room <num>. -        -d[<num>]     - Set debug verbosity to <num> -        -u            - Dump scripts if a directory called 'dumps' exists in -                        current directory -        --multi-midi  - enable combination Adlib and native MIDI -        --native-mt32 - true Roland MT-32 (disable GM emulation) +        [GAME]         - Short name of game to load. For example, 'monkey' for +                         Monkey Island. + +        -p<path>       - Path to where the game is installed. Default is Cwd. +        -x[<num>]      - Save game slot to load (default: autosave) +        -f             - Full-screen mode. +        -g<mode>       - Select graphics scaler. See below. +        -e<mode>       - Select sound engine. See below. +        -a             - Enable amiga pal conversion, for playing Amiga +                         versions +        -q<lang>       - Select language. See below. +        -c<num>        - Drive to play cd audio from.  E.g., 0 is first drive. +        -m<num>        - Set the music volume, 0-255.  Default is '192' +        -o<num>        - Set the master volume, 0-255. Default is '192' +        -s<num>        - Set the sfx volume, 0-255.    Default is '192' +        -t<num>        - Set music tempo. 50-200. Default is '100' (percent) +        -n             - Disable subtitles. Use with games that have voice. +        -y             - Set talk speed ('yak option'). Default is '60' +        -l<file>       - Load alternate configuration file +        -w[<file>]     - Write configuration file +        -v             - Show version information and exit +        -z             - Display list of games +        -b<num>        - Start in room <num>. +        -d[<num>]      - Set debug verbosity to <num> +        -u             - Dump scripts if a directory called 'dumps' exists in +                         current directory +        --multi-midi   - enable combination Adlib and native MIDI +        --native-mt32  - true Roland MT-32 (disable GM emulation) +        --aspect-ratio - enable aspect ratio correction +  Hot Keys: @@ -380,9 +383,13 @@ simon games.          Ctrl-Alt 0-9           - Switch between graphics filters          Ctrl-Alt b             - Switch beetwen bilinear and non-linear                                   filtering [OpenGL backend] -        Ctrl-Alt a             - Switch between: [OpenGL backend] -                                 - Fit the game in the whole screen (No black borders) -                                 - Don't fit the game in the whole screen (Black borders)  +        Ctrl-Alt a             - Toggle aspect-ratio correction on/off. +                                 Most of the games use a 320x200 pixel +                                 resolution, which may look squashed on +                                 modern monitors. Aspect-ratio correction +                                 stretches the image to use 320x240 pixels +                                 instead, or a multiple thereof. +      Scumm:          Ctrl 0-9 and Alt 0-9   - load and save game state          Ctrl-g                 - runs in really REALLY fast mode. diff --git a/backends/sdl/sdl-common.cpp b/backends/sdl/sdl-common.cpp index 1095d4b68f..cd3b99430c 100644 --- a/backends/sdl/sdl-common.cpp +++ b/backends/sdl/sdl-common.cpp @@ -41,22 +41,23 @@  #define JOY_BUT_SPACE 4  #define JOY_BUT_F5 5 -OSystem *OSystem_SDL_create(int gfx_mode, bool full_screen) { -	return OSystem_SDL_Common::create(gfx_mode, full_screen); +OSystem *OSystem_SDL_create(int gfx_mode, bool full_screen, bool aspect_ratio) { +	return OSystem_SDL_Common::create(gfx_mode, full_screen, aspect_ratio);  } -OSystem *OSystem_SDL_Common::create(int gfx_mode, bool full_screen) { +OSystem *OSystem_SDL_Common::create(int gfx_mode, bool full_screen, bool aspect_ratio) {  	OSystem_SDL_Common *syst = OSystem_SDL_Common::create_intern(); -	syst->init_intern(gfx_mode, full_screen); +	syst->init_intern(gfx_mode, full_screen, aspect_ratio);  	return syst;  } -void OSystem_SDL_Common::init_intern(int gfx_mode, bool full_screen) { +void OSystem_SDL_Common::init_intern(int gfx_mode, bool full_screen, bool aspect_ratio) {  	_mode = gfx_mode;  	_full_screen = full_screen; +	_adjustAspectRatio = aspect_ratio;  	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) ==-1) {  		error("Could not initialize SDL: %s.\n", SDL_GetError()); @@ -129,6 +130,10 @@ void OSystem_SDL_Common::init_size(uint w, uint h) {  	_screenWidth = w;  	_screenHeight = h; + +	if (h != 200) +		_adjustAspectRatio = false; +  	CKSUM_NUM = (_screenWidth * _screenHeight / (8 * 8));  	if (_dirty_checksums)  		free(_dirty_checksums); @@ -576,20 +581,18 @@ bool OSystem_SDL_Common::poll_event(Event *event) {  				}  			} -			// Ctr-Alt-a will change aspect ratio in OpenGL backend +			// Ctr-Alt-a will change aspect ratio  			if (b == (KBD_CTRL|KBD_ALT) && ev.key.keysym.sym=='a') { -					Property prop; -					prop.gfx_mode = 11; -					property(PROP_SET_GFX_MODE, &prop); -					break; +				property(PROP_TOGGLE_ASPECT_RATIO, NULL); +				break;  			}  			// Ctr-Alt-b will change bilinear filtering in OpenGL backend  			if (b == (KBD_CTRL|KBD_ALT) && ev.key.keysym.sym=='b') { -					Property prop; -					prop.gfx_mode = 12; -					property(PROP_SET_GFX_MODE, &prop); -					break; +				Property prop; +				prop.gfx_mode = GFX_BILINEAR; +				property(PROP_SET_GFX_MODE, &prop); +				break;  			}  #ifdef QTOPIA @@ -698,6 +701,8 @@ bool OSystem_SDL_Common::poll_event(Event *event) {  			event->mouse.x /= _scaleFactor;  			event->mouse.y /= _scaleFactor; +			if (_adjustAspectRatio) +				event->mouse.y = aspect2Real(event->mouse.y);  			return true;  		case SDL_MOUSEBUTTONDOWN: @@ -718,6 +723,9 @@ bool OSystem_SDL_Common::poll_event(Event *event) {  			event->mouse.x /= _scaleFactor;  			event->mouse.y /= _scaleFactor; +			if (_adjustAspectRatio) +				event->mouse.y = aspect2Real(event->mouse.y); +  			return true;  		case SDL_MOUSEBUTTONUP: @@ -731,6 +739,10 @@ bool OSystem_SDL_Common::poll_event(Event *event) {  			event->mouse.y = ev.button.y;  			event->mouse.x /= _scaleFactor;  			event->mouse.y /= _scaleFactor; + +			if (_adjustAspectRatio) +				event->mouse.y = aspect2Real(event->mouse.y); +  			return true;  		case SDL_JOYBUTTONDOWN: @@ -835,6 +847,10 @@ bool OSystem_SDL_Common::poll_event(Event *event) {  			event->mouse.y = km.y;  			event->mouse.x /= _scaleFactor;  			event->mouse.y /= _scaleFactor; + +			if (_adjustAspectRatio) +				event->mouse.y = aspect2Real(event->mouse.y); +  			return true;  		case SDL_VIDEOEXPOSE: diff --git a/backends/sdl/sdl-common.h b/backends/sdl/sdl-common.h index c5e6847ffa..9c4bf91ab7 100644 --- a/backends/sdl/sdl-common.h +++ b/backends/sdl/sdl-common.h @@ -123,7 +123,7 @@ public:  	virtual int16 RGBToColor(uint8 r, uint8 g, uint8 b);  	virtual void colorToRGB(int16 color, uint8 &r, uint8 &g, uint8 &b); -	static OSystem *create(int gfx_mode, bool full_screen); +	static OSystem *create(int gfx_mode, bool full_screenm, bool aspect_ratio);  protected:  	OSystem_SDL_Common(); @@ -131,7 +131,7 @@ protected:  	static OSystem_SDL_Common *create_intern(); -	void init_intern(int gfx_mode, bool full_screen); +	void init_intern(int gfx_mode, bool full_screen, bool aspect_ratio);  	// unseen game screen  	SDL_Surface *_screen; @@ -142,6 +142,8 @@ protected:  	int _tmpScreenWidth;  	bool _overlayVisible; +	bool _adjustAspectRatio; +  	// CD Audio  	SDL_CD *_cdrom;  	int cd_track, cd_num_loops, cd_start_frame, cd_end_frame; diff --git a/backends/sdl/sdl.cpp b/backends/sdl/sdl.cpp index 2caa4d2d67..ecb00cd2d8 100644 --- a/backends/sdl/sdl.cpp +++ b/backends/sdl/sdl.cpp @@ -147,12 +147,13 @@ normal_mode:;  	//  	// Create the surface that contains the scaled graphics in 16 bit mode  	// -	_hwscreen = SDL_SetVideoMode(_screenWidth * _scaleFactor, _screenHeight * _scaleFactor, 16,  + +	_hwscreen = SDL_SetVideoMode(_screenWidth * _scaleFactor, (_adjustAspectRatio ? 240 : _screenHeight) * _scaleFactor, 16,   		_full_screen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE  	);  	if (_hwscreen == NULL)  		error("_hwscreen failed"); -	 +  	//  	// Create the surface used for the graphics in 16 bit before scaling, and also the overlay  	// @@ -192,7 +193,7 @@ void OSystem_SDL::unload_gfx_mode() {  		SDL_FreeSurface(_hwscreen);   		_hwscreen = NULL;  	} -	 +  	if (_tmpscreen) {  		free(_tmpscreen->pixels);  		SDL_FreeSurface(_tmpscreen); @@ -281,7 +282,7 @@ void OSystem_SDL::update_screen() {  		uint32 srcPitch, dstPitch;  		SDL_Rect *last_rect = _dirty_rect_list + _num_dirty_rects; -		if (_scaler_proc == Normal1x) { +		if (_scaler_proc == Normal1x && !_adjustAspectRatio) {  			SDL_Surface *target = _overlayVisible ? _tmpscreen : _screen;  			for (r = _dirty_rect_list; r != last_rect; ++r) {  				dst = *r; @@ -314,23 +315,32 @@ void OSystem_SDL::update_screen() {  			for (r = _dirty_rect_list; r != last_rect; ++r) {  				register int dst_y = r->y + _currentShakePos;  				register int dst_h = 0; +				register int orig_dst_y = 0; +  				if (dst_y < _screenHeight) {  					dst_h = r->h;  					if (dst_h > _screenHeight - dst_y)  						dst_h = _screenHeight - dst_y; -						dst_y *= _scaleFactor; +					dst_y *= _scaleFactor; -						_scaler_proc((byte *)_tmpscreen->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, +					if (_adjustAspectRatio) { +						orig_dst_y = dst_y; +						dst_y = real2Aspect(dst_y); +					} + +					_scaler_proc((byte *)_tmpscreen->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,  						(byte *)_hwscreen->pixels + r->x * 2 * _scaleFactor + dst_y * dstPitch, dstPitch, r->w, dst_h);  				} -			 +  				r->x *= _scaleFactor;  				r->y = dst_y;  				r->w *= _scaleFactor;  				r->h = dst_h * _scaleFactor; -			} +				if (_adjustAspectRatio && orig_dst_y / _scaleFactor < _screenHeight) +					r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y); +			}  			SDL_UnlockSurface(_tmpscreen);  			SDL_UnlockSurface(_hwscreen);  		} @@ -339,7 +349,7 @@ void OSystem_SDL::update_screen() {  		// This is necessary if shaking is active.  		if (_forceFull) {  			_dirty_rect_list[0].y = 0; -			_dirty_rect_list[0].h = _screenHeight * _scaleFactor; +			_dirty_rect_list[0].h = (_adjustAspectRatio ? 240 : _screenHeight) * _scaleFactor;  		}  		// Finally, blit all our changes to the screen @@ -374,6 +384,12 @@ uint32 OSystem_SDL::property(int param, Property *value) {  		hotswap_gfx_mode();  		return 1; +	} else if (param == PROP_TOGGLE_ASPECT_RATIO) { +		if (_screenHeight == 200) { +			assert(_hwscreen != 0); +			_adjustAspectRatio ^= true; +			hotswap_gfx_mode(); +		}  	}  	return OSystem_SDL_Common::property(param, value); diff --git a/backends/sdl/sdl_gl.cpp b/backends/sdl/sdl_gl.cpp index d29029ddfe..949baf7b1d 100644 --- a/backends/sdl/sdl_gl.cpp +++ b/backends/sdl/sdl_gl.cpp @@ -54,7 +54,6 @@ protected:  	int _glFlags;  	int _glScreenStart;  	bool _glBilinearFilter; -	bool _glAspectRatio;  	bool _usingOpenGL;  	SDL_Surface *tmpSurface; // Used for black rectangles blitting   	SDL_Rect tmpBlackRect;   // Black rectangle at end of the GL screen @@ -79,7 +78,6 @@ OSystem_SDL_OpenGL::OSystem_SDL_OpenGL()  {    _glScreenStart = 0;     _glBilinearFilter = true; -  _glAspectRatio = false;    _usingOpenGL = false; // false => Switch to filters used in the sdl.cpp version    _glBottomOfTexture = 256; // height is always 256    // 640x480 resolution @@ -165,7 +163,7 @@ void OSystem_SDL_OpenGL::load_gfx_mode() {  	case GFX_NORMAL:  normal_mode:; -		_scaleFactor = 1; +		_scaleFactor = _usingOpenGL ? 2 : 1;  		_scaler_proc = Normal1x;  		break;  	default: @@ -199,8 +197,7 @@ normal_mode:;  		fb2gl.init(_glWindow.w, _glWindow.h, 0, _glScreenStart? 15: 70,   		    _glFlags); -	} -	else { // SDL backend +	} else { // SDL backend  		_hwscreen = SDL_SetVideoMode(_screenWidth * _scaleFactor, _screenHeight * _scaleFactor, 16,   		  _full_screen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE @@ -234,8 +231,7 @@ normal_mode:;  						Gmask,  						Bmask,  						Amask); -	} -	else { // SDL backend +	} else { // SDL backend  		_tmpscreen = SDL_CreateRGBSurfaceFrom(tmp_screen,  						_tmpScreenWidth,   						_screenHeight + 3,  @@ -346,8 +342,7 @@ void OSystem_SDL_OpenGL::update_screen() {  			SDL_FillRect(tmpSurface, &blackrect, 0);  			fb2gl.blit16(tmpSurface, 1, &blackrect, 0, 0); -		} -		else { // SDL backend +		} else { // SDL backend  			SDL_Rect blackrect = {0, 0, _screenWidth * _scaleFactor, _newShakePos * _scaleFactor};  			SDL_FillRect(_hwscreen, &blackrect, 0);  		} @@ -545,9 +540,30 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {  #endif  		return 1; -	} -	else if (param == PROP_SET_GFX_MODE) { +	} else if (param == PROP_TOGGLE_ASPECT_RATIO) { +		if (!_usingOpenGL) { +			_usingOpenGL = true; +			_mode = GFX_NORMAL; +			hotswap_gfx_mode(); +		} + +		_adjustAspectRatio ^= true; +		if (_adjustAspectRatio) { +			// Don't use the whole screen (black borders) +			fb2gl.init(0, 0, 0, 15, _glFlags); +			_glScreenStart = 20; +			SDL_FillRect(tmpSurface, &tmpBlackRect, 0); +			fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0, 0); +		} else { +			// Use the whole screen +			fb2gl.init(0, 0, 0, 70, _glFlags); +			_glScreenStart = 0; +		} +  		SDL_Rect full = {0, 0, _screenWidth, _screenHeight}; +		fb2gl.blit16(_tmpscreen, 1, &full, 0, _glScreenStart); +		fb2gl.display(); +	} else if (param == PROP_SET_GFX_MODE) {  		if (value->gfx_mode > 10) { // OpenGL modes  			if (!_usingOpenGL) { @@ -562,20 +578,6 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {  				_glBilinearFilter ^= true;  				fb2gl.setBilinearMode(_glBilinearFilter);  				break; -			case GFX_ASPECTRATIO:  -				_glAspectRatio ^= true; -				if (_glAspectRatio) { -					// Don't use the whole screen (black borders) -					fb2gl.init(0, 0, 0, 15, _glFlags); -					_glScreenStart = 20; -					SDL_FillRect(tmpSurface, &tmpBlackRect, 0); -					fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0, 0); -				} else { -					// Use the whole screen -					fb2gl.init(0, 0, 0, 70, _glFlags); -					_glScreenStart = 0; -				} -				break;  			default: // SDL backend  				if (value->gfx_mode >= 10)  				  return 0; @@ -589,6 +591,7 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {  		};  		if (_usingOpenGL) { +			SDL_Rect full = {0, 0, _screenWidth, _screenHeight};  			fb2gl.blit16(_tmpscreen, 1, &full, 0, _glScreenStart);  			fb2gl.display();  		} 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(); | 
