DS: Use the Background class for the game screen

This commit is contained in:
Cameron Cawley 2020-12-05 17:04:44 +00:00 committed by Eugene Sandulenko
parent b37843f10d
commit 7ddd7e4931
5 changed files with 156 additions and 109 deletions

View file

@ -23,17 +23,32 @@
#include <nds.h>
#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;
}

View file

@ -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

View file

@ -23,7 +23,6 @@
#include <nds.h>
#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<Graphics::PixelFormat> 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
}
}
}

View file

@ -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);

View file

@ -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();