Skip to content

Commit

Permalink
3DS: WIP Dynamic color formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
BallM4788 committed Dec 2, 2019
1 parent 1072fca commit 08e9557
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 35 deletions.
116 changes: 89 additions & 27 deletions backends/platform/3ds/osystem-graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@
#include "config.h"

// Used to transfer the final rendered display to the framebuffer
#define DISPLAY_TRANSFER_FLAGS \
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | \
GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
#define DISPLAY_TRANSFER_FLAGS(inFmt) \
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | \
GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(inFmt) | \
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))

#define GX_RGBA8 GX_TRANSFER_FMT_RGBA8
#define GX_RGB565 GX_TRANSFER_FMT_RGB565

namespace _3DS {

void OSystem_3DS::initGraphics() {
void OSystem_3DS::init3DSGraphics() {
_pfGame = Graphics::PixelFormat::createFormatCLUT8();
_pfGameTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);

Expand All @@ -49,13 +52,13 @@ void OSystem_3DS::initGraphics() {
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetClear(_renderTargetTop, C3D_CLEAR_ALL, 0x0000000, 0);
C3D_RenderTargetSetOutput(_renderTargetTop, GFX_TOP, GFX_LEFT,
DISPLAY_TRANSFER_FLAGS);
DISPLAY_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGBA8));

_renderTargetBottom =
C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetClear(_renderTargetBottom, C3D_CLEAR_ALL, 0x00000000, 0);
C3D_RenderTargetSetOutput(_renderTargetBottom, GFX_BOTTOM, GFX_LEFT,
DISPLAY_TRANSFER_FLAGS);
DISPLAY_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGBA8));

// Load and bind simple default shader (shader.v.pica)
_dvlb = DVLB_ParseFile((u32*)shader_shbin, shader_shbin_size);
Expand Down Expand Up @@ -83,7 +86,7 @@ void OSystem_3DS::initGraphics() {
C3D_CullFace(GPU_CULL_NONE);
}

