mirror of
https://github.com/libretro/scummvm.git
synced 2025-05-13 09:36:21 +00:00

All uses of the old target scale API actually wanted to disallow scaling of the mouse cursor. This commit adapts our API to this and thus simplifies backend implementations. Some backends, most notable the Wii and Android, did some implementation of the cursor target scale, which I didn't adapt yet. I added a TODO for the porters there.
751 lines
17 KiB
C++
751 lines
17 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_abort
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <gxflux/gfx_con.h>
|
|
|
|
#include "common/config-manager.h"
|
|
#include "graphics/conversion.h"
|
|
#include "backends/fs/wii/wii-fs-factory.h"
|
|
|
|
#include "osystem.h"
|
|
|
|
#define ROUNDUP(x,n) (-(-(x) & -(n)))
|
|
#define MAX_FPS 30
|
|
#define TLUT_GAME GX_TLUT0
|
|
#define TLUT_MOUSE GX_TLUT1
|
|
|
|
static const OSystem::GraphicsMode _supportedGraphicsModes[] = {
|
|
{
|
|
"default",
|
|
"Default",
|
|
OSystem_Wii::gmStandard
|
|
},
|
|
{
|
|
"defaultbilinear",
|
|
"Default, bilinear filtering",
|
|
OSystem_Wii::gmStandardFiltered
|
|
},
|
|
{
|
|
"ds",
|
|
"Double-strike",
|
|
OSystem_Wii::gmDoubleStrike
|
|
},
|
|
{
|
|
"dsbilinear",
|
|
"Double-strike, bilinear filtering",
|
|
OSystem_Wii::gmDoubleStrikeFiltered
|
|
},
|
|
{ 0, 0, 0 }
|
|
};
|
|
|
|
void OSystem_Wii::initGfx() {
|
|
gfx_set_underscan(ConfMan.getInt("wii_video_default_underscan_x"),
|
|
ConfMan.getInt("wii_video_default_underscan_y"));
|
|
|
|
_overlayWidth = gfx_video_get_width();
|
|
_overlayHeight = gfx_video_get_height();
|
|
|
|
#ifndef GAMECUBE
|
|
if (CONF_GetAspectRatio() && _fullscreen)
|
|
_overlayHeight = 400;
|
|
#endif
|
|
|
|
_overlaySize = _overlayWidth * _overlayHeight * 2;
|
|
_overlayPixels = (OverlayColor *) memalign(32, _overlaySize);
|
|
|
|
memset(&_texMouse, 0, sizeof(gfx_tex_t));
|
|
memset(&_texOverlay, 0, sizeof(gfx_tex_t));
|
|
memset(&_texGame, 0, sizeof(gfx_tex_t));
|
|
|
|
_cursorPalette = (u16 *) malloc(256 * 2);
|
|
if (!_cursorPalette) {
|
|
printf("could not alloc palette buffer\n");
|
|
::abort();
|
|
}
|
|
|
|
memset(_cursorPalette, 0, 256 * 2);
|
|
|
|
if (!gfx_tex_init(&_texOverlay, GFX_TF_RGB5A3, 0,
|
|
_overlayWidth, _overlayHeight)) {
|
|
printf("could not init the overlay texture\n");
|
|
::abort();
|
|
}
|
|
|
|
gfx_coords(&_coordsOverlay, &_texOverlay, GFX_COORD_FULLSCREEN);
|
|
}
|
|
|
|
void OSystem_Wii::deinitGfx() {
|
|
gfx_tex_deinit(&_texMouse);
|
|
gfx_tex_deinit(&_texGame);
|
|
gfx_tex_deinit(&_texOverlay);
|
|
|
|
free(_cursorPalette);
|
|
_cursorPalette = NULL;
|
|
|
|
free(_gamePixels);
|
|
_gamePixels = NULL;
|
|
|
|
free(_overlayPixels);
|
|
_overlayPixels = NULL;
|
|
}
|
|
|
|
void OSystem_Wii::updateScreenResolution() {
|
|
if (_overlayVisible) {
|
|
_currentWidth = _overlayWidth;
|
|
_currentHeight = _overlayHeight;
|
|
} else {
|
|
_currentWidth = _gameWidth;
|
|
_currentHeight = _gameHeight;
|
|
}
|
|
|
|
if (_currentWidth > 0)
|
|
_currentXScale = f32(gfx_video_get_width()) / f32(_currentWidth);
|
|
else
|
|
_currentXScale = 1.0;
|
|
|
|
if (_currentHeight > 0)
|
|
_currentYScale = f32(gfx_video_get_height()) / f32(_currentHeight);
|
|
else
|
|
_currentYScale = 1.0;
|
|
|
|
updateEventScreenResolution();
|
|
}
|
|
|
|
void OSystem_Wii::switchVideoMode(int mode) {
|
|
static const struct {
|
|
gfx_video_mode_t mode;
|
|
bool filter;
|
|
} map[] = {
|
|
{ GFX_MODE_DEFAULT, false },
|
|
{ GFX_MODE_DEFAULT, true },
|
|
{ GFX_MODE_DS, false },
|
|
{ GFX_MODE_DS, true }
|
|
};
|
|
|
|
if (_gameHeight > 240) {
|
|
if (mode == gmDoubleStrike)
|
|
mode = gmStandard;
|
|
else if (mode == gmDoubleStrikeFiltered)
|
|
mode = gmStandardFiltered;
|
|
}
|
|
|
|
printf("switchVideoMode %d\n", mode);
|
|
|
|
if (map[_actualGraphicsMode].mode != map[mode].mode) {
|
|
GXRModeObj obj;
|
|
|
|
gfx_video_deinit();
|
|
gfx_video_get_modeobj(&obj, GFX_STANDARD_AUTO, map[mode].mode);
|
|
gfx_video_init(&obj);
|
|
gfx_init();
|
|
gfx_con_init(NULL);
|
|
}
|
|
|
|
_actualGraphicsMode = mode;
|
|
|
|
_bilinearFilter = map[mode].filter;
|
|
gfx_tex_set_bilinear_filter(&_texGame, _bilinearFilter);
|
|
gfx_tex_set_bilinear_filter(&_texMouse, _bilinearFilter);
|
|
|
|
u16 usx, usy;
|
|
if (map[mode].mode == GFX_MODE_DS) {
|
|
usx = ConfMan.getInt("wii_video_ds_underscan_x",
|
|
Common::ConfigManager::kApplicationDomain);
|
|
usy = ConfMan.getInt("wii_video_ds_underscan_y",
|
|
Common::ConfigManager::kApplicationDomain);
|
|
} else {
|
|
usx = ConfMan.getInt("wii_video_default_underscan_x",
|
|
Common::ConfigManager::kApplicationDomain);
|
|
usy = ConfMan.getInt("wii_video_default_underscan_y",
|
|
Common::ConfigManager::kApplicationDomain);
|
|
}
|
|
|
|
gfx_set_underscan(usx, usy);
|
|
gfx_coords(&_coordsOverlay, &_texOverlay, GFX_COORD_FULLSCREEN);
|
|
gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN);
|
|
updateScreenResolution();
|
|
}
|
|
|
|
const OSystem::GraphicsMode* OSystem_Wii::getSupportedGraphicsModes() const {
|
|
return _supportedGraphicsModes;
|
|
}
|
|
|
|
int OSystem_Wii::getDefaultGraphicsMode() const {
|
|
return gmStandard;
|
|
}
|
|
|
|
bool OSystem_Wii::setGraphicsMode(int mode) {
|
|
_configGraphicsMode = mode;
|
|
return true;
|
|
}
|
|
|
|
int OSystem_Wii::getGraphicsMode() const {
|
|
return _configGraphicsMode;
|
|
}
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
Graphics::PixelFormat OSystem_Wii::getScreenFormat() const {
|
|
return _pfGame;
|
|
}
|
|
|
|
Common::List<Graphics::PixelFormat> OSystem_Wii::getSupportedFormats() const {
|
|
Common::List<Graphics::PixelFormat> res;
|
|
res.push_back(_pfRGB565);
|
|
res.push_back(Graphics::PixelFormat::createFormatCLUT8());
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
void OSystem_Wii::initSize(uint width, uint height,
|
|
const Graphics::PixelFormat *format) {
|
|
bool update = false;
|
|
gfx_tex_format_t tex_format;
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
Graphics::PixelFormat newFormat;
|
|
|
|
if (format)
|
|
newFormat = *format;
|
|
else
|
|
newFormat = Graphics::PixelFormat::createFormatCLUT8();
|
|
|
|
if (newFormat.bytesPerPixel > 2)
|
|
newFormat = Graphics::PixelFormat::createFormatCLUT8();
|
|
|
|
if (_pfGame != newFormat) {
|
|
_pfGame = newFormat;
|
|
update = true;
|
|
}
|
|
#endif
|
|
|
|
uint newWidth, newHeight;
|
|
if (_pfGame.bytesPerPixel > 1) {
|
|
newWidth = ROUNDUP(width, 4);
|
|
newHeight = ROUNDUP(height, 4);
|
|
} else {
|
|
newWidth = ROUNDUP(width, 8);
|
|
newHeight = ROUNDUP(height, 4);
|
|
}
|
|
|
|
if (_gameWidth != newWidth || _gameHeight != newHeight) {
|
|
assert((newWidth <= 640) && (newHeight <= 480));
|
|
|
|
if (width != newWidth || height != newHeight)
|
|
printf("extending texture for compability: %ux%u -> %ux%u\n",
|
|
width, height, newWidth, newHeight);
|
|
|
|
_gameWidth = newWidth;
|
|
_gameHeight = newHeight;
|
|
update = true;
|
|
}
|
|
|
|
if (_gameRunning) {
|
|
switchVideoMode(_configGraphicsMode);
|
|
|
|
if (_arCorrection && (_gameWidth == 320) && (_gameHeight == 200))
|
|
gfx_set_ar(320.0 / 240.0);
|
|
else
|
|
gfx_set_ar(f32(_gameWidth) / f32(_gameHeight));
|
|
}
|
|
|
|
if (update) {
|
|
free(_gamePixels);
|
|
|
|
tex_format = GFX_TF_PALETTE_RGB565;
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
if (_pfGame.bytesPerPixel > 1) {
|
|
tex_format = GFX_TF_RGB565;
|
|
_pfGameTexture = _pfRGB565;
|
|
}
|
|
|
|
printf("initSize %u*%u*%u (%u%u%u -> %u%u%u match: %d)\n",
|
|
_gameWidth, _gameHeight, _pfGame.bytesPerPixel * 8,
|
|
8 - _pfGame.rLoss, 8 - _pfGame.gLoss, 8 - _pfGame.bLoss,
|
|
8 - _pfGameTexture.rLoss, 8 - _pfGameTexture.gLoss,
|
|
8 - _pfGameTexture.bLoss, _pfGame == _pfGameTexture);
|
|
|
|
_gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight *
|
|
_pfGame.bytesPerPixel);
|
|
memset(_gamePixels, 0, _gameWidth * _gameHeight *
|
|
_pfGame.bytesPerPixel);
|
|
#else
|
|
printf("initSize %u*%u\n", _gameWidth, _gameHeight);
|
|
|
|
_gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight);
|
|
memset(_gamePixels, 0, _gameWidth * _gameHeight);
|
|
#endif
|
|
|
|
if (!gfx_tex_init(&_texGame, tex_format, TLUT_GAME,
|
|
_gameWidth, _gameHeight)) {
|
|
printf("could not init the game texture\n");
|
|
::abort();
|
|
}
|
|
|
|
gfx_tex_set_bilinear_filter(&_texGame, _bilinearFilter);
|
|
gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN);
|
|
|
|
updateScreenResolution();
|
|
}
|
|
}
|
|
|
|
int16 OSystem_Wii::getWidth() {
|
|
return _gameWidth;
|
|
}
|
|
|
|
int16 OSystem_Wii::getHeight() {
|
|
return _gameHeight;
|
|
}
|
|
|
|
void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) {
|
|
#ifdef USE_RGB_COLOR
|
|
assert(_pfGame.bytesPerPixel == 1);
|
|
#endif
|
|
|
|
const byte *s = colors;
|
|
u16 *d = _texGame.palette;
|
|
|
|
for (uint i = 0; i < num; ++i, s +=3)
|
|
d[start + i] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(s[0], s[1], s[2]);
|
|
|
|
gfx_tex_flush_palette(&_texGame);
|
|
|
|
s = colors;
|
|
d = _cursorPalette;
|
|
|
|
for (uint i = 0; i < num; ++i, s += 3) {
|
|
d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
|
|
}
|
|
|
|
if (_cursorPaletteDisabled) {
|
|
assert(_texMouse.palette);
|
|
|
|
memcpy((u8 *)_texMouse.palette + start * 2,
|
|
(u8 *)_cursorPalette + start * 2, num * 2);
|
|
|
|
_cursorPaletteDirty = true;
|
|
}
|
|
}
|
|
|
|
void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) {
|
|
#ifdef USE_RGB_COLOR
|
|
assert(_pfGame.bytesPerPixel == 1);
|
|
#endif
|
|
|
|
u16 *s = _texGame.palette;
|
|
byte *d = colors;
|
|
|
|
u8 r, g, b;
|
|
for (uint i = 0; i < num; ++i, d += 3) {
|
|
Graphics::colorToRGB<Graphics::ColorMasks<565> >(s[start + i], r, g, b);
|
|
d[0] = r;
|
|
d[1] = g;
|
|
d[2] = b;
|
|
}
|
|
}
|
|
|
|
void OSystem_Wii::setCursorPalette(const byte *colors, uint start, uint num) {
|
|
if (!_texMouse.palette) {
|
|
printf("switching to palette based cursor\n");
|
|
|
|
if (!gfx_tex_init(&_texMouse, GFX_TF_PALETTE_RGB5A3, TLUT_MOUSE,
|
|
16, 16)) {
|
|
printf("could not init the mouse texture\n");
|
|
::abort();
|
|
}
|
|
|
|
gfx_tex_set_bilinear_filter(&_texMouse, _bilinearFilter);
|
|
}
|
|
|
|
if (_cursorPaletteDisabled) {
|
|
memcpy(_cursorPalette, _texMouse.palette, 256 * 2);
|
|
_cursorPaletteDisabled = false;
|
|
}
|
|
|
|
const byte *s = colors;
|
|
u16 *d = _texMouse.palette;
|
|
|
|
for (uint i = 0; i < num; ++i, s += 3)
|
|
d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
|
|
|
|
_cursorPaletteDirty = true;
|
|
}
|
|
|
|
void OSystem_Wii::copyRectToScreen(const byte *buf, int pitch, int x, int y,
|
|
int w, int h) {
|
|
assert(x >= 0 && x < _gameWidth);
|
|
assert(y >= 0 && y < _gameHeight);
|
|
assert(w > 0 && x + w <= _gameWidth);
|
|
assert(h > 0 && y + h <= _gameHeight);
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
if (_pfGame.bytesPerPixel > 1) {
|
|
if (!Graphics::crossBlit(_gamePixels +
|
|
y * _gameWidth * _pfGame.bytesPerPixel +
|
|
x * _pfGame.bytesPerPixel,
|
|
buf, _gameWidth * _pfGame.bytesPerPixel,
|
|
pitch, w, h, _pfGameTexture, _pfGame)) {
|
|
printf("crossBlit failed\n");
|
|
::abort();
|
|
}
|
|
} else {
|
|
#endif
|
|
byte *dst = _gamePixels + y * _gameWidth + x;
|
|
if (_gameWidth == pitch && pitch == w) {
|
|
memcpy(dst, buf, h * w);
|
|
} else {
|
|
do {
|
|
memcpy(dst, buf, w);
|
|
buf += pitch;
|
|
dst += _gameWidth;
|
|
} while (--h);
|
|
}
|
|
#ifdef USE_RGB_COLOR
|
|
}
|
|
#endif
|
|
|
|
_gameDirty = true;
|
|
}
|
|
|
|
bool OSystem_Wii::needsScreenUpdate() {
|
|
if (getMillis() - _lastScreenUpdate < 1000 / MAX_FPS)
|
|
return false;
|
|
|
|
if (_gameRunning && _gameDirty)
|
|
return true;
|
|
|
|
if (_overlayVisible && _overlayDirty)
|
|
return true;
|
|
|
|
if (_mouseVisible && _texMouse.palette && _cursorPaletteDirty)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void OSystem_Wii::updateScreen() {
|
|
static f32 ar;
|
|
static gfx_screen_coords_t cc;
|
|
static int cs;
|
|
|
|
u32 now = getMillis();
|
|
if (now - _lastScreenUpdate < 1000 / MAX_FPS)
|
|
return;
|
|
|
|
if (!gfx_frame_start()) {
|
|
printf("last frame not done!\n");
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG_WII_MEMSTATS
|
|
wii_memstats();
|
|
#endif
|
|
|
|
cs = _cursorScale;
|
|
_lastScreenUpdate = now;
|
|
|
|
if (_overlayVisible || _consoleVisible)
|
|
gfx_set_colorop(COLOROP_SIMPLEFADE, gfx_color_none, gfx_color_none);
|
|
|
|
if (_gameRunning) {
|
|
if (_gameDirty) {
|
|
gfx_tex_convert(&_texGame, _gamePixels);
|
|
_gameDirty = false;
|
|
}
|
|
|
|
gfx_draw_tex(&_texGame, &_coordsGame);
|
|
}
|
|
|
|
if (_overlayVisible) {
|
|
if (!_consoleVisible)
|
|
gfx_set_colorop(COLOROP_NONE, gfx_color_none, gfx_color_none);
|
|
|
|
if (_gameRunning)
|
|
ar = gfx_set_ar(4.0 / 3.0);
|
|
|
|
// ugly, but the modern theme sets a factor of 3, only god knows why
|
|
if (cs > 2)
|
|
cs = 1;
|
|
else
|
|
cs *= 2;
|
|
|
|
if (_overlayDirty) {
|
|
gfx_tex_convert(&_texOverlay, _overlayPixels);
|
|
_overlayDirty = false;
|
|
}
|
|
|
|
gfx_draw_tex(&_texOverlay, &_coordsOverlay);
|
|
}
|
|
|
|
if (_mouseVisible) {
|
|
cc.x = f32(_mouseX - cs * _mouseHotspotX) * _currentXScale;
|
|
cc.y = f32(_mouseY - cs * _mouseHotspotY) * _currentYScale;
|
|
cc.w = f32(_texMouse.width) * _currentXScale * cs;
|
|
cc.h = f32(_texMouse.height) * _currentYScale * cs;
|
|
|
|
if (_texMouse.palette && _cursorPaletteDirty) {
|
|
_texMouse.palette[_mouseKeyColor] = 0;
|
|
gfx_tex_flush_palette(&_texMouse);
|
|
_cursorPaletteDirty = false;
|
|
}
|
|
|
|
gfx_draw_tex(&_texMouse, &cc);
|
|
}
|
|
|
|
if (_consoleVisible)
|
|
gfx_con_draw();
|
|
|
|
if (_overlayVisible && _gameRunning)
|
|
gfx_set_ar(ar);
|
|
|
|
gfx_frame_end();
|
|
}
|
|
|
|
Graphics::Surface *OSystem_Wii::lockScreen() {
|
|
_surface.pixels = _gamePixels;
|
|
_surface.w = _gameWidth;
|
|
_surface.h = _gameHeight;
|
|
#ifdef USE_RGB_COLOR
|
|
_surface.pitch = _gameWidth * _pfGame.bytesPerPixel;
|
|
_surface.format = _pfGame;
|
|
#else
|
|
_surface.pitch = _gameWidth;
|
|
_surface.format = Graphics::PixelFormat::createFormatCLUT8();
|
|
#endif
|
|
|
|
return &_surface;
|
|
}
|
|
|
|
void OSystem_Wii::unlockScreen() {
|
|
_gameDirty = true;
|
|
}
|
|
|
|
void OSystem_Wii::setShakePos(int shakeOffset) {
|
|
gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN);
|
|
_coordsGame.y -= f32(shakeOffset) * _currentYScale;
|
|
}
|
|
|
|
void OSystem_Wii::showOverlay() {
|
|
_mouseX = _overlayWidth / 2;
|
|
_mouseY = _overlayHeight / 2;
|
|
_overlayVisible = true;
|
|
updateScreenResolution();
|
|
gfx_tex_set_bilinear_filter(&_texMouse, true);
|
|
}
|
|
|
|
void OSystem_Wii::hideOverlay() {
|
|
_mouseX = _gameWidth / 2;
|
|
_mouseY = _gameHeight / 2;
|
|
_overlayVisible = false;
|
|
updateScreenResolution();
|
|
gfx_tex_set_bilinear_filter(&_texMouse, _bilinearFilter);
|
|
}
|
|
|
|
void OSystem_Wii::clearOverlay() {
|
|
memset(_overlayPixels, 0, _overlaySize);
|
|
_overlayDirty = true;
|
|
}
|
|
|
|
void OSystem_Wii::grabOverlay(OverlayColor *buf, int pitch) {
|
|
int h = _overlayHeight;
|
|
OverlayColor *src = _overlayPixels;
|
|
|
|
do {
|
|
memcpy(buf, src, _overlayWidth * sizeof(OverlayColor));
|
|
src += _overlayWidth;
|
|
buf += pitch;
|
|
} while (--h);
|
|
}
|
|
|
|
void OSystem_Wii::copyRectToOverlay(const OverlayColor *buf, int pitch, int x,
|
|
int y, int w, int h) {
|
|
if (x < 0) {
|
|
w += x;
|
|
buf -= x;
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0) {
|
|
h += y;
|
|
buf -= y * pitch;
|
|
y = 0;
|
|
}
|
|
|
|
if (w > _overlayWidth - x)
|
|
w = _overlayWidth - x;
|
|
|
|
if (h > _overlayHeight - y)
|
|
h = _overlayHeight - y;
|
|
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
OverlayColor *dst = _overlayPixels + (y * _overlayWidth + x);
|
|
if (_overlayWidth == pitch && pitch == w) {
|
|
memcpy(dst, buf, h * w * sizeof(OverlayColor));
|
|
} else {
|
|
do {
|
|
memcpy(dst, buf, w * sizeof(OverlayColor));
|
|
buf += pitch;
|
|
dst += _overlayWidth;
|
|
} while (--h);
|
|
}
|
|
|
|
_overlayDirty = true;
|
|
}
|
|
|
|
int16 OSystem_Wii::getOverlayWidth() {
|
|
return _overlayWidth;
|
|
}
|
|
|
|
int16 OSystem_Wii::getOverlayHeight() {
|
|
return _overlayHeight;
|
|
}
|
|
|
|
Graphics::PixelFormat OSystem_Wii::getOverlayFormat() const {
|
|
return Graphics::createPixelFormat<3444>();
|
|
}
|
|
|
|
bool OSystem_Wii::showMouse(bool visible) {
|
|
bool last = _mouseVisible;
|
|
_mouseVisible = visible;
|
|
|
|
return last;
|
|
}
|
|
|
|
void OSystem_Wii::warpMouse(int x, int y) {
|
|
_mouseX = x;
|
|
_mouseY = y;
|
|
}
|
|
|
|
void OSystem_Wii::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX,
|
|
int hotspotY, uint32 keycolor,
|
|
bool dontScale,
|
|
const Graphics::PixelFormat *format) {
|
|
gfx_tex_format_t tex_format = GFX_TF_PALETTE_RGB5A3;
|
|
uint tw, th;
|
|
bool tmpBuf = false;
|
|
uint32 oldKeycolor = _mouseKeyColor;
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
if (!format)
|
|
_pfCursor = Graphics::PixelFormat::createFormatCLUT8();
|
|
else
|
|
_pfCursor = *format;
|
|
|
|
if (_pfCursor.bytesPerPixel > 1) {
|
|
tex_format = GFX_TF_RGB5A3;
|
|
_mouseKeyColor = keycolor & 0xffff;
|
|
tw = ROUNDUP(w, 4);
|
|
th = ROUNDUP(h, 4);
|
|
|
|
if (_pfCursor != _pfRGB3444)
|
|
tmpBuf = true;
|
|
} else {
|
|
#endif
|
|
_mouseKeyColor = keycolor & 0xff;
|
|
tw = ROUNDUP(w, 8);
|
|
th = ROUNDUP(h, 4);
|
|
#ifdef USE_RGB_COLOR
|
|
}
|
|
#endif
|
|
|
|
if (!gfx_tex_init(&_texMouse, tex_format, TLUT_MOUSE, tw, th)) {
|
|
printf("could not init the mouse texture\n");
|
|
::abort();
|
|
}
|
|
|
|
gfx_tex_set_bilinear_filter(&_texMouse, _bilinearFilter);
|
|
|
|
if ((tw != w) || (th != h))
|
|
tmpBuf = true;
|
|
|
|
if (!tmpBuf) {
|
|
gfx_tex_convert(&_texMouse, buf);
|
|
} else {
|
|
u8 bpp = _texMouse.bpp >> 3;
|
|
byte *tmp = (byte *) malloc(tw * th * bpp);
|
|
|
|
if (!tmp) {
|
|
printf("could not alloc temp cursor buffer\n");
|
|
::abort();
|
|
}
|
|
|
|
if (bpp > 1)
|
|
memset(tmp, 0, tw * th * bpp);
|
|
else
|
|
memset(tmp, _mouseKeyColor, tw * th);
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
if (bpp > 1) {
|
|
if (!Graphics::crossBlit(tmp, buf,
|
|
tw * _pfRGB3444.bytesPerPixel,
|
|
w * _pfCursor.bytesPerPixel,
|
|
tw, th, _pfRGB3444, _pfCursor)) {
|
|
printf("crossBlit failed (cursor)\n");
|
|
::abort();
|
|
}
|
|
|
|
// nasty, shouldn't the frontend set the alpha channel?
|
|
u16 *s = (u16 *) buf;
|
|
u16 *d = (u16 *) tmp;
|
|
for (u16 y = 0; y < h; ++y) {
|
|
for (u16 x = 0; x < w; ++x) {
|
|
if (*s++ != _mouseKeyColor)
|
|
*d++ |= 7 << 12;
|
|
else
|
|
d++;
|
|
}
|
|
|
|
d += tw - w;
|
|
}
|
|
} else {
|
|
#endif
|
|
byte *dst = tmp;
|
|
|
|
do {
|
|
memcpy(dst, buf, w * bpp);
|
|
buf += w * bpp;
|
|
dst += tw * bpp;
|
|
} while (--h);
|
|
#ifdef USE_RGB_COLOR
|
|
}
|
|
#endif
|
|
|
|
gfx_tex_convert(&_texMouse, tmp);
|
|
free(tmp);
|
|
}
|
|
|
|
_mouseHotspotX = hotspotX;
|
|
_mouseHotspotY = hotspotY;
|
|
// TODO: Adapt to new dontScale logic!
|
|
_cursorScale = 1;
|
|
|
|
if ((_texMouse.palette) && (oldKeycolor != _mouseKeyColor))
|
|
_cursorPaletteDirty = true;
|
|
}
|