mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-09 19:32:11 +00:00
760 lines
17 KiB
C++
760 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 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"
|
|
|
|
#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 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] = _pfRGB565.RGBToColor(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] = _pfRGB3444.ARGBToColor(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) 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) {
|
|
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] = _pfRGB3444.ARGBToColor(0xff, s[0], s[1], s[2]);
|
|
|
|
_cursorPaletteDirty = true;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
|
|
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) {
|
|
|
|
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 ((_texMouse.palette) && (oldKeycolor != _mouseKeyColor))
|
|
_cursorPaletteDirty = true;
|
|
}
|