diff --git a/backends/platform/ds/background.cpp b/backends/platform/ds/background.cpp index fafe4dab74f..606aaf45494 100644 --- a/backends/platform/ds/background.cpp +++ b/backends/platform/ds/background.cpp @@ -23,17 +23,32 @@ #include #include "backends/platform/ds/background.h" +#include "backends/platform/ds/blitters.h" namespace DS { -BgSize getBgSize(int width, int height, bool isRGB, int &realPitch) { +Background::Background() : + _bg(-1), _visible(true), _swScale(false), + _realPitch(0), _realHeight(0), + _pfCLUT8(Graphics::PixelFormat::createFormatCLUT8()), + _pfABGR1555(Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15)) { +} + +static BgSize getBgSize(uint16 width, uint16 height, bool isRGB, bool swScale, uint16 &realPitch, uint16 &realHeight) { + if (swScale) { + isRGB = true; + width = (width * 4) / 5; + } + BgSize size; if (width > 512 && !isRGB) { size = BgSize_B8_1024x512; realPitch = 1024; + realHeight = 512; } else if (height > 512 && !isRGB) { size = BgSize_B8_512x1024; realPitch = 512; + realHeight = 1024; } else if (height > 256) { if (isRGB) { size = BgSize_B16_512x512; @@ -42,6 +57,7 @@ BgSize getBgSize(int width, int height, bool isRGB, int &realPitch) { size = BgSize_B8_512x512; realPitch = 512; } + realHeight = 512; } else if (width > 256) { if (isRGB) { size = BgSize_B16_512x256; @@ -50,6 +66,7 @@ BgSize getBgSize(int width, int height, bool isRGB, int &realPitch) { size = BgSize_B8_512x256; realPitch = 512; } + realHeight = 256; } else if (width > 128 || height > 128) { if (isRGB) { size = BgSize_B16_256x256; @@ -58,6 +75,7 @@ BgSize getBgSize(int width, int height, bool isRGB, int &realPitch) { size = BgSize_B8_256x256; realPitch = 256; } + realHeight = 256; } else { if (isRGB) { size = BgSize_B16_128x128; @@ -66,42 +84,133 @@ BgSize getBgSize(int width, int height, bool isRGB, int &realPitch) { size = BgSize_B8_128x128; realPitch = 128; } + realHeight = 128; } return size; } -void Background::create(uint16 width, uint16 height, bool isRGB, int layer, bool isSub, int mapBase) { - const Graphics::PixelFormat f = isRGB ? Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15) : Graphics::PixelFormat::createFormatCLUT8(); +size_t Background::getRequiredVRAM(uint16 width, uint16 height, bool isRGB, bool swScale) { + uint16 realPitch, realHeight; + /* BgSize size = */ getBgSize(width, height, isRGB, swScale, realPitch, realHeight); + return realPitch * realHeight; +} + +void Background::create(uint16 width, uint16 height, bool isRGB) { + const Graphics::PixelFormat f = isRGB ? _pfABGR1555 : _pfCLUT8; + Surface::create(width, height, f); + _bg = -1; + _swScale = false; +} + +void Background::create(uint16 width, uint16 height, bool isRGB, int layer, bool isSub, int mapBase, bool swScale) { + const Graphics::PixelFormat f = isRGB ? _pfABGR1555 : _pfCLUT8; Surface::create(width, height, f); - BgType type = isRGB ? BgType_Bmp16 : BgType_Bmp8; - BgSize size = getBgSize(width, height, isRGB, _realPitch); + BgType type = (isRGB || swScale) ? BgType_Bmp16 : BgType_Bmp8; + BgSize size = getBgSize(width, height, isRGB, swScale, _realPitch, _realHeight); if (isSub) { _bg = bgInitSub(layer, type, size, mapBase, 0); } else { _bg = bgInit(layer, type, size, mapBase, 0); } + + _swScale = swScale; +} + +void Background::init(Background *surface) { + Surface::init(surface->w, surface->h, surface->pitch, surface->pixels, surface->format); + _bg = -1; + _swScale = false; +} + +void Background::init(Background *surface, int layer, bool isSub, int mapBase, bool swScale) { + Surface::init(surface->w, surface->h, surface->pitch, surface->pixels, surface->format); + + bool isRGB = (format != _pfCLUT8); + BgType type = (isRGB || swScale) ? BgType_Bmp16 : BgType_Bmp8; + BgSize size = getBgSize(w, h, isRGB, swScale, _realPitch, _realHeight); + + if (isSub) { + _bg = bgInitSub(layer, type, size, mapBase, 0); + } else { + _bg = bgInit(layer, type, size, mapBase, 0); + } + + _swScale = swScale; +} + +static void dmaBlit(uint16 *dst, const uint dstPitch, const uint16 *src, const uint srcPitch, + const uint w, const uint h, const uint bytesPerPixel) { + if (dstPitch == srcPitch && ((w * bytesPerPixel) == dstPitch)) { + dmaCopy(src, dst, dstPitch * h); + return; + } + + // The DS video RAM doesn't support 8-bit writes because Nintendo wanted + // to save a few pennies/euro cents on the hardware. + + uint row = w * bytesPerPixel; + + for (uint dy = 0; dy < h; dy += 2) { + const u16 *src1 = src; + src += (srcPitch >> 1); + DC_FlushRange(src1, row << 1); + + const u16 *src2 = src; + src += (srcPitch >> 1); + DC_FlushRange(src2, row << 1); + + u16 *dest1 = dst; + dst += (dstPitch >> 1); + DC_FlushRange(dest1, row << 1); + + u16 *dest2 = dst; + dst += (dstPitch >> 1); + DC_FlushRange(dest2, row << 1); + + dmaCopyHalfWordsAsynch(2, src1, dest1, row); + dmaCopyHalfWordsAsynch(3, src2, dest2, row); + + while (dmaBusy(2) || dmaBusy(3)); + } } void Background::update() { - u16 *src = (u16 *)getPixels(); + if (_bg < 0) + return; + u16 *dst = bgGetGfxPtr(_bg); - dmaCopy(src, dst, _realPitch * h); + if (_swScale) { + if (format == _pfCLUT8) { + Rescale_320x256xPAL8_To_256x256x1555( + dst, (const u8 *)getPixels(), _realPitch / 2, pitch, BG_PALETTE, h); + } else { + Rescale_320x256x1555_To_256x256x1555( + dst, (const u16 *)getPixels(), _realPitch / 2, pitch / 2); + } + } else { + dmaBlit(dst, _realPitch, (const u16 *)getPixels(), pitch, w, h, format.bytesPerPixel); + } } void Background::reset() { + if (_bg < 0) + return; + u16 *dst = bgGetGfxPtr(_bg); dmaFillHalfWords(0, dst, _realPitch * h); } void Background::show() { - bgShow(_bg); + if (_bg >= 0) + bgShow(_bg); _visible = true; } void Background::hide() { - bgHide(_bg); + if (_bg >= 0) + bgHide(_bg); _visible = false; } diff --git a/backends/platform/ds/background.h b/backends/platform/ds/background.h index 4bce40ca14c..c64e0f89a9e 100644 --- a/backends/platform/ds/background.h +++ b/backends/platform/ds/background.h @@ -29,7 +29,13 @@ namespace DS { class Background : public Graphics::Surface { public: - void create(uint16 width, uint16 height, bool isRGB, int layer, bool isSub, int mapBase); + Background(); + + size_t getRequiredVRAM(uint16 width, uint16 height, bool isRGB, bool swScale); + void create(uint16 width, uint16 height, bool isRGB); + void create(uint16 width, uint16 height, bool isRGB, int layer, bool isSub, int mapBase, bool swScale); + void init(Background *surface); + void init(Background *surface, int layer, bool isSub, int mapBase, bool swScale); void update(); void reset(); @@ -51,8 +57,9 @@ public: protected: int _bg; - bool _visible; - int _realPitch; + bool _visible, _swScale; + uint16 _realPitch, _realHeight; + const Graphics::PixelFormat _pfCLUT8, _pfABGR1555; }; } // End of namespace DS diff --git a/backends/platform/ds/ds-graphics.cpp b/backends/platform/ds/ds-graphics.cpp index 33f13686c6f..1404882cd2a 100644 --- a/backends/platform/ds/ds-graphics.cpp +++ b/backends/platform/ds/ds-graphics.cpp @@ -23,7 +23,6 @@ #include #include "backends/platform/ds/osystem_ds.h" -#include "backends/platform/ds/blitters.h" #include "common/translation.h" @@ -83,24 +82,17 @@ void setTopScreenTarget(int x, int y) { subScTargetY <<=8; } -void setGameSize(int width, int height, bool isRGB) { +void setGameSize(int width, int height) { gameWidth = width; gameHeight = height; - vramSetBankB(VRAM_B_MAIN_BG_0x06020000); - vramSetBankD(VRAM_D_MAIN_BG_0x06040000); - 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 = (isRGB ? BG_BMP16_512x256 :BG_BMP8_512x256) | BG_BMP_BASE(8); - REG_BG3PA = (int) (((float) (gameWidth) / 256.0f) * 256); REG_BG3PB = 0; REG_BG3PC = 0; @@ -108,8 +100,6 @@ void setGameSize(int width, int height, bool isRGB) { } #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; @@ -281,6 +271,8 @@ void initHardware() { videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); vramSetBankA(VRAM_A_MAIN_BG_0x06000000); + vramSetBankB(VRAM_B_MAIN_BG_0x06020000); + vramSetBankD(VRAM_D_MAIN_BG_0x06040000); vramSetBankE(VRAM_E_MAIN_SPRITE); scX = 0; @@ -314,7 +306,7 @@ void OSystem_DS::initGraphics() { oamInit(&oamMain, SpriteMapping_Bmp_1D_128, false); _cursorSprite = oamAllocateGfx(&oamMain, SpriteSize_64x64, SpriteColorFormat_Bmp); - _overlay.create(256, 192, true, 2, false, 0); + _overlay.create(256, 192, true, 2, false, 0, false); } bool OSystem_DS::hasFeature(Feature f) { @@ -404,17 +396,27 @@ Common::List OSystem_DS::getSupportedFormats() const { void OSystem_DS::initSize(uint width, uint height, const Graphics::PixelFormat *format) { Graphics::PixelFormat actualFormat = format ? *format : _pfCLUT8; - _framebuffer.create(width, height, actualFormat); + bool isRGB = (actualFormat != _pfCLUT8), swScale = ((_graphicsMode == GFX_SWSCALE) && (width == 320)); // 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; + if (_framebuffer.getRequiredVRAM(width, height, isRGB, swScale) > 0x40000) { + _framebuffer.create(width, height, isRGB); } else { - _graphicsEnable = true; - DS::setGameSize(width, height, (actualFormat != _pfCLUT8)); + _framebuffer.reset(); + _framebuffer.create(width, height, isRGB, 3, false, 8, swScale); + DS::setGameSize(width, height); } + +#ifdef DISABLE_TEXT_CONSOLE + if (_framebuffer.getRequiredVRAM(width, height, isRGB, false) > 0x20000) { + _subScreen.init(&_framebuffer); + } else { + _subScreen.reset(); + _subScreen.init(&_framebuffer, 3, true, 0, false); + } +#endif } int16 OSystem_DS::getHeight() { @@ -485,37 +487,6 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int _framebuffer.copyRectToSurface(buf, pitch, x, y, w, h); } -void OSystem_DS::dmaBlit(uint16 *dst, const uint dstPitch, const uint16 *src, const uint srcPitch, - const uint w, const uint h, const uint bytesPerPixel) { - // The DS video RAM doesn't support 8-bit writes because Nintendo wanted - // to save a few pennies/euro cents on the hardware. - - uint row = w * bytesPerPixel; - - for (uint dy = 0; dy < h; dy += 2) { - const u16 *src1 = src; - src += (srcPitch >> 1); - DC_FlushRange(src1, row << 1); - - const u16 *src2 = src; - src += (srcPitch >> 1); - DC_FlushRange(src2, row << 1); - - u16 *dest1 = dst; - dst += (dstPitch >> 1); - DC_FlushRange(dest1, row << 1); - - u16 *dest2 = dst; - dst += (dstPitch >> 1); - DC_FlushRange(dest2, row << 1); - - dmaCopyHalfWordsAsynch(2, src1, dest1, row); - dmaCopyHalfWordsAsynch(3, src2, dest2, row); - - while (dmaBusy(2) || dmaBusy(3)); - } -} - 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); @@ -523,34 +494,11 @@ void OSystem_DS::updateScreen() { if (_overlay.isVisible()) { _overlay.update(); - } else if (_graphicsEnable) { - u16 *base = BG_GFX + 0x10000; - if (_graphicsMode == GFX_SWSCALE) { - if (_framebuffer.format == _pfCLUT8) { - Rescale_320x256xPAL8_To_256x256x1555( - base, - (const u8 *)_framebuffer.getPixels(), - 256, - _framebuffer.pitch, - BG_PALETTE, - _framebuffer.h ); - } else { - Rescale_320x256x1555_To_256x256x1555( - base, - (const u16 *)_framebuffer.getPixels(), - 256, - _framebuffer.pitch / 2 ); - } - } else { - dmaBlit(base, 512 * _framebuffer.format.bytesPerPixel, - (const u16 *)_framebuffer.getPixels(), _framebuffer.pitch, - _framebuffer.w, _framebuffer.h, _framebuffer.format.bytesPerPixel); - + } else { + _framebuffer.update(); #ifdef DISABLE_TEXT_CONSOLE - if (_framebuffer.format == _pfCLUT8) - dmaCopy(base, BG_GFX_SUB, 512 * 256); + _subScreen.update(); #endif - } } } diff --git a/backends/platform/ds/osystem_ds.cpp b/backends/platform/ds/osystem_ds.cpp index 0473971704f..2c6b265c143 100644 --- a/backends/platform/ds/osystem_ds.cpp +++ b/backends/platform/ds/osystem_ds.cpp @@ -45,9 +45,8 @@ OSystem_DS *OSystem_DS::_instance = NULL; OSystem_DS::OSystem_DS() - : _eventSource(NULL), _isOverlayShown(true), + : _eventSource(NULL), _disableCursorPalette(true), _graphicsMode(GFX_HWSCALE), _stretchMode(100), - _disableCursorPalette(true), _graphicsEnable(true), _pfCLUT8(Graphics::PixelFormat::createFormatCLUT8()), _pfABGR1555(Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15)), _callbackTimer(10), _currentTimeMillis(0) @@ -130,18 +129,6 @@ void OSystem_DS::getTimeAndDate(TimeDate &td) const { void OSystem_DS::quit() { } -void OSystem_DS::engineInit() { -#ifdef DISABLE_TEXT_CONSOLE - videoBgEnableSub(3); -#endif -} - -void OSystem_DS::engineDone() { -#ifdef DISABLE_TEXT_CONSOLE - videoBgDisableSub(3); -#endif -} - void OSystem_DS::logMessage(LogMessageType::Type type, const char *message) { #ifndef DISABLE_TEXT_CONSOLE printf("%s", message); diff --git a/backends/platform/ds/osystem_ds.h b/backends/platform/ds/osystem_ds.h index f257545cda0..cc3351fcbcb 100644 --- a/backends/platform/ds/osystem_ds.h +++ b/backends/platform/ds/osystem_ds.h @@ -39,9 +39,11 @@ enum { class OSystem_DS : public ModularMutexBackend, public ModularMixerBackend, public PaletteManager { protected: - DS::Background _overlay; - Graphics::Surface _framebuffer, _cursor; - bool _graphicsEnable, _isOverlayShown; + DS::Background _framebuffer, _overlay; +#ifdef DISABLE_TEXT_CONSOLE + DS::Background _subScreen; +#endif + Graphics::Surface _cursor; int _graphicsMode, _stretchMode; static OSystem_DS *_instance; @@ -60,9 +62,6 @@ protected: void initGraphics(); - void dmaBlit(uint16 *dst, const uint dstPitch, const uint16 *src, const uint srcPitch, - const uint w, const uint h, const uint bytesPerPixel); - bool _disableCursorPalette; const Graphics::PixelFormat _pfCLUT8, _pfABGR1555; @@ -138,9 +137,6 @@ public: virtual void setFocusRectangle(const Common::Rect& rect); virtual void clearFocusRectangle(); - virtual void engineInit(); - virtual void engineDone(); - virtual void initBackend(); virtual Graphics::Surface *lockScreen();