mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
When the engine doesn't sepcify any cursor, an empty cursor is on the stack. When restoring it after displaying the virtual keyboard, if the game is not CLUT8, the game and the cursor palette are nullptr. In this case, clear the palette.
789 lines
18 KiB
C++
789 lines
18 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#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/blit.h"
|
|
#include "backends/fs/wii/wii-fs-factory.h"
|
|
|
|
#include "osystem.h"
|
|
|
|
// Uncomment this to enable debug output to console
|
|
//#define PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
|
|
#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 = (uint16 *) 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 (_overlayInGUI) {
|
|
_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, uint flags) {
|
|
_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;
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
if (_pfGame.bytesPerPixel > 1) {
|
|
newWidth = ROUNDUP(width, 4);
|
|
newHeight = ROUNDUP(height, 4);
|
|
} else {
|
|
#endif
|
|
newWidth = ROUNDUP(width, 8);
|
|
newHeight = ROUNDUP(height, 4);
|
|
#ifdef USE_RGB_COLOR
|
|
}
|
|
#endif
|
|
|
|
if (_gameWidth != newWidth || _gameHeight != newHeight) {
|
|
assert((newWidth <= 640) && (newHeight <= 480));
|
|
|
|
if (width != newWidth || height != newHeight)
|
|
printf("extending texture for compatibility: %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::updateMousePalette() {
|
|
#ifdef PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
printf("%s() _cursorPaletteDisabled:%d\n", __func__, _cursorPaletteDisabled);
|
|
#endif
|
|
|
|
if (_texMouse.palette) {
|
|
if (!_cursorPaletteDisabled) {
|
|
memcpy(_texMouse.palette, _cursorPalette, 256 * 2);
|
|
#ifdef USE_RGB_COLOR
|
|
} else if (_pfGame.bytesPerPixel != 1) {
|
|
// When restoring the palette, there may be cases where game doesn't have any palette
|
|
// In this case, clear the palette
|
|
memset(_texMouse.palette, 0, 256 * 2);
|
|
#endif
|
|
} else {
|
|
memcpy(_texMouse.palette, _texGame.palette, 256 * 2);
|
|
}
|
|
|
|
_cursorPaletteDirty = true;
|
|
}
|
|
}
|
|
|
|
void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) {
|
|
#ifdef PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
printf("%s(%p, %d, %d) _cursorPaletteDisabled:%d\n", __func__, colors, start, num, _cursorPaletteDisabled);
|
|
#endif
|
|
|
|
#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] = _pfRGB565.RGBToColor(s[0], s[1], s[2]);
|
|
|
|
gfx_tex_flush_palette(&_texGame);
|
|
|
|
updateMousePalette();
|
|
}
|
|
|
|
void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) const {
|
|
#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) {
|
|
_pfRGB565.colorToRGB(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) {
|
|
#ifdef PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
printf("%s(%p,%u,%u) _cursorPaletteDisabled:%d\n", __func__, colors, start, num, _cursorPaletteDisabled);
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
_cursorPaletteDisabled = false;
|
|
|
|
const byte *s = colors;
|
|
u16 *d = _cursorPalette;
|
|
|
|
for (uint i = 0; i < num; ++i, s += 3) {
|
|
d[start + i] = _pfRGB3444.ARGBToColor(0xff, s[0], s[1], s[2]);
|
|
}
|
|
|
|
updateMousePalette();
|
|
}
|
|
|
|
void OSystem_Wii::copyRectToScreen(const void *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,
|
|
(const byte *)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 {
|
|
const byte *src = (const byte *)buf;
|
|
do {
|
|
memcpy(dst, src, w);
|
|
src += 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 f32 csx, csy;
|
|
|
|
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
|
|
|
|
_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);
|
|
|
|
if (_overlayDirty) {
|
|
gfx_tex_convert(&_texOverlay, _overlayPixels);
|
|
_overlayDirty = false;
|
|
}
|
|
|
|
gfx_draw_tex(&_texOverlay, &_coordsOverlay);
|
|
}
|
|
|
|
if (_mouseVisible) {
|
|
if (_cursorDontScale) {
|
|
csx = 1.0f / _currentXScale;
|
|
csy = 1.0f / _currentYScale;
|
|
} else {
|
|
csx = 1.0f;
|
|
csy = 1.0f;
|
|
}
|
|
|
|
cc.x = f32(_mouseX - csx * _mouseHotspotX) * _currentXScale;
|
|
cc.y = f32(_mouseY - csy * _mouseHotspotY) * _currentYScale;
|
|
cc.w = f32(_texMouse.width) * _currentXScale * csx;
|
|
cc.h = f32(_texMouse.height) * _currentYScale * csy;
|
|
|
|
if (_texMouse.palette && _cursorPaletteDirty) {
|
|
_texMouse.palette[_mouseKeyColor] = 0;
|
|
gfx_tex_flush_palette(&_texMouse);
|
|
_cursorPaletteDirty = false;
|
|
}
|
|
|
|
#ifdef PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
//printf("%s() cc.x:%f cc.y:%f cc.w:%f cc.h:%f xscale:%f yscale:%f\n", __func__, cc.x, cc.y, cc.w, cc.h, _currentXScale, _currentYScale);
|
|
#endif
|
|
|
|
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.init(_gameWidth, _gameHeight,
|
|
#ifdef USE_RGB_COLOR
|
|
_gameWidth * _pfGame.bytesPerPixel, _gamePixels, _pfGame
|
|
#else
|
|
_gameWidth, _gamePixels, Graphics::PixelFormat::createFormatCLUT8()
|
|
#endif
|
|
);
|
|
|
|
return &_surface;
|
|
}
|
|
|
|
void OSystem_Wii::unlockScreen() {
|
|
_gameDirty = true;
|
|
}
|
|
|
|
void OSystem_Wii::setShakePos(int shakeXOffset, int shakeYOffset) {
|
|
gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN);
|
|
_coordsGame.x -= f32(shakeXOffset) * _currentXScale;
|
|
_coordsGame.y -= f32(shakeYOffset) * _currentYScale;
|
|
}
|
|
|
|
void OSystem_Wii::showOverlay(bool inGUI) {
|
|
if (inGUI) {
|
|
_mouseX = _overlayWidth / 2;
|
|
_mouseY = _overlayHeight / 2;
|
|
}
|
|
_overlayInGUI = inGUI;
|
|
_overlayVisible = true;
|
|
updateScreenResolution();
|
|
gfx_tex_set_bilinear_filter(&_texMouse, true);
|
|
}
|
|
|
|
void OSystem_Wii::hideOverlay() {
|
|
if (_overlayInGUI) {
|
|
_mouseX = _gameWidth / 2;
|
|
_mouseY = _gameHeight / 2;
|
|
}
|
|
_overlayInGUI = false;
|
|
_overlayVisible = false;
|
|
updateScreenResolution();
|
|
gfx_tex_set_bilinear_filter(&_texMouse, _bilinearFilter);
|
|
}
|
|
|
|
void OSystem_Wii::clearOverlay() {
|
|
memset(_overlayPixels, 0, _overlaySize);
|
|
_overlayDirty = true;
|
|
}
|
|
|
|
void OSystem_Wii::grabOverlay(Graphics::Surface &surface) {
|
|
assert(surface.w >= _overlayWidth);
|
|
assert(surface.h >= _overlayHeight);
|
|
assert(surface.format.bytesPerPixel == sizeof(uint16));
|
|
|
|
byte *src = (byte *)_overlayPixels;
|
|
byte *dst = (byte *)surface.getPixels();
|
|
Graphics::copyBlit(dst, src, surface.pitch, _overlayWidth * sizeof(uint16),
|
|
_overlayWidth, _overlayHeight, sizeof(uint16));
|
|
}
|
|
|
|
void OSystem_Wii::copyRectToOverlay(const void *buf, int pitch, int x,
|
|
int y, int w, int h) {
|
|
const byte *src = (const byte *)buf;
|
|
if (x < 0) {
|
|
w += x;
|
|
src -= x * sizeof(uint16);
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0) {
|
|
h += y;
|
|
src -= y * pitch;
|
|
y = 0;
|
|
}
|
|
|
|
if (w > _overlayWidth - x)
|
|
w = _overlayWidth - x;
|
|
|
|
if (h > _overlayHeight - y)
|
|
h = _overlayHeight - y;
|
|
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
uint16 *dst = _overlayPixels + (y * _overlayWidth + x);
|
|
if (_overlayWidth == (uint16)w && (uint16)pitch == _overlayWidth * sizeof(uint16)) {
|
|
memcpy(dst, src, h * pitch);
|
|
} else {
|
|
do {
|
|
memcpy(dst, src, w * sizeof(uint16));
|
|
src += 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 _pfRGB3444;
|
|
}
|
|
|
|
bool OSystem_Wii::showMouse(bool visible) {
|
|
bool last = _mouseVisible;
|
|
_mouseVisible = visible;
|
|
|
|
#ifdef PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
if (_mouseVisible != last) {
|
|
printf("%s(%d)\n", __func__, _mouseVisible);
|
|
}
|
|
#endif
|
|
|
|
return last;
|
|
}
|
|
|
|
void OSystem_Wii::warpMouse(int x, int y) {
|
|
_mouseX = x;
|
|
_mouseY = y;
|
|
}
|
|
|
|
void OSystem_Wii::setMouseCursor(const void *buf, uint w, uint h, int hotspotX,
|
|
int hotspotY, uint32 keycolor,
|
|
bool dontScale,
|
|
const Graphics::PixelFormat *format, const byte *mask) {
|
|
#ifdef PLATFORM_WII_OSYSTEM_GFX_DEBUG
|
|
printf("%s(%p, w:%u, h:%u, hsX:%d, hsY:%d, kc:%u, dontScale:%d, %p, %p)\n", __func__, buf, w, h, hotspotX, hotspotY, keycolor, dontScale, format, mask);
|
|
#endif
|
|
|
|
if (mask)
|
|
printf("OSystem_Wii::setMouseCursor: Masks are not supported\n");
|
|
|
|
gfx_tex_format_t tex_format = GFX_TF_PALETTE_RGB5A3;
|
|
uint tw, th;
|
|
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);
|
|
|
|
} 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);
|
|
|
|
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, (const byte *)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?
|
|
const u16 *s = (const 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
|
|
const byte *s = (const byte *)buf;
|
|
byte *d = (byte *) tmp;
|
|
for (u16 y = 0; y < h; ++y) {
|
|
for (u16 x = 0; x < w; ++x) {
|
|
*d++ = *s++;
|
|
}
|
|
d += tw - w;
|
|
}
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
}
|
|
#endif
|
|
|
|
gfx_tex_convert(&_texMouse, tmp);
|
|
free(tmp);
|
|
|
|
_mouseHotspotX = hotspotX;
|
|
_mouseHotspotY = hotspotY;
|
|
_cursorDontScale = dontScale;
|
|
|
|
if (_pfCursor.bytesPerPixel == 1 && oldKeycolor != _mouseKeyColor)
|
|
updateMousePalette();
|
|
}
|