void OSystem_3DS::destroyGraphics() {
void OSystem_3DS::destroy3DSGraphics() {
_gameScreen.free();
_gameTopTexture.free();
_gameBottomTexture.free();
Expand All @@ -101,7 +104,7 @@ void OSystem_3DS::destroyGraphics() {

bool OSystem_3DS::hasFeature(OSystem::Feature f) {
return (f == OSystem::kFeatureCursorPalette ||
f == OSystem::kFeatureOverlaySupportsAlpha);
f == OSystem::kFeatureOverlaySupportsAlpha);
}

void OSystem_3DS::setFeatureState(OSystem::Feature f, bool enable) {
Expand Down Expand Up @@ -144,27 +147,70 @@ void OSystem_3DS::resetGraphicsScale() {
int OSystem_3DS::getGraphicsMode() const {
return GFX_LINEAR;
}

// Begin added
void OSystem_3DS::alterRenderTgtFmt(C3D_RenderTarget* target, GPU_COLORBUF colorFmt,
GX_TRANSFER_FORMAT oldTransFmt,
GX_TRANSFER_FORMAT newTransFmt) {
C3D_FrameBuf* fb = &target->frameBuf;
if (target->ownsColor)
vramFree(target->frameBuf.colorBuf);
void* colorBuf = vramAlloc(C3D_CalcColorBufSize(fb->width,fb->height,colorFmt));
C3D_FrameBufColor(fb, colorBuf, colorFmt);
target->ownsColor = true;
// C3D_RenderTargetClear(target, C3D_CLEAR_ALL, 0x0000000, 0);
target->transferFlags = DISPLAY_TRANSFER_FLAGS(newTransFmt);
}
// End added

void OSystem_3DS::initSize(uint width, uint height,
const Graphics::PixelFormat *format) {
const Graphics::PixelFormat *format) {
debug("3ds initsize w:%d h:%d", width, height);
int oldScreen = config.screen;
loadConfig();
if (config.screen != oldScreen) {
_screenChangeId++;
}

if (format) {
// Begin added
if (format->bytesPerPixel != _pfGameTexture.bytesPerPixel) {
if ((format->bytesPerPixel == 1) && (_pfGameTexture.bytesPerPixel == 4)) {
// Do nothing
} else {
C3D_Flush();
if (format->bytesPerPixel == 2) {
_pfGameTexture = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
alterRenderTgtFmt(_renderTargetTop, GPU_RB_RGB565, GX_RGBA8, GX_RGB565);
alterRenderTgtFmt(_renderTargetBottom, GPU_RB_RGB565, GX_RGBA8, GX_RGB565);
// _renderTargetTop->transferFlags = DISPLAY_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGB565);
// _renderTargetBottom->transferFlags = DISPLAY_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGB565);
} else {
_pfGameTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
alterRenderTgtFmt(_renderTargetTop, GPU_RB_RGBA8, GX_RGB565, GX_RGBA8);
alterRenderTgtFmt(_renderTargetBottom, GPU_RB_RGBA8, GX_RGB565, GX_RGBA8);
// _renderTargetTop->transferFlags = DISPLAY_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGBA8);
// _renderTargetBottom->transferFlags = DISPLAY_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGBA8);
}
_gameScreen.free();
_gameTopTexture.free();
_gameBottomTexture.free();
_overlay.free();
_activityIcon.free();
}
}
// End added
debug("pixelformat: %d %d %d %d %d", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());
_pfGame = *format;
}

_gameWidth = width;
_gameHeight = height;
_gameTopTexture.create(width, height, _pfGameTexture);
_overlay.create(400, 320, _pfGameTexture);
_magCenterX = _magWidth / 2;
_magCenterY = _magHeight / 2;

if (format) {
debug("pixelformat: %d %d %d %d %d", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());
_pfGame = *format;
}

_gameScreen.create(width, height, _pfGame);

_focusDirty = true;
Expand Down Expand Up @@ -259,7 +305,7 @@ void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) const {
}

void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
int y, int w, int h) {
int y, int w, int h) {
Common::Rect rect(x, y, x+w, y+h);
_gameScreen.copyRectToSurface(buf, pitch, x, y, w, h);
Graphics::Surface subSurface = _gameScreen.getSubArea(rect);
Expand Down Expand Up @@ -508,7 +554,7 @@ void OSystem_3DS::grabOverlay(void *buf, int pitch) {
}

void OSystem_3DS::copyRectToOverlay(const void *buf, int pitch, int x,
int y, int w, int h) {
int y, int w, int h) {
_overlay.copyRectToSurface(buf, pitch, x, y, w, h);
_overlay.markDirty();
}
Expand Down Expand Up @@ -556,9 +602,9 @@ void OSystem_3DS::displayMessageOnOSD(const char *msg) {
// Render the message, centered, and in white
for (i = 0; i < lines.size(); i++) {
font->drawString(&_osdMessage, lines[i],
0, 0 + i * lineHeight + vOffset + lineSpacing, width,
_pfGameTexture.RGBToColor(255, 255, 255),
Graphics::kTextAlignCenter);
0, 0 + i * lineHeight + vOffset + lineSpacing, width,
_pfGameTexture.RGBToColor(255, 255, 255),
Graphics::kTextAlignCenter);
}

_osdMessageEndTime = getMillis(true) + kOSDMessageDuration;
Expand Down Expand Up @@ -618,9 +664,9 @@ void OSystem_3DS::setCursorDelta(float deltaX, float deltaY) {
}

void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
int hotspotX, int hotspotY,
uint32 keycolor, bool dontScale,
const Graphics::PixelFormat *format) {
int hotspotX, int hotspotY,
uint32 keycolor, bool dontScale,
const Graphics::PixelFormat *format) {
_cursorScalable = !dontScale;
_cursorHotspotX = hotspotX;
_cursorHotspotY = hotspotY;
Expand Down Expand Up @@ -651,23 +697,39 @@ void OSystem_3DS::setCursorPalette(const byte *colors, uint start, uint num) {
namespace {
template<typename SrcColor>
void applyKeyColor(Graphics::Surface *src, Graphics::Surface *dst, const SrcColor keyColor) {
assert(dst->format.bytesPerPixel == 4);
// assert(dst->format.bytesPerPixel == 4);
assert((dst->w >= src->w) && (dst->h >= src->h));

uint32 *dstPtr32 = NULL;
uint16 *dstPtr16 = NULL;

for (uint y = 0; y < src->h; ++y) {
SrcColor *srcPtr = (SrcColor *)src->getBasePtr(0, y);
uint32 *dstPtr = (uint32 *)dst->getBasePtr(0, y);
if (dst->format.bytesPerPixel == 4) {
dstPtr32 = (uint32 *)dst->getBasePtr(0, y);
} else {
dstPtr16 = (uint16 *)dst->getBasePtr(0, y);
}

for (uint x = 0; x < src->w; ++x) {
const SrcColor color = *srcPtr++;

if (color == keyColor) {
*dstPtr = 0;
if (dst->format.bytesPerPixel == 4) {
*dstPtr32 = 0;
} else {
*dstPtr16 = 0;
}
}

dstPtr++;
if (dst->format.bytesPerPixel == 4) {
dstPtr32++;
} else {
dstPtr16++;
}
}
}

}
} // End of anonymous namespace

Expand Down
4 changes: 2 additions & 2 deletions backends/platform/3ds/osystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ OSystem_3DS::~OSystem_3DS() {
exiting = true;
destroyEvents();
destroyAudio();
destroyGraphics();
destroy3DSGraphics();

delete _timerManager;
_timerManager = 0;
Expand All @@ -118,7 +118,7 @@ void OSystem_3DS::initBackend() {
_timerManager = new DefaultTimerManager();
_savefileManager = new DefaultSaveFileManager("sdmc:/3ds/scummvm/saves/");

initGraphics();
init3DSGraphics();
initAudio();
initEvents();
EventsBaseBackend::initBackend();
Expand Down
7 changes: 5 additions & 2 deletions backends/platform/3ds/osystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
int getGraphicsMode() const;
inline Graphics::PixelFormat getScreenFormat() const { return _pfGame; }
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
void alterRenderTgtFmt(C3D_RenderTarget* target, GPU_COLORBUF colorFmt,
GX_TRANSFER_FORMAT oldTransFmt,
GX_TRANSFER_FORMAT newTransFmt);
void initSize(uint width, uint height,
const Graphics::PixelFormat *format = NULL);
virtual int getScreenChangeID() const { return _screenChangeId; };
Expand Down Expand Up @@ -156,8 +159,8 @@ class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
MagnifyMode getMagnifyMode(){ return _magnifyMode; }

private:
void initGraphics();
void destroyGraphics();
void init3DSGraphics();
void destroy3DSGraphics();
void initAudio();
void destroyAudio();
void initEvents();
Expand Down
13 changes: 11 additions & 2 deletions backends/platform/3ds/sprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "backends/platform/3ds/sprite.h"
#include "common/util.h"

#define GX_RGBA8 GX_TRANSFER_FMT_RGBA8
#define GX_RGB565 GX_TRANSFER_FMT_RGB565

static uint nextHigher2(uint v) {
if (v == 0)
return 1;
Expand Down Expand Up @@ -69,7 +72,11 @@ void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f)

if (width && height) {
pixels = linearAlloc(h * pitch);
C3D_TexInit(&texture, w, h, GPU_RGBA8);
if (format.bytesPerPixel == 2) {
C3D_TexInit(&texture, w, h, GPU_RGB565);
} else {
C3D_TexInit(&texture, w, h, GPU_RGBA8);
}
C3D_TexSetFilter(&texture, GPU_LINEAR, GPU_LINEAR);
assert(pixels && texture.data);
clear();
Expand Down Expand Up @@ -104,8 +111,10 @@ void Sprite::convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte
void Sprite::transfer() {
if (pixels && dirtyPixels) {
dirtyPixels = false;
GX_TRANSFER_FORMAT transFmt = (format.bytesPerPixel == 2) ? GX_RGB565 : GX_RGBA8;
GSPGPU_FlushDataCache(pixels, w * h * format.bytesPerPixel);
C3D_SyncDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), TEXTURE_TRANSFER_FLAGS);
C3D_SyncDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h),
TEXTURE_TRANSFER_FLAGS(transFmt));
}
}

Expand Down
4 changes: 2 additions & 2 deletions backends/platform/3ds/sprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
#include <3ds.h>
#include <citro3d.h>

#define TEXTURE_TRANSFER_FLAGS \
#define TEXTURE_TRANSFER_FLAGS(transFmt) \
(GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | \
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
GX_TRANSFER_IN_FORMAT(transFmt) | GX_TRANSFER_OUT_FORMAT(transFmt) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))

typedef struct {
Expand Down

0 comments on commit 08e9557

Please sign in to comment.