mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-01 14:21:41 +00:00
DS: Move graphics code into a separate file
This commit is contained in:
parent
1c40d79732
commit
626b6ac4e9
@ -23,7 +23,7 @@
|
||||
#include <nds.h>
|
||||
|
||||
#include "backends/events/ds/ds-events.h"
|
||||
#include "osystem_ds.h"
|
||||
#include "backends/platform/ds/osystem_ds.h"
|
||||
|
||||
bool DSEventSource::pollEvent(Common::Event &event) {
|
||||
if (_eventQueue.empty()) {
|
||||
|
653
backends/platform/ds/ds-graphics.cpp
Normal file
653
backends/platform/ds/ds-graphics.cpp
Normal file
@ -0,0 +1,653 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nds.h>
|
||||
|
||||
#include "backends/platform/ds/osystem_ds.h"
|
||||
#include "backends/platform/ds/blitters.h"
|
||||
|
||||
#include "common/translation.h"
|
||||
|
||||
namespace DS {
|
||||
|
||||
// From console.c in NDSLib
|
||||
|
||||
// Defines
|
||||
#define SCUMM_GAME_HEIGHT 142
|
||||
#define SCUMM_GAME_WIDTH 227
|
||||
|
||||
// Scaled
|
||||
static int scX;
|
||||
static int scY;
|
||||
|
||||
static int subScX;
|
||||
static int subScY;
|
||||
static int subScTargetX;
|
||||
static int subScTargetY;
|
||||
static int subScreenWidth = SCUMM_GAME_WIDTH;
|
||||
static int subScreenHeight = SCUMM_GAME_HEIGHT;
|
||||
static int subScreenScale = 256;
|
||||
|
||||
static bool gameScreenSwap = false;
|
||||
|
||||
// Shake
|
||||
static int s_shakeXOffset = 0;
|
||||
static int s_shakeYOffset = 0;
|
||||
|
||||
// Touch
|
||||
static int touchScX, touchScY, touchX, touchY;
|
||||
|
||||
// 8-bit surface size
|
||||
static int gameWidth = 320;
|
||||
static int gameHeight = 200;
|
||||
|
||||
void setGameScreenSwap(bool enable) {
|
||||
gameScreenSwap = enable;
|
||||
}
|
||||
|
||||
void setTopScreenZoom(int percentage) {
|
||||
s32 scale = (percentage << 8) / 100;
|
||||
subScreenScale = (256 * 256) / scale;
|
||||
}
|
||||
|
||||
void setTopScreenTarget(int x, int y) {
|
||||
subScTargetX = (x - (subScreenWidth >> 1));
|
||||
subScTargetY = (y - (subScreenHeight >> 1));
|
||||
|
||||
if (subScTargetX < 0) subScTargetX = 0;
|
||||
if (subScTargetX > gameWidth - subScreenWidth) subScTargetX = gameWidth - subScreenWidth;
|
||||
|
||||
if (subScTargetY < 0) subScTargetY = 0;
|
||||
if (subScTargetY > gameHeight - subScreenHeight) subScTargetY = gameHeight - subScreenHeight;
|
||||
|
||||
subScTargetX <<=8;
|
||||
subScTargetY <<=8;
|
||||
}
|
||||
|
||||
void setGameSize(int width, int height) {
|
||||
gameWidth = width;
|
||||
gameHeight = height;
|
||||
}
|
||||
|
||||
int getGameWidth() {
|
||||
return gameWidth;
|
||||
}
|
||||
|
||||
int getGameHeight() {
|
||||
return gameHeight;
|
||||
}
|
||||
|
||||
void displayMode8Bit() {
|
||||
vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
|
||||
|
||||
if (g_system->getGraphicsMode() == GFX_SWSCALE) {
|
||||
REG_BG3CNT = BG_BMP16_256x256 | BG_BMP_BASE(8);
|
||||
|
||||
REG_BG3PA = 256;
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = (int) ((200.0f / 192.0f) * 256);
|
||||
|
||||
} else {
|
||||
REG_BG3CNT = BG_BMP8_512x256 | BG_BMP_BASE(8);
|
||||
|
||||
REG_BG3PA = (int) (((float) (gameWidth) / 256.0f) * 256);
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = (int) ((200.0f / 192.0f) * 256);
|
||||
}
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
REG_BG3CNT_SUB = BG_BMP8_512x256;
|
||||
|
||||
REG_BG3PA_SUB = (int) (subScreenWidth / 256.0f * 256);
|
||||
REG_BG3PB_SUB = 0;
|
||||
REG_BG3PC_SUB = 0;
|
||||
REG_BG3PD_SUB = (int) (subScreenHeight / 192.0f * 256);
|
||||
#endif
|
||||
|
||||
if (gameScreenSwap) {
|
||||
lcdMainOnTop();
|
||||
} else {
|
||||
lcdMainOnBottom();
|
||||
}
|
||||
}
|
||||
|
||||
void setShakePos(int shakeXOffset, int shakeYOffset) {
|
||||
s_shakeXOffset = shakeXOffset;
|
||||
s_shakeYOffset = shakeYOffset;
|
||||
}
|
||||
|
||||
Common::Point warpMouse(int penX, int penY, bool isOverlayShown) {
|
||||
int storedMouseX, storedMouseY;
|
||||
if (!isOverlayShown) {
|
||||
storedMouseX = ((penX - touchX) << 8) / touchScX;
|
||||
storedMouseY = ((penY - touchY) << 8) / touchScY;
|
||||
} else {
|
||||
storedMouseX = penX;
|
||||
storedMouseY = penY;
|
||||
}
|
||||
|
||||
return Common::Point(storedMouseX, storedMouseY);
|
||||
}
|
||||
|
||||
void setMainScreenScroll(int x, int y) {
|
||||
REG_BG3X = x;
|
||||
REG_BG3Y = y;
|
||||
|
||||
if (!gameScreenSwap) {
|
||||
touchX = x >> 8;
|
||||
touchY = y >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void setMainScreenScale(int x, int y) {
|
||||
if ((g_system->getGraphicsMode() == GFX_SWSCALE) && (x==320)) {
|
||||
REG_BG3PA = 256;
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = y;
|
||||
} else {
|
||||
REG_BG3PA = x;
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = y;
|
||||
}
|
||||
|
||||
if (!gameScreenSwap) {
|
||||
touchScX = x;
|
||||
touchScY = y;
|
||||
}
|
||||
}
|
||||
|
||||
void setZoomedScreenScroll(int x, int y, bool shake) {
|
||||
if (gameScreenSwap) {
|
||||
touchX = x >> 8;
|
||||
touchY = y >> 8;
|
||||
}
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
REG_BG3X_SUB = x;
|
||||
REG_BG3Y_SUB = y;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setZoomedScreenScale(int x, int y) {
|
||||
if (gameScreenSwap) {
|
||||
touchScX = x;
|
||||
touchScY = y;
|
||||
}
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
REG_BG3PA_SUB = x;
|
||||
REG_BG3PB_SUB = 0;
|
||||
REG_BG3PC_SUB = 0;
|
||||
REG_BG3PD_SUB = y;
|
||||
#endif
|
||||
}
|
||||
|
||||
Common::Point transformPoint(uint16 x, uint16 y, bool isOverlayShown) {
|
||||
if (!isOverlayShown) {
|
||||
x = ((x * touchScX) >> 8) + touchX;
|
||||
x = CLIP<uint16>(x, 0, gameWidth - 1);
|
||||
|
||||
y = ((y * touchScY) >> 8) + touchY;
|
||||
y = CLIP<uint16>(y, 0, gameHeight - 1);
|
||||
}
|
||||
|
||||
return Common::Point(x, y);
|
||||
}
|
||||
|
||||
void VBlankHandler(void) {
|
||||
int xCenter = subScTargetX + ((subScreenWidth >> 1) << 8);
|
||||
int yCenter = subScTargetY + ((subScreenHeight >> 1) << 8);
|
||||
|
||||
subScreenWidth = (256 * subScreenScale) >> 8;
|
||||
subScreenHeight = (192 * subScreenScale) >> 8;
|
||||
|
||||
if ( ((subScreenWidth) > 256 - 8) && ((subScreenWidth) < 256 + 8) ) {
|
||||
subScreenWidth = 256;
|
||||
subScreenHeight = 192;
|
||||
} else if ( ((subScreenWidth) > 128 - 8) && ((subScreenWidth) < 128 + 8) ) {
|
||||
subScreenWidth = 128;
|
||||
subScreenHeight = 96;
|
||||
} else if (subScreenWidth > 256) {
|
||||
subScreenWidth = 320;
|
||||
subScreenHeight = 200;
|
||||
}
|
||||
|
||||
subScTargetX = xCenter - ((subScreenWidth >> 1) << 8);
|
||||
subScTargetY = yCenter - ((subScreenHeight >> 1) << 8);
|
||||
|
||||
subScTargetX = CLIP(subScTargetX, 0, (gameWidth - subScreenWidth) << 8);
|
||||
subScTargetY = CLIP(subScTargetY, 0, (gameHeight - subScreenHeight) << 8);
|
||||
|
||||
subScX += (subScTargetX - subScX) >> 2;
|
||||
subScY += (subScTargetY - subScY) >> 2;
|
||||
|
||||
if (g_system->getGraphicsMode() == GFX_NOSCALE) {
|
||||
if (scX + 256 > gameWidth - 1) {
|
||||
scX = gameWidth - 1 - 256;
|
||||
}
|
||||
|
||||
if (scX < 0) {
|
||||
scX = 0;
|
||||
}
|
||||
|
||||
if (scY + 192 > gameHeight - 1) {
|
||||
scY = gameHeight - 1 - 192;
|
||||
}
|
||||
|
||||
if (scY < 0) {
|
||||
scY = 0;
|
||||
}
|
||||
|
||||
setZoomedScreenScroll(subScX, subScY, (subScreenWidth != 256) && (subScreenWidth != 128));
|
||||
setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8);
|
||||
|
||||
setMainScreenScroll((scX << 8) + (s_shakeXOffset << 8), (scY << 8) + (s_shakeYOffset << 8));
|
||||
setMainScreenScale(256, 256); // 1:1 scale
|
||||
} else {
|
||||
if (scY > gameHeight - 192 - 1) {
|
||||
scY = gameHeight - 192 - 1;
|
||||
}
|
||||
|
||||
if (scY < 0) {
|
||||
scY = 0;
|
||||
}
|
||||
|
||||
setZoomedScreenScroll(subScX, subScY, (subScreenWidth != 256) && (subScreenWidth != 128));
|
||||
setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8);
|
||||
|
||||
setMainScreenScroll(64 + (s_shakeXOffset << 8), (scY << 8) + (s_shakeYOffset << 8));
|
||||
setMainScreenScale(320, 256); // 1:1 scale
|
||||
}
|
||||
}
|
||||
|
||||
void setTalkPos(int x, int y) {
|
||||
setTopScreenTarget(x, y);
|
||||
}
|
||||
|
||||
void initHardware() {
|
||||
powerOn(POWER_ALL);
|
||||
|
||||
for (int r = 0; r < 255; r++) {
|
||||
BG_PALETTE[r] = 0;
|
||||
}
|
||||
|
||||
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
|
||||
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
|
||||
vramSetBankE(VRAM_E_MAIN_SPRITE);
|
||||
|
||||
REG_BG2CNT = BG_BMP16_256x256;
|
||||
REG_BG2PA = 256;
|
||||
REG_BG2PB = 0;
|
||||
REG_BG2PC = 0;
|
||||
REG_BG2PD = 256;
|
||||
|
||||
scX = 0;
|
||||
scY = 0;
|
||||
subScX = 0;
|
||||
subScY = 0;
|
||||
subScTargetX = 0;
|
||||
subScTargetY = 0;
|
||||
|
||||
lcdMainOnBottom();
|
||||
|
||||
//irqs are nice
|
||||
irqSet(IRQ_VBLANK, VBlankHandler);
|
||||
irqEnable(IRQ_VBLANK);
|
||||
|
||||
#ifndef DISABLE_TEXT_CONSOLE
|
||||
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
|
||||
vramSetBankH(VRAM_H_SUB_BG);
|
||||
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true);
|
||||
#else
|
||||
videoSetModeSub(MODE_3_2D | DISPLAY_BG3_ACTIVE);
|
||||
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OSystem_DS::initGraphics() {
|
||||
DS::initHardware();
|
||||
|
||||
oamInit(&oamMain, SpriteMapping_Bmp_1D_128, false);
|
||||
_cursorSprite = oamAllocateGfx(&oamMain, SpriteSize_64x64, SpriteColorFormat_Bmp);
|
||||
|
||||
_overlay.create(256, 192, Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15));
|
||||
}
|
||||
|
||||
bool OSystem_DS::hasFeature(Feature f) {
|
||||
return (f == kFeatureCursorPalette) || (f == kFeatureStretchMode);
|
||||
}
|
||||
|
||||
void OSystem_DS::setFeatureState(Feature f, bool enable) {
|
||||
if (f == kFeatureCursorPalette) {
|
||||
_disableCursorPalette = !enable;
|
||||
refreshCursor(_cursorSprite, _cursor, !_disableCursorPalette ? _cursorPalette : _palette);
|
||||
}
|
||||
}
|
||||
|
||||
bool OSystem_DS::getFeatureState(Feature f) {
|
||||
if (f == kFeatureCursorPalette)
|
||||
return !_disableCursorPalette;
|
||||
return false;
|
||||
}
|
||||
|
||||
static const OSystem::GraphicsMode graphicsModes[] = {
|
||||
{ "NONE", _s("Unscaled"), GFX_NOSCALE },
|
||||
{ "HW", _s("Hardware scale (fast, but low quality)"), GFX_HWSCALE },
|
||||
{ "SW", _s("Software scale (good quality, but slower)"), GFX_SWSCALE },
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
|
||||
const OSystem::GraphicsMode *OSystem_DS::getSupportedGraphicsModes() const {
|
||||
return graphicsModes;
|
||||
}
|
||||
|
||||
int OSystem_DS::getDefaultGraphicsMode() const {
|
||||
return GFX_HWSCALE;
|
||||
}
|
||||
|
||||
bool OSystem_DS::setGraphicsMode(int mode) {
|
||||
switch (mode) {
|
||||
case GFX_NOSCALE:
|
||||
case GFX_HWSCALE:
|
||||
case GFX_SWSCALE:
|
||||
_graphicsMode = mode;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int OSystem_DS::getGraphicsMode() const {
|
||||
return _graphicsMode;
|
||||
}
|
||||
|
||||
static const OSystem::GraphicsMode stretchModes[] = {
|
||||
{ "100", "100%", 100 },
|
||||
{ "150", "150%", 150 },
|
||||
{ "200", "200%", 200 },
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
|
||||
const OSystem::GraphicsMode *OSystem_DS::getSupportedStretchModes() const {
|
||||
return stretchModes;
|
||||
}
|
||||
|
||||
int OSystem_DS::getDefaultStretchMode() const {
|
||||
return 100;
|
||||
}
|
||||
|
||||
bool OSystem_DS::setStretchMode(int mode) {
|
||||
_stretchMode = mode;
|
||||
DS::setTopScreenZoom(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
int OSystem_DS::getStretchMode() const {
|
||||
return _stretchMode;
|
||||
}
|
||||
|
||||
void OSystem_DS::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
|
||||
_framebuffer.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
// For Lost in Time, the title screen is displayed in 640x400.
|
||||
// In order to support this game, the screen mode is set, but
|
||||
// all draw calls are ignored until the game switches to 320x200.
|
||||
if ((width == 640) && (height == 400)) {
|
||||
_graphicsEnable = false;
|
||||
} else {
|
||||
_graphicsEnable = true;
|
||||
DS::setGameSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getHeight() {
|
||||
return _framebuffer.h;
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getWidth() {
|
||||
return _framebuffer.w;
|
||||
}
|
||||
|
||||
void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
|
||||
for (unsigned int r = start; r < start + num; r++) {
|
||||
int red = *colors;
|
||||
int green = *(colors + 1);
|
||||
int blue = *(colors + 2);
|
||||
|
||||
red >>= 3;
|
||||
green >>= 3;
|
||||
blue >>= 3;
|
||||
|
||||
{
|
||||
u16 paletteValue = red | (green << 5) | (blue << 10);
|
||||
|
||||
if (!_isOverlayShown) {
|
||||
BG_PALETTE[r] = paletteValue;
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
BG_PALETTE_SUB[r] = paletteValue;
|
||||
#endif
|
||||
}
|
||||
|
||||
_palette[r] = paletteValue;
|
||||
}
|
||||
|
||||
colors += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
|
||||
|
||||
for (unsigned int r = start; r < start + num; r++) {
|
||||
int red = *colors;
|
||||
int green = *(colors + 1);
|
||||
int blue = *(colors + 2);
|
||||
|
||||
red >>= 3;
|
||||
green >>= 3;
|
||||
blue >>= 3;
|
||||
|
||||
u16 paletteValue = red | (green << 5) | (blue << 10);
|
||||
_cursorPalette[r] = paletteValue;
|
||||
|
||||
colors += 3;
|
||||
}
|
||||
|
||||
_disableCursorPalette = false;
|
||||
refreshCursor(_cursorSprite, _cursor, !_disableCursorPalette ? _cursorPalette : _palette);
|
||||
}
|
||||
|
||||
void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) const {
|
||||
for (unsigned int r = start; r < start + num; r++) {
|
||||
*colors++ = (BG_PALETTE[r] & 0x001F) << 3;
|
||||
*colors++ = (BG_PALETTE[r] & 0x03E0) >> 5 << 3;
|
||||
*colors++ = (BG_PALETTE[r] & 0x7C00) >> 10 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
|
||||
_framebuffer.copyRectToSurface(buf, pitch, x, y, w, h);
|
||||
}
|
||||
|
||||
void OSystem_DS::updateScreen() {
|
||||
oamSet(&oamMain, 0, _cursorPos.x - _cursorHotX, _cursorPos.y - _cursorHotY, 0, 15, SpriteSize_64x64,
|
||||
SpriteColorFormat_Bmp, _cursorSprite, 0, false, !_cursorVisible, false, false, false);
|
||||
oamUpdate(&oamMain);
|
||||
|
||||
if (_isOverlayShown) {
|
||||
u16 *back = (u16 *)_overlay.getPixels();
|
||||
dmaCopyHalfWords(3, back, BG_GFX, 256 * 192 * 2);
|
||||
} else if (!_graphicsEnable) {
|
||||
return;
|
||||
} else if (_graphicsMode == GFX_SWSCALE) {
|
||||
u16 *base = BG_GFX + 0x10000;
|
||||
Rescale_320x256xPAL8_To_256x256x1555(
|
||||
base,
|
||||
(const u8 *)_framebuffer.getPixels(),
|
||||
256,
|
||||
_framebuffer.pitch,
|
||||
BG_PALETTE,
|
||||
_framebuffer.h );
|
||||
} else {
|
||||
// The DS video RAM doesn't support 8-bit writes because Nintendo wanted
|
||||
// to save a few pennies/euro cents on the hardware.
|
||||
|
||||
u16 *bg = BG_GFX + 0x10000;
|
||||
s32 stride = 512;
|
||||
|
||||
u16 *src = (u16 *)_framebuffer.getPixels();
|
||||
|
||||
for (int dy = 0; dy < _framebuffer.h; dy++) {
|
||||
DC_FlushRange(src, _framebuffer.w << 1);
|
||||
|
||||
u16 *dest1 = bg + (dy * (stride >> 1));
|
||||
DC_FlushRange(dest1, _framebuffer.w << 1);
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
u16 *dest2 = (u16 *)BG_GFX_SUB + (dy << 8);
|
||||
DC_FlushRange(dest2, _framebuffer.w << 1);
|
||||
|
||||
dmaCopyHalfWordsAsynch(2, src, dest2, _framebuffer.w);
|
||||
#endif
|
||||
dmaCopyHalfWordsAsynch(3, src, dest1, _framebuffer.w);
|
||||
|
||||
while (dmaBusy(2) || dmaBusy(3));
|
||||
|
||||
src += _framebuffer.pitch >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::setShakePos(int shakeXOffset, int shakeYOffset) {
|
||||
DS::setShakePos(shakeXOffset, shakeYOffset);
|
||||
}
|
||||
|
||||
void OSystem_DS::showOverlay() {
|
||||
dmaFillHalfWords(0, BG_GFX, 256 * 192 * 2);
|
||||
videoBgEnable(2);
|
||||
lcdMainOnBottom();
|
||||
_isOverlayShown = true;
|
||||
}
|
||||
|
||||
void OSystem_DS::hideOverlay() {
|
||||
videoBgDisable(2);
|
||||
DS::displayMode8Bit();
|
||||
_isOverlayShown = false;
|
||||
}
|
||||
|
||||
bool OSystem_DS::isOverlayVisible() const {
|
||||
return _isOverlayShown;
|
||||
}
|
||||
|
||||
void OSystem_DS::clearOverlay() {
|
||||
memset(_overlay.getPixels(), 0, _overlay.pitch * _overlay.h);
|
||||
}
|
||||
|
||||
void OSystem_DS::grabOverlay(void *buf, int pitch) {
|
||||
byte *dst = (byte *)buf;
|
||||
|
||||
for (int y = 0; y < _overlay.h; ++y) {
|
||||
memcpy(dst, _overlay.getBasePtr(0, y), _overlay.w * _overlay.format.bytesPerPixel);
|
||||
dst += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
|
||||
_overlay.copyRectToSurface(buf, pitch, x, y, w, h);
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getOverlayHeight() {
|
||||
return _overlay.h;
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getOverlayWidth() {
|
||||
return _overlay.w;
|
||||
}
|
||||
|
||||
Graphics::PixelFormat OSystem_DS::getOverlayFormat() const {
|
||||
return _overlay.format;
|
||||
}
|
||||
|
||||
Common::Point OSystem_DS::transformPoint(uint16 x, uint16 y) {
|
||||
return DS::transformPoint(x, y, _isOverlayShown);
|
||||
}
|
||||
|
||||
bool OSystem_DS::showMouse(bool visible) {
|
||||
const bool last = _cursorVisible;
|
||||
_cursorVisible = visible;
|
||||
return last;
|
||||
}
|
||||
|
||||
void OSystem_DS::warpMouse(int x, int y) {
|
||||
_cursorPos = DS::warpMouse(x, y, _isOverlayShown);
|
||||
}
|
||||
|
||||
void OSystem_DS::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
|
||||
if (!buf || w == 0 || h == 0 || (format && *format != Graphics::PixelFormat::createFormatCLUT8()))
|
||||
return;
|
||||
|
||||
if (_cursor.w != w || _cursor.h != h)
|
||||
_cursor.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
_cursor.copyRectToSurface(buf, w, 0, 0, w, h);
|
||||
_cursorHotX = hotspotX;
|
||||
_cursorHotY = hotspotY;
|
||||
_cursorKey = keycolor;
|
||||
refreshCursor(_cursorSprite, _cursor, !_disableCursorPalette ? _cursorPalette : _palette);
|
||||
}
|
||||
|
||||
void OSystem_DS::refreshCursor(u16 *dst, const Graphics::Surface &src, const uint16 *palette) {
|
||||
uint w = MIN<uint>(src.w, 64);
|
||||
uint h = MIN<uint>(src.h, 64);
|
||||
|
||||
dmaFillHalfWords(0, dst, 64 * 64 * 2);
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
const uint8 *row = (const uint8 *)src.getBasePtr(0, y);
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint8 color = *row++;
|
||||
|
||||
if (color != _cursorKey)
|
||||
dst[y * 64 + x] = palette[color] | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Surface *OSystem_DS::lockScreen() {
|
||||
return &_framebuffer;
|
||||
}
|
||||
|
||||
void OSystem_DS::unlockScreen() {
|
||||
// No need to do anything here. The screen will be updated in updateScreen().
|
||||
}
|
||||
|
||||
void OSystem_DS::setFocusRectangle(const Common::Rect& rect) {
|
||||
DS::setTalkPos(rect.left + rect.width() / 2, rect.top + rect.height() / 2);
|
||||
}
|
||||
|
||||
void OSystem_DS::clearFocusRectangle() {
|
||||
|
||||
}
|
@ -65,327 +65,12 @@
|
||||
// - Memory size for ite
|
||||
// - Try discworld?
|
||||
|
||||
|
||||
// Allow use of stuff in <nds.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
|
||||
|
||||
|
||||
#include <nds.h>
|
||||
#include <filesystem.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dsmain.h"
|
||||
#include "osystem_ds.h"
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include "backends/platform/ds/osystem_ds.h"
|
||||
#include "backends/plugins/ds/ds-provider.h"
|
||||
#include "base/main.h"
|
||||
#include "base/version.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace DS {
|
||||
|
||||
// From console.c in NDSLib
|
||||
|
||||
// Defines
|
||||
#define SCUMM_GAME_HEIGHT 142
|
||||
#define SCUMM_GAME_WIDTH 227
|
||||
|
||||
// Scaled
|
||||
static int scX;
|
||||
static int scY;
|
||||
|
||||
static int subScX;
|
||||
static int subScY;
|
||||
static int subScTargetX;
|
||||
static int subScTargetY;
|
||||
static int subScreenWidth = SCUMM_GAME_WIDTH;
|
||||
static int subScreenHeight = SCUMM_GAME_HEIGHT;
|
||||
static int subScreenScale = 256;
|
||||
|
||||
static bool gameScreenSwap = false;
|
||||
|
||||
// Shake
|
||||
static int s_shakeXOffset = 0;
|
||||
static int s_shakeYOffset = 0;
|
||||
|
||||
// Touch
|
||||
static int touchScX, touchScY, touchX, touchY;
|
||||
|
||||
// 8-bit surface size
|
||||
static int gameWidth = 320;
|
||||
static int gameHeight = 200;
|
||||
|
||||
void setGameScreenSwap(bool enable) {
|
||||
gameScreenSwap = enable;
|
||||
}
|
||||
|
||||
void setTopScreenZoom(int percentage) {
|
||||
s32 scale = (percentage << 8) / 100;
|
||||
subScreenScale = (256 * 256) / scale;
|
||||
}
|
||||
|
||||
void setGameSize(int width, int height) {
|
||||
gameWidth = width;
|
||||
gameHeight = height;
|
||||
}
|
||||
|
||||
int getGameWidth() {
|
||||
return gameWidth;
|
||||
}
|
||||
|
||||
int getGameHeight() {
|
||||
return gameHeight;
|
||||
}
|
||||
|
||||
void displayMode8Bit() {
|
||||
vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
|
||||
|
||||
if (g_system->getGraphicsMode() == GFX_SWSCALE) {
|
||||
REG_BG3CNT = BG_BMP16_256x256 | BG_BMP_BASE(8);
|
||||
|
||||
REG_BG3PA = 256;
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = (int) ((200.0f / 192.0f) * 256);
|
||||
|
||||
} else {
|
||||
REG_BG3CNT = BG_BMP8_512x256 | BG_BMP_BASE(8);
|
||||
|
||||
REG_BG3PA = (int) (((float) (gameWidth) / 256.0f) * 256);
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = (int) ((200.0f / 192.0f) * 256);
|
||||
}
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
REG_BG3CNT_SUB = BG_BMP8_512x256;
|
||||
|
||||
REG_BG3PA_SUB = (int) (subScreenWidth / 256.0f * 256);
|
||||
REG_BG3PB_SUB = 0;
|
||||
REG_BG3PC_SUB = 0;
|
||||
REG_BG3PD_SUB = (int) (subScreenHeight / 192.0f * 256);
|
||||
#endif
|
||||
|
||||
if (gameScreenSwap) {
|
||||
lcdMainOnTop();
|
||||
} else {
|
||||
lcdMainOnBottom();
|
||||
}
|
||||
}
|
||||
|
||||
void setShakePos(int shakeXOffset, int shakeYOffset) {
|
||||
s_shakeXOffset = shakeXOffset;
|
||||
s_shakeYOffset = shakeYOffset;
|
||||
}
|
||||
|
||||
Common::Point warpMouse(int penX, int penY, bool isOverlayShown) {
|
||||
int storedMouseX, storedMouseY;
|
||||
if (!isOverlayShown) {
|
||||
storedMouseX = ((penX - touchX) << 8) / touchScX;
|
||||
storedMouseY = ((penY - touchY) << 8) / touchScY;
|
||||
} else {
|
||||
storedMouseX = penX;
|
||||
storedMouseY = penY;
|
||||
}
|
||||
|
||||
return Common::Point(storedMouseX, storedMouseY);
|
||||
}
|
||||
|
||||
void setMainScreenScroll(int x, int y) {
|
||||
REG_BG3X = x;
|
||||
REG_BG3Y = y;
|
||||
|
||||
if (!gameScreenSwap) {
|
||||
touchX = x >> 8;
|
||||
touchY = y >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void setMainScreenScale(int x, int y) {
|
||||
if ((g_system->getGraphicsMode() == GFX_SWSCALE) && (x==320)) {
|
||||
REG_BG3PA = 256;
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = y;
|
||||
} else {
|
||||
REG_BG3PA = x;
|
||||
REG_BG3PB = 0;
|
||||
REG_BG3PC = 0;
|
||||
REG_BG3PD = y;
|
||||
}
|
||||
|
||||
if (!gameScreenSwap) {
|
||||
touchScX = x;
|
||||
touchScY = y;
|
||||
}
|
||||
}
|
||||
|
||||
void setZoomedScreenScroll(int x, int y, bool shake) {
|
||||
if (gameScreenSwap) {
|
||||
touchX = x >> 8;
|
||||
touchY = y >> 8;
|
||||
}
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
REG_BG3X_SUB = x;
|
||||
REG_BG3Y_SUB = y;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setZoomedScreenScale(int x, int y) {
|
||||
if (gameScreenSwap) {
|
||||
touchScX = x;
|
||||
touchScY = y;
|
||||
}
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
REG_BG3PA_SUB = x;
|
||||
REG_BG3PB_SUB = 0;
|
||||
REG_BG3PC_SUB = 0;
|
||||
REG_BG3PD_SUB = y;
|
||||
#endif
|
||||
}
|
||||
|
||||
Common::Point transformPoint(uint16 x, uint16 y, bool isOverlayShown) {
|
||||
if (!isOverlayShown) {
|
||||
x = ((x * touchScX) >> 8) + touchX;
|
||||
x = CLIP<uint16>(x, 0, gameWidth - 1);
|
||||
|
||||
y = ((y * touchScY) >> 8) + touchY;
|
||||
y = CLIP<uint16>(y, 0, gameHeight - 1);
|
||||
}
|
||||
|
||||
return Common::Point(x, y);
|
||||
}
|
||||
|
||||
void VBlankHandler(void) {
|
||||
int xCenter = subScTargetX + ((subScreenWidth >> 1) << 8);
|
||||
int yCenter = subScTargetY + ((subScreenHeight >> 1) << 8);
|
||||
|
||||
subScreenWidth = (256 * subScreenScale) >> 8;
|
||||
subScreenHeight = (192 * subScreenScale) >> 8;
|
||||
|
||||
if ( ((subScreenWidth) > 256 - 8) && ((subScreenWidth) < 256 + 8) ) {
|
||||
subScreenWidth = 256;
|
||||
subScreenHeight = 192;
|
||||
} else if ( ((subScreenWidth) > 128 - 8) && ((subScreenWidth) < 128 + 8) ) {
|
||||
subScreenWidth = 128;
|
||||
subScreenHeight = 96;
|
||||
} else if (subScreenWidth > 256) {
|
||||
subScreenWidth = 320;
|
||||
subScreenHeight = 200;
|
||||
}
|
||||
|
||||
subScTargetX = xCenter - ((subScreenWidth >> 1) << 8);
|
||||
subScTargetY = yCenter - ((subScreenHeight >> 1) << 8);
|
||||
|
||||
subScTargetX = CLIP(subScTargetX, 0, (gameWidth - subScreenWidth) << 8);
|
||||
subScTargetY = CLIP(subScTargetY, 0, (gameHeight - subScreenHeight) << 8);
|
||||
|
||||
subScX += (subScTargetX - subScX) >> 2;
|
||||
subScY += (subScTargetY - subScY) >> 2;
|
||||
|
||||
if (g_system->getGraphicsMode() == GFX_NOSCALE) {
|
||||
if (scX + 256 > gameWidth - 1) {
|
||||
scX = gameWidth - 1 - 256;
|
||||
}
|
||||
|
||||
if (scX < 0) {
|
||||
scX = 0;
|
||||
}
|
||||
|
||||
if (scY + 192 > gameHeight - 1) {
|
||||
scY = gameHeight - 1 - 192;
|
||||
}
|
||||
|
||||
if (scY < 0) {
|
||||
scY = 0;
|
||||
}
|
||||
|
||||
setZoomedScreenScroll(subScX, subScY, (subScreenWidth != 256) && (subScreenWidth != 128));
|
||||
setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8);
|
||||
|
||||
setMainScreenScroll((scX << 8) + (s_shakeXOffset << 8), (scY << 8) + (s_shakeYOffset << 8));
|
||||
setMainScreenScale(256, 256); // 1:1 scale
|
||||
} else {
|
||||
if (scY > gameHeight - 192 - 1) {
|
||||
scY = gameHeight - 192 - 1;
|
||||
}
|
||||
|
||||
if (scY < 0) {
|
||||
scY = 0;
|
||||
}
|
||||
|
||||
setZoomedScreenScroll(subScX, subScY, (subScreenWidth != 256) && (subScreenWidth != 128));
|
||||
setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8);
|
||||
|
||||
setMainScreenScroll(64 + (s_shakeXOffset << 8), (scY << 8) + (s_shakeYOffset << 8));
|
||||
setMainScreenScale(320, 256); // 1:1 scale
|
||||
}
|
||||
}
|
||||
|
||||
void setTalkPos(int x, int y) {
|
||||
setTopScreenTarget(x, y);
|
||||
}
|
||||
|
||||
void setTopScreenTarget(int x, int y) {
|
||||
subScTargetX = (x - (subScreenWidth >> 1));
|
||||
subScTargetY = (y - (subScreenHeight >> 1));
|
||||
|
||||
if (subScTargetX < 0) subScTargetX = 0;
|
||||
if (subScTargetX > gameWidth - subScreenWidth) subScTargetX = gameWidth - subScreenWidth;
|
||||
|
||||
if (subScTargetY < 0) subScTargetY = 0;
|
||||
if (subScTargetY > gameHeight - subScreenHeight) subScTargetY = gameHeight - subScreenHeight;
|
||||
|
||||
subScTargetX <<=8;
|
||||
subScTargetY <<=8;
|
||||
}
|
||||
|
||||
void initHardware() {
|
||||
powerOn(POWER_ALL);
|
||||
|
||||
for (int r = 0; r < 255; r++) {
|
||||
BG_PALETTE[r] = 0;
|
||||
}
|
||||
|
||||
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
|
||||
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
|
||||
vramSetBankE(VRAM_E_MAIN_SPRITE);
|
||||
|
||||
REG_BG2CNT = BG_BMP16_256x256;
|
||||
REG_BG2PA = 256;
|
||||
REG_BG2PB = 0;
|
||||
REG_BG2PC = 0;
|
||||
REG_BG2PD = 256;
|
||||
|
||||
scX = 0;
|
||||
scY = 0;
|
||||
subScX = 0;
|
||||
subScY = 0;
|
||||
subScTargetX = 0;
|
||||
subScTargetY = 0;
|
||||
|
||||
lcdMainOnBottom();
|
||||
|
||||
//irqs are nice
|
||||
irqSet(IRQ_VBLANK, VBlankHandler);
|
||||
irqEnable(IRQ_VBLANK);
|
||||
|
||||
#ifndef DISABLE_TEXT_CONSOLE
|
||||
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
|
||||
vramSetBankH(VRAM_H_SUB_BG);
|
||||
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true);
|
||||
#else
|
||||
videoSetModeSub(MODE_3_2D | DISPLAY_BG3_ACTIVE);
|
||||
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// Fast Ram
|
||||
///////////////////
|
||||
|
@ -23,51 +23,14 @@
|
||||
#ifndef _DSMAIN_H
|
||||
#define _DSMAIN_H
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include <nds.h>
|
||||
#include "osystem_ds.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace DS {
|
||||
|
||||
// Video
|
||||
void displayMode8Bit(); // Switch to 8-bit mode5
|
||||
void displayMode16Bit(); // Switch to 16-bit mode5
|
||||
|
||||
// Get address of current back buffer
|
||||
u16 * get16BitBackBuffer();
|
||||
|
||||
void setTalkPos(int x, int y);
|
||||
void setTopScreenTarget(int x, int y);
|
||||
void setTopScreenZoom(int percentage);
|
||||
|
||||
// Events
|
||||
void VBlankHandler();
|
||||
Common::Point transformPoint(uint16 x, uint16 y, bool isOverlayShown);
|
||||
Common::Point warpMouse(int penX, int penY, bool isOverlayShown);
|
||||
|
||||
// Shake
|
||||
void setShakePos(int shakeXOffset, int shakeYOffset);
|
||||
|
||||
// Options
|
||||
void setGameScreenSwap(bool enable);
|
||||
|
||||
// Display
|
||||
bool getIsDisplayMode8Bit();
|
||||
void setGameSize(int width, int height);
|
||||
int getGameWidth();
|
||||
int getGameHeight();
|
||||
void initHardware();
|
||||
|
||||
// Fast RAM allocation (ITCM)
|
||||
void fastRamReset();
|
||||
void* fastRamAlloc(int size);
|
||||
|
||||
|
||||
} // End of namespace DS
|
||||
|
||||
|
||||
|
||||
int cygprofile_getHBlanks();
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@ MODULE := backends/platform/ds
|
||||
|
||||
MODULE_OBJS := \
|
||||
blitters_arm.o \
|
||||
ds-graphics.o \
|
||||
dsmain.o \
|
||||
osystem_ds.o
|
||||
|
||||
|
@ -20,35 +20,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Allow use of stuff in <time.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
// Allow use of stuff in <nds.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
|
||||
|
||||
#include <nds.h>
|
||||
#include <filesystem.h>
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "backends/platform/ds/osystem_ds.h"
|
||||
|
||||
#include "common/util.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "osystem_ds.h"
|
||||
#include "dsmain.h"
|
||||
#include "blitters.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/str.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "backends/fs/devoptab/devoptab-fs-factory.h"
|
||||
#include "backends/keymapper/hardware-input.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "backends/audiocd/default/default-audiocd.h"
|
||||
#include "backends/events/default/default-events.h"
|
||||
#include "backends/fs/devoptab/devoptab-fs-factory.h"
|
||||
#include "backends/keymapper/hardware-input.h"
|
||||
#include "backends/mixer/maxmod/maxmod-mixer.h"
|
||||
#include "backends/mutex/null/null-mutex.h"
|
||||
#include "backends/saves/default/default-saves.h"
|
||||
@ -83,7 +69,7 @@ void timerTickHandler() {
|
||||
}
|
||||
|
||||
void OSystem_DS::initBackend() {
|
||||
DS::initHardware();
|
||||
initGraphics();
|
||||
|
||||
defaultExceptionHandler();
|
||||
|
||||
@ -100,312 +86,9 @@ void OSystem_DS::initBackend() {
|
||||
_mixerManager = new MaxModMixerManager(11025, 4096);
|
||||
_mixerManager->init();
|
||||
|
||||
oamInit(&oamMain, SpriteMapping_Bmp_1D_128, false);
|
||||
_cursorSprite = oamAllocateGfx(&oamMain, SpriteSize_64x64, SpriteColorFormat_Bmp);
|
||||
|
||||
_overlay.create(256, 192, Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15));
|
||||
|
||||
BaseBackend::initBackend();
|
||||
}
|
||||
|
||||
bool OSystem_DS::hasFeature(Feature f) {
|
||||
return (f == kFeatureCursorPalette) || (f == kFeatureStretchMode);
|
||||
}
|
||||
|
||||
void OSystem_DS::setFeatureState(Feature f, bool enable) {
|
||||
if (f == kFeatureCursorPalette) {
|
||||
_disableCursorPalette = !enable;
|
||||
refreshCursor(_cursorSprite, _cursor, !_disableCursorPalette ? _cursorPalette : _palette);
|
||||
}
|
||||
}
|
||||
|
||||
bool OSystem_DS::getFeatureState(Feature f) {
|
||||
if (f == kFeatureCursorPalette)
|
||||
return !_disableCursorPalette;
|
||||
return false;
|
||||
}
|
||||
|
||||
static const OSystem::GraphicsMode graphicsModes[] = {
|
||||
{ "NONE", _s("Unscaled"), GFX_NOSCALE },
|
||||
{ "HW", _s("Hardware scale (fast, but low quality)"), GFX_HWSCALE },
|
||||
{ "SW", _s("Software scale (good quality, but slower)"), GFX_SWSCALE },
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
|
||||
const OSystem::GraphicsMode *OSystem_DS::getSupportedGraphicsModes() const {
|
||||
return graphicsModes;
|
||||
}
|
||||
|
||||
int OSystem_DS::getDefaultGraphicsMode() const {
|
||||
return GFX_HWSCALE;
|
||||
}
|
||||
|
||||
bool OSystem_DS::setGraphicsMode(int mode) {
|
||||
switch (mode) {
|
||||
case GFX_NOSCALE:
|
||||
case GFX_HWSCALE:
|
||||
case GFX_SWSCALE:
|
||||
_graphicsMode = mode;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int OSystem_DS::getGraphicsMode() const {
|
||||
return _graphicsMode;
|
||||
}
|
||||
|
||||
static const OSystem::GraphicsMode stretchModes[] = {
|
||||
{ "100", "100%", 100 },
|
||||
{ "150", "150%", 150 },
|
||||
{ "200", "200%", 200 },
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
|
||||
const OSystem::GraphicsMode *OSystem_DS::getSupportedStretchModes() const {
|
||||
return stretchModes;
|
||||
}
|
||||
|
||||
int OSystem_DS::getDefaultStretchMode() const {
|
||||
return 100;
|
||||
}
|
||||
|
||||
bool OSystem_DS::setStretchMode(int mode) {
|
||||
_stretchMode = mode;
|
||||
DS::setTopScreenZoom(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
int OSystem_DS::getStretchMode() const {
|
||||
return _stretchMode;
|
||||
}
|
||||
|
||||
void OSystem_DS::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
|
||||
_framebuffer.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
// For Lost in Time, the title screen is displayed in 640x400.
|
||||
// In order to support this game, the screen mode is set, but
|
||||
// all draw calls are ignored until the game switches to 320x200.
|
||||
if ((width == 640) && (height == 400)) {
|
||||
_graphicsEnable = false;
|
||||
} else {
|
||||
_graphicsEnable = true;
|
||||
DS::setGameSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getHeight() {
|
||||
return _framebuffer.h;
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getWidth() {
|
||||
return _framebuffer.w;
|
||||
}
|
||||
|
||||
void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
|
||||
for (unsigned int r = start; r < start + num; r++) {
|
||||
int red = *colors;
|
||||
int green = *(colors + 1);
|
||||
int blue = *(colors + 2);
|
||||
|
||||
red >>= 3;
|
||||
green >>= 3;
|
||||
blue >>= 3;
|
||||
|
||||
{
|
||||
u16 paletteValue = red | (green << 5) | (blue << 10);
|
||||
|
||||
if (!_isOverlayShown) {
|
||||
BG_PALETTE[r] = paletteValue;
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
BG_PALETTE_SUB[r] = paletteValue;
|
||||
#endif
|
||||
}
|
||||
|
||||
_palette[r] = paletteValue;
|
||||
}
|
||||
|
||||
colors += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
|
||||
|
||||
for (unsigned int r = start; r < start + num; r++) {
|
||||
int red = *colors;
|
||||
int green = *(colors + 1);
|
||||
int blue = *(colors + 2);
|
||||
|
||||
red >>= 3;
|
||||
green >>= 3;
|
||||
blue >>= 3;
|
||||
|
||||
u16 paletteValue = red | (green << 5) | (blue << 10);
|
||||
_cursorPalette[r] = paletteValue;
|
||||
|
||||
colors += 3;
|
||||
}
|
||||
|
||||
_disableCursorPalette = false;
|
||||
refreshCursor(_cursorSprite, _cursor, !_disableCursorPalette ? _cursorPalette : _palette);
|
||||
}
|
||||
|
||||
void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) const {
|
||||
for (unsigned int r = start; r < start + num; r++) {
|
||||
*colors++ = (BG_PALETTE[r] & 0x001F) << 3;
|
||||
*colors++ = (BG_PALETTE[r] & 0x03E0) >> 5 << 3;
|
||||
*colors++ = (BG_PALETTE[r] & 0x7C00) >> 10 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
|
||||
_framebuffer.copyRectToSurface(buf, pitch, x, y, w, h);
|
||||
}
|
||||
|
||||
void OSystem_DS::updateScreen() {
|
||||
oamSet(&oamMain, 0, _cursorPos.x - _cursorHotX, _cursorPos.y - _cursorHotY, 0, 15, SpriteSize_64x64,
|
||||
SpriteColorFormat_Bmp, _cursorSprite, 0, false, !_cursorVisible, false, false, false);
|
||||
oamUpdate(&oamMain);
|
||||
|
||||
if (_isOverlayShown) {
|
||||
u16 *back = (u16 *)_overlay.getPixels();
|
||||
dmaCopyHalfWords(3, back, BG_GFX, 256 * 192 * 2);
|
||||
} else if (!_graphicsEnable) {
|
||||
return;
|
||||
} else if (_graphicsMode == GFX_SWSCALE) {
|
||||
u16 *base = BG_GFX + 0x10000;
|
||||
Rescale_320x256xPAL8_To_256x256x1555(
|
||||
base,
|
||||
(const u8 *)_framebuffer.getPixels(),
|
||||
256,
|
||||
_framebuffer.pitch,
|
||||
BG_PALETTE,
|
||||
_framebuffer.h );
|
||||
} else {
|
||||
// The DS video RAM doesn't support 8-bit writes because Nintendo wanted
|
||||
// to save a few pennies/euro cents on the hardware.
|
||||
|
||||
u16 *bg = BG_GFX + 0x10000;
|
||||
s32 stride = 512;
|
||||
|
||||
u16 *src = (u16 *)_framebuffer.getPixels();
|
||||
|
||||
for (int dy = 0; dy < _framebuffer.h; dy++) {
|
||||
DC_FlushRange(src, _framebuffer.w << 1);
|
||||
|
||||
u16 *dest1 = bg + (dy * (stride >> 1));
|
||||
DC_FlushRange(dest1, _framebuffer.w << 1);
|
||||
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
u16 *dest2 = (u16 *)BG_GFX_SUB + (dy << 8);
|
||||
DC_FlushRange(dest2, _framebuffer.w << 1);
|
||||
|
||||
dmaCopyHalfWordsAsynch(2, src, dest2, _framebuffer.w);
|
||||
#endif
|
||||
dmaCopyHalfWordsAsynch(3, src, dest1, _framebuffer.w);
|
||||
|
||||
while (dmaBusy(2) || dmaBusy(3));
|
||||
|
||||
src += _framebuffer.pitch >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::setShakePos(int shakeXOffset, int shakeYOffset) {
|
||||
DS::setShakePos(shakeXOffset, shakeYOffset);
|
||||
}
|
||||
|
||||
void OSystem_DS::showOverlay() {
|
||||
dmaFillHalfWords(0, BG_GFX, 256 * 192 * 2);
|
||||
videoBgEnable(2);
|
||||
lcdMainOnBottom();
|
||||
_isOverlayShown = true;
|
||||
}
|
||||
|
||||
void OSystem_DS::hideOverlay() {
|
||||
videoBgDisable(2);
|
||||
DS::displayMode8Bit();
|
||||
_isOverlayShown = false;
|
||||
}
|
||||
|
||||
bool OSystem_DS::isOverlayVisible() const {
|
||||
return _isOverlayShown;
|
||||
}
|
||||
|
||||
void OSystem_DS::clearOverlay() {
|
||||
memset(_overlay.getPixels(), 0, _overlay.pitch * _overlay.h);
|
||||
}
|
||||
|
||||
void OSystem_DS::grabOverlay(void *buf, int pitch) {
|
||||
byte *dst = (byte *)buf;
|
||||
|
||||
for (int y = 0; y < _overlay.h; ++y) {
|
||||
memcpy(dst, _overlay.getBasePtr(0, y), _overlay.w * _overlay.format.bytesPerPixel);
|
||||
dst += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
|
||||
_overlay.copyRectToSurface(buf, pitch, x, y, w, h);
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getOverlayHeight() {
|
||||
return _overlay.h;
|
||||
}
|
||||
|
||||
int16 OSystem_DS::getOverlayWidth() {
|
||||
return _overlay.w;
|
||||
}
|
||||
|
||||
Graphics::PixelFormat OSystem_DS::getOverlayFormat() const {
|
||||
return _overlay.format;
|
||||
}
|
||||
|
||||
Common::Point OSystem_DS::transformPoint(uint16 x, uint16 y) {
|
||||
return DS::transformPoint(x, y, _isOverlayShown);
|
||||
}
|
||||
|
||||
bool OSystem_DS::showMouse(bool visible) {
|
||||
const bool last = _cursorVisible;
|
||||
_cursorVisible = visible;
|
||||
return last;
|
||||
}
|
||||
|
||||
void OSystem_DS::warpMouse(int x, int y) {
|
||||
_cursorPos = DS::warpMouse(x, y, _isOverlayShown);
|
||||
}
|
||||
|
||||
void OSystem_DS::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
|
||||
if (!buf || w == 0 || h == 0 || (format && *format != Graphics::PixelFormat::createFormatCLUT8()))
|
||||
return;
|
||||
|
||||
if (_cursor.w != w || _cursor.h != h)
|
||||
_cursor.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
_cursor.copyRectToSurface(buf, w, 0, 0, w, h);
|
||||
_cursorHotX = hotspotX;
|
||||
_cursorHotY = hotspotY;
|
||||
_cursorKey = keycolor;
|
||||
refreshCursor(_cursorSprite, _cursor, !_disableCursorPalette ? _cursorPalette : _palette);
|
||||
}
|
||||
|
||||
void OSystem_DS::refreshCursor(u16 *dst, const Graphics::Surface &src, const uint16 *palette) {
|
||||
uint w = MIN<uint>(src.w, 64);
|
||||
uint h = MIN<uint>(src.h, 64);
|
||||
|
||||
dmaFillHalfWords(0, dst, 64 * 64 * 2);
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
const uint8 *row = (const uint8 *)src.getBasePtr(0, y);
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint8 color = *row++;
|
||||
|
||||
if (color != _cursorKey)
|
||||
dst[y * 64 + x] = palette[color] | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_DS::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
|
||||
s.add("nitro:/", new Common::FSDirectory("nitro:/"), priority);
|
||||
}
|
||||
@ -445,22 +128,6 @@ void OSystem_DS::getTimeAndDate(TimeDate &td) const {
|
||||
void OSystem_DS::quit() {
|
||||
}
|
||||
|
||||
Graphics::Surface *OSystem_DS::lockScreen() {
|
||||
return &_framebuffer;
|
||||
}
|
||||
|
||||
void OSystem_DS::unlockScreen() {
|
||||
// No need to do anything here. The screen will be updated in updateScreen().
|
||||
}
|
||||
|
||||
void OSystem_DS::setFocusRectangle(const Common::Rect& rect) {
|
||||
DS::setTalkPos(rect.left + rect.width() / 2, rect.top + rect.height() / 2);
|
||||
}
|
||||
|
||||
void OSystem_DS::clearFocusRectangle() {
|
||||
|
||||
}
|
||||
|
||||
void OSystem_DS::engineInit() {
|
||||
#ifdef DISABLE_TEXT_CONSOLE
|
||||
videoBgEnableSub(3);
|
||||
|
@ -56,6 +56,8 @@ protected:
|
||||
|
||||
DSEventSource *_eventSource;
|
||||
|
||||
void initGraphics();
|
||||
|
||||
Graphics::Surface *createTempFrameBuffer();
|
||||
bool _disableCursorPalette;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user