mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-13 15:40:57 +00:00
BACKENDS: ATARI: Use RGB332 for the overlay
This commit is contained in:
parent
6c5e3dbfd5
commit
52f8bd45e2
@ -213,16 +213,19 @@ set_tt_palette_loop:
|
||||
dbra d0,set_tt_palette_loop
|
||||
rts
|
||||
|
||||
| extern void asm_screen_set_falcon_palette(const uint32 pPalette[256]);
|
||||
| extern void asm_screen_set_falcon_palette(const byte pPalette[256*3]);
|
||||
|
|
||||
_asm_screen_set_falcon_palette:
|
||||
move.l (4,sp),a0
|
||||
lea pending_palette,a1
|
||||
moveq #256/2-1,d0
|
||||
move.w #256-1,d0
|
||||
|
||||
set_falcon_palette_loop:
|
||||
move.l (a0)+,(a1)+
|
||||
move.l (a0)+,(a1)+
|
||||
clr.l d1
|
||||
move.w (a0)+,d1
|
||||
swap d1
|
||||
move.b (a0)+,d1
|
||||
move.l d1,(a1)+
|
||||
dbra d0,set_falcon_palette_loop
|
||||
|
||||
addq.w #1,has_pending_palette
|
||||
|
@ -51,9 +51,9 @@ void asm_screen_falcon_restore(void);
|
||||
void asm_screen_set_tt_palette(const uint16 pPalette[256]);
|
||||
/**
|
||||
* Set Atari Falcon palette.
|
||||
* @param pPalette 256 palette entries (RRRRRRrr GGGGGGgg 00000000 BBBBBBbb)
|
||||
* @param pPalette 256 palette entries (RRRRRRRR GGGGGGGG BBBBBBBB)
|
||||
*/
|
||||
void asm_screen_set_falcon_palette(const uint32 pPalette[256]);
|
||||
void asm_screen_set_falcon_palette(const byte pPalette[256*3]);
|
||||
|
||||
/**
|
||||
* Set Atari TT/Falcon video base.
|
||||
|
@ -71,9 +71,6 @@ public:
|
||||
return graphicsModes;
|
||||
}
|
||||
|
||||
int16 getOverlayHeight() const override { return 2 * OVERLAY_HEIGHT; }
|
||||
int16 getOverlayWidth() const override { return 2 * OVERLAY_WIDTH; }
|
||||
|
||||
protected:
|
||||
AtariMemAlloc getStRamAllocFunc() const override {
|
||||
return [](size_t bytes) {
|
||||
@ -96,9 +93,9 @@ private:
|
||||
dstSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
|
||||
}
|
||||
|
||||
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface,
|
||||
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &bgSurface,
|
||||
const Graphics::Surface &srcSurface, int destX, int destY,
|
||||
const Common::Rect &subRect, uint32 key) const override {
|
||||
const Common::Rect &subRect, uint32 key, const byte srcPalette[256*3]) const override {
|
||||
dstSurface.copyRectToSurfaceWithKey(srcSurface, destX, destY, subRect, key);
|
||||
}
|
||||
|
||||
|
@ -64,9 +64,6 @@ public:
|
||||
return AtariGraphicsManager::endGFXTransaction();
|
||||
}
|
||||
|
||||
int16 getOverlayHeight() const override { return _vgaMonitor ? OVERLAY_HEIGHT : 2 * OVERLAY_HEIGHT; }
|
||||
int16 getOverlayWidth() const override { return _vgaMonitor ? OVERLAY_WIDTH : 2 * OVERLAY_WIDTH; }
|
||||
|
||||
private:
|
||||
void copyRectToSurface(Graphics::Surface &dstSurface,
|
||||
const Graphics::Surface &srcSurface, int destX, int destY,
|
||||
@ -91,12 +88,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: allow specifying different background than _chunkySurface?
|
||||
// TODO: alignRect and this function could be perhaps better if we know that all surfaces
|
||||
// are aligned on 16px and their pitch is % 16 as well?
|
||||
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface,
|
||||
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &bgSurface,
|
||||
const Graphics::Surface &srcSurface, int destX, int destY,
|
||||
const Common::Rect &subRect, uint32 key) const override {
|
||||
const Common::Rect &subRect, uint32 key, const byte srcPalette[256*3]) const override {
|
||||
Common::Rect backgroundRect(destX, destY, destX + subRect.width(), destY + subRect.height());
|
||||
|
||||
// ensure that background's left and right lie on a 16px boundary and double the width if needed
|
||||
@ -105,22 +99,52 @@ private:
|
||||
const int deltaX = destX - backgroundRect.left;
|
||||
|
||||
backgroundRect.right = (backgroundRect.right + deltaX + 15) & 0xfff0;
|
||||
if (backgroundRect.right > _chunkySurface.w)
|
||||
backgroundRect.right = _chunkySurface.w;
|
||||
if (backgroundRect.right > bgSurface.w)
|
||||
backgroundRect.right = bgSurface.w;
|
||||
|
||||
static Graphics::Surface cachedSurface;
|
||||
|
||||
if (cachedSurface.w != backgroundRect.width() || cachedSurface.h != backgroundRect.height()) {
|
||||
if (cachedSurface.w != backgroundRect.width()
|
||||
|| cachedSurface.h != backgroundRect.height()
|
||||
|| cachedSurface.format != bgSurface.format) {
|
||||
cachedSurface.create(
|
||||
backgroundRect.width(),
|
||||
backgroundRect.height(),
|
||||
_chunkySurface.format);
|
||||
bgSurface.format);
|
||||
}
|
||||
|
||||
// copy background
|
||||
cachedSurface.copyRectToSurface(_chunkySurface, 0, 0, backgroundRect);
|
||||
cachedSurface.copyRectToSurface(bgSurface, 0, 0, backgroundRect);
|
||||
|
||||
// copy cursor
|
||||
cachedSurface.copyRectToSurfaceWithKey(srcSurface, deltaX, 0, subRect, key);
|
||||
if (cachedSurface.format == PIXELFORMAT_RGB332) {
|
||||
assert(srcSurface.format == PIXELFORMAT_CLUT8);
|
||||
|
||||
// Convert CLUT8 to RGB332 palette and do copyRectToSurfaceWithKey() at the same time
|
||||
const byte *src = (const byte*)srcSurface.getBasePtr(subRect.left, subRect.top);
|
||||
byte *dst = (byte*)cachedSurface.getBasePtr(deltaX, 0);
|
||||
|
||||
const int16 w = subRect.width();
|
||||
const int16 h = subRect.height();
|
||||
|
||||
for (int16 y = 0; y < h; ++y) {
|
||||
for (int16 x = 0; x < w; ++x) {
|
||||
const uint32 color = *src++;
|
||||
if (color != key) {
|
||||
*dst++ = (srcPalette[color*3 + 0] & 0xe0)
|
||||
| ((srcPalette[color*3 + 1] >> 3) & 0x1c)
|
||||
| ((srcPalette[color*3 + 2] >> 6) & 0x03);
|
||||
} else {
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
src += (srcSurface.pitch - w);
|
||||
dst += (cachedSurface.pitch - w);
|
||||
}
|
||||
} else {
|
||||
cachedSurface.copyRectToSurfaceWithKey(srcSurface, deltaX, 0, subRect, key);
|
||||
}
|
||||
|
||||
copyRectToSurface(
|
||||
dstSurface,
|
||||
|
@ -63,6 +63,13 @@ AtariGraphicsManager::AtariGraphicsManager() {
|
||||
|
||||
ConfMan.flushToDisk();
|
||||
|
||||
// Generate RGB332 palette for the overlay
|
||||
for (uint i = 0; i < 256; i++) {
|
||||
_overlayPalette[i*3 + 0] = ((i >> 5) & 7) << 5;
|
||||
_overlayPalette[i*3 + 1] = ((i >> 2) & 7) << 5;
|
||||
_overlayPalette[i*3 + 2] = (i & 3) << 6;
|
||||
}
|
||||
|
||||
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
|
||||
}
|
||||
|
||||
@ -76,8 +83,13 @@ bool AtariGraphicsManager::hasFeature(OSystem::Feature f) const {
|
||||
debug("hasFeature(kFeatureAspectRatioCorrection): %d", !_vgaMonitor);
|
||||
return !_vgaMonitor;
|
||||
case OSystem::Feature::kFeatureCursorPalette:
|
||||
debug("hasFeature(kFeatureCursorPalette): %d", isOverlayVisible());
|
||||
return isOverlayVisible();
|
||||
// XXX: pretend to have cursor palette all the time, this function
|
||||
// can get called (and it is) any time, before and after showOverlay()
|
||||
// (overlay cursor uses the cross if kFeatureCursorPalette returns false
|
||||
// here too soon)
|
||||
//debug("hasFeature(kFeatureCursorPalette): %d", isOverlayVisible());
|
||||
//return isOverlayVisible();
|
||||
return true;
|
||||
case OSystem::Feature::kFeatureVSync:
|
||||
debug("hasFeature(kFeatureVSync): %d", _vsync);
|
||||
return true;
|
||||
@ -109,7 +121,8 @@ bool AtariGraphicsManager::getFeatureState(OSystem::Feature f) const {
|
||||
return _aspectRatioCorrection;
|
||||
case OSystem::Feature::kFeatureCursorPalette:
|
||||
//debug("getFeatureState(kFeatureCursorPalette): %d", isOverlayVisible());
|
||||
return isOverlayVisible();
|
||||
//return isOverlayVisible();
|
||||
return true;
|
||||
case OSystem::Feature::kFeatureVSync:
|
||||
//debug("getFeatureState(kFeatureVSync): %d", _vsync);
|
||||
return _vsync;
|
||||
@ -134,7 +147,7 @@ void AtariGraphicsManager::initSize(uint width, uint height, const Graphics::Pix
|
||||
|
||||
_pendingState.width = width;
|
||||
_pendingState.height = height;
|
||||
_pendingState.format = format ? *format : PIXELFORMAT8;
|
||||
_pendingState.format = format ? *format : PIXELFORMAT_CLUT8;
|
||||
}
|
||||
|
||||
void AtariGraphicsManager::beginGFXTransaction() {
|
||||
@ -150,7 +163,7 @@ OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
|
||||
//if (_pendingState == _currentState)
|
||||
// return static_cast<OSystem::TransactionError>(error);
|
||||
|
||||
if (_pendingState.format != PIXELFORMAT8)
|
||||
if (_pendingState.format != PIXELFORMAT_CLUT8)
|
||||
error |= OSystem::TransactionError::kTransactionFormatNotSupported;
|
||||
|
||||
// TODO: Several engines support unusual resolutions like 256x240 (NES Maniac Mansion),
|
||||
@ -354,17 +367,13 @@ void AtariGraphicsManager::updateScreen() {
|
||||
bool resolutionChanged = false;
|
||||
|
||||
if (_pendingScreenChange & kPendingScreenChangeOverlay) {
|
||||
if (_vgaMonitor) {
|
||||
if (getOverlayWidth() == 640 && getOverlayHeight() == 480)
|
||||
asm_screen_set_scp_res(scp_640x480x16_vga);
|
||||
else
|
||||
asm_screen_set_scp_res(scp_320x240x16_vga);
|
||||
} else {
|
||||
//asm_screen_set_scp_res(scp_320x240x16_rgb);
|
||||
asm_screen_set_scp_res(scp_640x480x16_rgb);
|
||||
}
|
||||
if (_vgaMonitor)
|
||||
asm_screen_set_scp_res(scp_640x480x8_vga);
|
||||
else
|
||||
asm_screen_set_scp_res(scp_640x480x8_rgb);
|
||||
|
||||
asm_screen_set_vram(_screenOverlaySurface.getPixels());
|
||||
asm_screen_set_falcon_palette(_overlayPalette);
|
||||
resolutionChanged = true;
|
||||
}
|
||||
|
||||
@ -374,16 +383,8 @@ void AtariGraphicsManager::updateScreen() {
|
||||
resolutionChanged = true;
|
||||
}
|
||||
|
||||
if ((_pendingScreenChange & kPendingScreenChangePalette) && !isOverlayVisible()) {
|
||||
static uint falconPalette[256];
|
||||
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
// RRRRRRRR GGGGGGGG BBBBBBBB -> RRRRRRrr GGGGGGgg 00000000 BBBBBBbb
|
||||
falconPalette[i] = (_palette[i * 3 + 0] << 24) | (_palette[i * 3 + 1] << 16) | _palette[i * 3 + 2];
|
||||
}
|
||||
#ifdef SCREEN_ACTIVE
|
||||
asm_screen_set_falcon_palette(falconPalette);
|
||||
#endif
|
||||
if (_pendingScreenChange & kPendingScreenChangePalette) {
|
||||
asm_screen_set_falcon_palette(_palette);
|
||||
}
|
||||
|
||||
_pendingScreenChange = kPendingScreenChangeNone;
|
||||
@ -411,7 +412,7 @@ void AtariGraphicsManager::showOverlay(bool inGUI) {
|
||||
if (_overlayVisible)
|
||||
return;
|
||||
|
||||
_pendingScreenChange &= ~kPendingScreenChangeScreen;
|
||||
_pendingScreenChange &= ~(kPendingScreenChangeScreen | kPendingScreenChangePalette);
|
||||
_pendingScreenChange |= kPendingScreenChangeOverlay;
|
||||
|
||||
_cursor.swap();
|
||||
@ -433,7 +434,7 @@ void AtariGraphicsManager::hideOverlay() {
|
||||
return;
|
||||
|
||||
_pendingScreenChange &= ~kPendingScreenChangeOverlay;
|
||||
_pendingScreenChange |= kPendingScreenChangeScreen;
|
||||
_pendingScreenChange |= (kPendingScreenChangeScreen | kPendingScreenChangePalette);
|
||||
|
||||
_cursor.swap();
|
||||
// don't fool game cursor logic (especially direct rendering)
|
||||
@ -463,29 +464,44 @@ void AtariGraphicsManager::clearOverlay() {
|
||||
vOffset = (480 - 400) / 2;
|
||||
}
|
||||
|
||||
ScaleMode scaleMode;
|
||||
if (w == _overlaySurface.w && h == _overlaySurface.h) {
|
||||
scaleMode = ScaleMode::NONE;
|
||||
} else if (w / _overlaySurface.w == 2 && h / _overlaySurface.h == 2) {
|
||||
scaleMode = ScaleMode::DOWNSCALE;
|
||||
vOffset /= 2;
|
||||
} else if (_overlaySurface.w / w == 2 && _overlaySurface.h / h == 2) {
|
||||
scaleMode = ScaleMode::UPSCALE;
|
||||
bool upscale = false;
|
||||
|
||||
if (_overlaySurface.w / w == 2 && _overlaySurface.h / h == 2) {
|
||||
upscale = true;
|
||||
vOffset *= 2;
|
||||
} else {
|
||||
warning("Unknown overlay (%d, %d) / screen (%d, %d) ratio: ",
|
||||
} else if (vOffset != 0) {
|
||||
warning("Unknown overlay (%d, %d) / screen (%d, %d) ratio",
|
||||
_overlaySurface.w, _overlaySurface.h, w, h);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(_overlaySurface.getBasePtr(0, 0), 0, _overlaySurface.pitch * vOffset);
|
||||
copySurface8ToSurface16(
|
||||
sourceSurface,
|
||||
_palette,
|
||||
_overlaySurface,
|
||||
0, vOffset,
|
||||
Common::Rect(sourceSurface.w, sourceSurface.h),
|
||||
scaleMode);
|
||||
|
||||
// Transpose from game palette to RGB332 (overlay palette)
|
||||
const byte *src = (const byte*)sourceSurface.getPixels();
|
||||
byte *dst = (byte*)_overlaySurface.getBasePtr(0, vOffset);
|
||||
|
||||
for (int y = 0; y < sourceSurface.h; y++) {
|
||||
for (int x = 0; x < sourceSurface.w; x++) {
|
||||
const byte col = *src++;
|
||||
const byte pixel = (_palette[3*col + 0] & 0xe0)
|
||||
| ((_palette[3*col + 1] >> 3) & 0x1c)
|
||||
| ((_palette[3*col + 2] >> 6) & 0x03);
|
||||
|
||||
if (upscale) {
|
||||
*(dst + _overlaySurface.pitch) = pixel;
|
||||
*dst++ = pixel;
|
||||
*(dst + _overlaySurface.pitch) = pixel;
|
||||
*dst++ = pixel;
|
||||
} else {
|
||||
*dst++ = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
if (upscale)
|
||||
dst += _overlaySurface.pitch;
|
||||
}
|
||||
|
||||
memset(_overlaySurface.getBasePtr(0, _overlaySurface.h - vOffset), 0, _overlaySurface.pitch * vOffset);
|
||||
|
||||
handleModifiedRect(_overlaySurface, Common::Rect(_overlaySurface.w, _overlaySurface.h), _modifiedOverlayRects);
|
||||
@ -530,7 +546,7 @@ void AtariGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int h
|
||||
if (mask)
|
||||
warning("AtariGraphicsManager::setMouseCursor: Masks are not supported");
|
||||
|
||||
const Graphics::PixelFormat cursorFormat = format ? *format : PIXELFORMAT8;
|
||||
const Graphics::PixelFormat cursorFormat = format ? *format : PIXELFORMAT_CLUT8;
|
||||
_cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor, cursorFormat);
|
||||
}
|
||||
|
||||
@ -576,14 +592,14 @@ Common::Keymap *AtariGraphicsManager::getKeymap() const {
|
||||
void AtariGraphicsManager::allocateSurfaces() {
|
||||
for (int i = 0; i < SCREENS; ++i) {
|
||||
if (!(_screen[i] = allocateAtariSurface(_screenSurface,
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8,
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT_CLUT8,
|
||||
getStRamAllocFunc())))
|
||||
error("Failed to allocate screen memory in ST RAM");
|
||||
_screenAligned[i] = (byte*)_screenSurface.getPixels();
|
||||
}
|
||||
_screenSurface.setPixels(_screenAligned[getDefaultGraphicsMode() <= 1 ? FRONT_BUFFER : BACK_BUFFER1]);
|
||||
|
||||
_chunkySurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8);
|
||||
_chunkySurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT_CLUT8);
|
||||
|
||||
if (!(_overlayScreen = allocateAtariSurface(_screenOverlaySurface,
|
||||
getOverlayWidth(), getOverlayHeight(), getOverlayFormat(),
|
||||
@ -658,7 +674,7 @@ bool AtariGraphicsManager::updateOverlay() {
|
||||
if (!drawCursor && !_cursor.outOfScreen && _cursor.visible)
|
||||
drawCursor = rect.intersects(_cursor.dstRect);
|
||||
|
||||
_screenOverlaySurface.copyRectToSurface(_overlaySurface, rect.left, rect.top, rect);
|
||||
copyRectToSurface(_screenOverlaySurface, _overlaySurface, rect.left, rect.top, rect);
|
||||
|
||||
_modifiedOverlayRects.pop_back();
|
||||
|
||||
@ -669,7 +685,8 @@ bool AtariGraphicsManager::updateOverlay() {
|
||||
return updated;
|
||||
|
||||
if ((_cursor.positionChanged || !_cursor.visible) && !_oldCursorRect.isEmpty()) {
|
||||
_screenOverlaySurface.copyRectToSurface(_overlaySurface, _oldCursorRect.left, _oldCursorRect.top, _oldCursorRect);
|
||||
alignRect(_screenOverlaySurface, _oldCursorRect);
|
||||
copyRectToSurface(_screenOverlaySurface, _overlaySurface, _oldCursorRect.left, _oldCursorRect.top, _oldCursorRect);
|
||||
_oldCursorRect = Common::Rect();
|
||||
|
||||
updated = true;
|
||||
@ -677,14 +694,10 @@ bool AtariGraphicsManager::updateOverlay() {
|
||||
|
||||
if (drawCursor && _cursor.visible) {
|
||||
//debug("Redraw cursor (overlay): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
|
||||
|
||||
copySurface8ToSurface16WithKey(
|
||||
_cursor.surface,
|
||||
_cursor.palette,
|
||||
_screenOverlaySurface,
|
||||
copyRectToSurfaceWithKey(
|
||||
_screenOverlaySurface, _overlaySurface, _cursor.surface,
|
||||
_cursor.dstRect.left, _cursor.dstRect.top,
|
||||
_cursor.srcRect,
|
||||
_cursor.keycolor);
|
||||
_cursor.srcRect, _cursor.keycolor, _cursor.palette);
|
||||
|
||||
_cursor.positionChanged = _cursor.surfaceChanged = false;
|
||||
_oldCursorRect = _cursor.dstRect;
|
||||
@ -795,9 +808,9 @@ bool AtariGraphicsManager::updateSingleBuffer() {
|
||||
if (drawCursor && _cursor.visible) {
|
||||
//debug("Redraw cursor (single): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
|
||||
copyRectToSurfaceWithKey(
|
||||
_screenSurface, _cursor.surface,
|
||||
_screenSurface, _chunkySurface, _cursor.surface,
|
||||
_cursor.dstRect.left, _cursor.dstRect.top,
|
||||
_cursor.srcRect, _cursor.keycolor);
|
||||
_cursor.srcRect, _cursor.keycolor, _cursor.palette);
|
||||
|
||||
_cursor.positionChanged = _cursor.surfaceChanged = false;
|
||||
_oldCursorRect = _cursor.dstRect;
|
||||
@ -849,9 +862,9 @@ bool AtariGraphicsManager::updateDoubleAndTripleBuffer() {
|
||||
//debug("Redraw cursor (double/triple): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
|
||||
|
||||
copyRectToSurfaceWithKey(
|
||||
frontBufferScreenSurface, _cursor.surface,
|
||||
frontBufferScreenSurface, _chunkySurface, _cursor.surface,
|
||||
_cursor.dstRect.left, _cursor.dstRect.top,
|
||||
_cursor.srcRect, _cursor.keycolor);
|
||||
_cursor.srcRect, _cursor.keycolor, _cursor.palette);
|
||||
|
||||
_cursor.positionChanged = _cursor.surfaceChanged = false;
|
||||
_oldCursorRect = _cursor.dstRect;
|
||||
@ -882,100 +895,10 @@ void AtariGraphicsManager::freeAtariSurface(byte *ptr, Graphics::Surface &surfac
|
||||
freeFunc(ptr);
|
||||
}
|
||||
|
||||
void AtariGraphicsManager::copySurface8ToSurface16(
|
||||
const Graphics::Surface &srcSurface, const byte *srcPalette,
|
||||
Graphics::Surface &dstSurface, int destX, int destY,
|
||||
const Common::Rect subRect, ScaleMode scaleMode) const {
|
||||
assert(srcSurface.format.bytesPerPixel == 1);
|
||||
assert(dstSurface.format.bytesPerPixel == 2);
|
||||
|
||||
// faster (no memory (re-)allocation) version of Surface::convertTo()
|
||||
const int w = subRect.width();
|
||||
const int h = subRect.height();
|
||||
|
||||
const int srcScale = scaleMode == ScaleMode::DOWNSCALE ? 2 : 1;
|
||||
const byte *srcRow = (const byte*)srcSurface.getBasePtr(subRect.left * srcScale, subRect.top * srcScale);
|
||||
uint16 *dstRow = (uint16*)dstSurface.getBasePtr(destX, destY); // already upscaled if needed
|
||||
|
||||
static uint32 srcPaletteMap[256];
|
||||
Graphics::convertPaletteToMap(srcPaletteMap, srcPalette, 256, dstSurface.format);
|
||||
|
||||
// optimized paths for each case...
|
||||
if (scaleMode == ScaleMode::NONE) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
*dstRow++ = srcPaletteMap[*srcRow++];
|
||||
}
|
||||
|
||||
srcRow += srcSurface.w - w;
|
||||
dstRow += dstSurface.w - w;
|
||||
}
|
||||
} else if (scaleMode == ScaleMode::DOWNSCALE) {
|
||||
for (int y = 0; y < h / 2; y++) {
|
||||
for (int x = 0; x < w / 2; x++) {
|
||||
*dstRow++ = srcPaletteMap[*srcRow];
|
||||
srcRow += 2;
|
||||
}
|
||||
|
||||
srcRow += srcSurface.w - w + srcSurface.w;
|
||||
dstRow += dstSurface.w - w / 2;
|
||||
}
|
||||
} else if (scaleMode == ScaleMode::UPSCALE) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
const uint16 pixel = srcPaletteMap[*srcRow++];
|
||||
|
||||
*(dstRow + dstSurface.w) = pixel;
|
||||
*dstRow++ = pixel;
|
||||
*(dstRow + dstSurface.w) = pixel;
|
||||
*dstRow++ = pixel;
|
||||
}
|
||||
|
||||
srcRow += srcSurface.w - w;
|
||||
dstRow += dstSurface.w - w * 2 + dstSurface.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtariGraphicsManager::copySurface8ToSurface16WithKey(
|
||||
const Graphics::Surface &srcSurface, const byte *srcPalette,
|
||||
Graphics::Surface &dstSurface, int destX, int destY,
|
||||
const Common::Rect subRect, uint32 key) const {
|
||||
assert(srcSurface.format.bytesPerPixel == 1);
|
||||
assert(dstSurface.format.bytesPerPixel == 2);
|
||||
|
||||
// faster (no memory (re-)allocation) version of Surface::convertTo()
|
||||
const int w = subRect.width();
|
||||
const int h = subRect.height();
|
||||
|
||||
const byte *srcRow = (const byte *)srcSurface.getBasePtr(subRect.left, subRect.top);
|
||||
uint16 *dstRow = (uint16 *)dstSurface.getBasePtr(destX, destY);
|
||||
|
||||
static uint32 srcPaletteMap[256];
|
||||
Graphics::convertPaletteToMap(srcPaletteMap, srcPalette, 256, dstSurface.format);
|
||||
|
||||
const uint16 keyColor = srcPaletteMap[key];
|
||||
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
const uint16 pixel = srcPaletteMap[*srcRow++];
|
||||
|
||||
if (pixel != keyColor) {
|
||||
*dstRow++ = pixel;
|
||||
} else {
|
||||
dstRow++;
|
||||
}
|
||||
}
|
||||
|
||||
srcRow += srcSurface.w - w;
|
||||
dstRow += dstSurface.w - w;
|
||||
}
|
||||
}
|
||||
|
||||
void AtariGraphicsManager::handleModifiedRect(
|
||||
const Graphics::Surface &surface,
|
||||
Common::Rect rect, Common::Array<Common::Rect> &rects) const {
|
||||
if (_currentState.mode == GraphicsMode::SingleBuffering)
|
||||
if (_currentState.mode == GraphicsMode::SingleBuffering || isOverlayVisible())
|
||||
alignRect(surface, rect);
|
||||
|
||||
if (rect.width() == surface.w && rect.height() == surface.h) {
|
||||
@ -1034,7 +957,8 @@ void AtariGraphicsManager::Cursor::updatePosition(int deltaX, int deltaY, const
|
||||
positionChanged = true;
|
||||
}
|
||||
|
||||
void AtariGraphicsManager::Cursor::setSurface(const void *buf, int w, int h, int _hotspotX, int _hotspotY, uint32 _keycolor, const Graphics::PixelFormat &format) {
|
||||
void AtariGraphicsManager::Cursor::setSurface(const void *buf, int w, int h, int hotspotX_, int hotspotY_, uint32 keycolor_,
|
||||
const Graphics::PixelFormat &format) {
|
||||
if (w == 0 || h == 0 || buf == nullptr) {
|
||||
if (surface.getPixels())
|
||||
surface.free();
|
||||
@ -1044,11 +968,11 @@ void AtariGraphicsManager::Cursor::setSurface(const void *buf, int w, int h, int
|
||||
if (surface.w != w || surface.h != h || surface.format != format)
|
||||
surface.create(w, h, format);
|
||||
|
||||
surface.copyRectToSurface(buf, w * format.bytesPerPixel, 0, 0, w, h);
|
||||
surface.copyRectToSurface(buf, w * surface.format.bytesPerPixel, 0, 0, w, h);
|
||||
|
||||
hotspotX = _hotspotX;
|
||||
hotspotY = _hotspotY;
|
||||
keycolor = _keycolor;
|
||||
hotspotX = hotspotX_;
|
||||
hotspotY = hotspotY_;
|
||||
keycolor = keycolor_;
|
||||
|
||||
surfaceChanged = true;
|
||||
}
|
||||
|
@ -35,10 +35,6 @@
|
||||
constexpr int SCREEN_WIDTH = 640;
|
||||
constexpr int SCREEN_HEIGHT = 480;
|
||||
|
||||
// minimum overlay dimensions
|
||||
constexpr int OVERLAY_WIDTH = 320;
|
||||
constexpr int OVERLAY_HEIGHT = 240;
|
||||
|
||||
class AtariGraphicsManager : public GraphicsManager, Common::EventObserver {
|
||||
public:
|
||||
AtariGraphicsManager();
|
||||
@ -75,10 +71,12 @@ public:
|
||||
void showOverlay(bool inGUI) override;
|
||||
void hideOverlay() override;
|
||||
bool isOverlayVisible() const override { return _overlayVisible; }
|
||||
Graphics::PixelFormat getOverlayFormat() const override { return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); }
|
||||
Graphics::PixelFormat getOverlayFormat() const override { return PIXELFORMAT_RGB332; }
|
||||
void clearOverlay() override;
|
||||
void grabOverlay(Graphics::Surface &surface) const override;
|
||||
void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
int16 getOverlayHeight() const override { return 480; }
|
||||
int16 getOverlayWidth() const override { return 640; }
|
||||
|
||||
bool showMouse(bool visible) override;
|
||||
void warpMouse(int x, int y) override;
|
||||
@ -93,7 +91,8 @@ public:
|
||||
Common::Keymap *getKeymap() const;
|
||||
|
||||
protected:
|
||||
const Graphics::PixelFormat PIXELFORMAT8 = Graphics::PixelFormat::createFormatCLUT8();
|
||||
const Graphics::PixelFormat PIXELFORMAT_CLUT8 = Graphics::PixelFormat::createFormatCLUT8();
|
||||
const Graphics::PixelFormat PIXELFORMAT_RGB332 = Graphics::PixelFormat(1, 3, 3, 2, 0, 5, 2, 0, 0);
|
||||
|
||||
typedef void* (*AtariMemAlloc)(size_t bytes);
|
||||
typedef void (*AtariMemFree)(void *ptr);
|
||||
@ -141,8 +140,6 @@ protected:
|
||||
static const int BACK_BUFFER1 = 1;
|
||||
static const int BACK_BUFFER2 = 2;
|
||||
|
||||
Graphics::Surface _chunkySurface; // for Videl's copyRectToSurfaceWithKey
|
||||
|
||||
private:
|
||||
enum CustomEventAction {
|
||||
kActionToggleAspectRatioCorrection = 100,
|
||||
@ -165,27 +162,13 @@ private:
|
||||
virtual void copyRectToSurface(Graphics::Surface &dstSurface,
|
||||
const Graphics::Surface &srcSurface, int destX, int destY,
|
||||
const Common::Rect &subRect) const = 0;
|
||||
virtual void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface,
|
||||
virtual void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &bgSurface,
|
||||
const Graphics::Surface &srcSurface, int destX, int destY,
|
||||
const Common::Rect &subRect, uint32 key) const = 0;
|
||||
const Common::Rect &subRect, uint32 key, const byte srcPalette[256*3]) const = 0;
|
||||
virtual void alignRect(const Graphics::Surface &srcSurface, Common::Rect &rect) const {}
|
||||
|
||||
enum class ScaleMode {
|
||||
NONE,
|
||||
UPSCALE,
|
||||
DOWNSCALE
|
||||
};
|
||||
void copySurface8ToSurface16(const Graphics::Surface &srcSurface, const byte *srcPalette,
|
||||
Graphics::Surface &dstSurface, int destX, int destY,
|
||||
const Common::Rect subRect, ScaleMode scaleMode) const;
|
||||
void copySurface8ToSurface16WithKey(const Graphics::Surface &srcSurface, const byte* srcPalette,
|
||||
Graphics::Surface &dstSurface, int destX, int destY,
|
||||
const Common::Rect subRect, uint32 key) const;
|
||||
|
||||
void handleModifiedRect(const Graphics::Surface &surface, Common::Rect rect, Common::Array<Common::Rect> &rects) const;
|
||||
|
||||
void updateCursorRect();
|
||||
|
||||
bool _aspectRatioCorrection = false;
|
||||
bool _oldAspectRatioCorrection = false;
|
||||
bool _vsync = true;
|
||||
@ -206,6 +189,7 @@ private:
|
||||
Common::Rect _modifiedScreenRect; // direct rendering only
|
||||
bool _screenModified = false; // double/triple buffering only
|
||||
|
||||
Graphics::Surface _chunkySurface;
|
||||
Common::Array<Common::Rect> _modifiedChunkyRects;
|
||||
|
||||
byte *_overlayScreen = nullptr; // for Mfree() purposes only
|
||||
@ -265,7 +249,7 @@ private:
|
||||
Common::Rect srcRect;
|
||||
Common::Rect dstRect;
|
||||
|
||||
// palette (only used for 16bpp screen surfaces)
|
||||
// palette (only used for the overlay)
|
||||
byte palette[256*3] = {};
|
||||
|
||||
private:
|
||||
@ -279,6 +263,7 @@ private:
|
||||
Common::Rect _oldCursorRect;
|
||||
|
||||
byte _palette[256*3] = {};
|
||||
byte _overlayPalette[256*3] = {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -108,40 +108,6 @@ byte scp_320x240x8_vga[] = {
|
||||
0x00, 0xa0
|
||||
};
|
||||
|
||||
const byte scp_320x240x16_rgb[] = {
|
||||
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xa9, 0xc1, 0x08, 0x00, 0xc2, 0x8c, 0xb0,
|
||||
0x01, 0x64, 0x05, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
|
||||
0x00, 0xc0, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x2c,
|
||||
0x00, 0xf0, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xfe, 0x00, 0x99, 0x00, 0x59, 0x00, 0x38, 0x00, 0x99,
|
||||
0x00, 0xd9, 0x02, 0x71, 0x02, 0x39, 0x00, 0x59, 0x00, 0x59, 0x02, 0x39,
|
||||
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x40
|
||||
};
|
||||
|
||||
const byte scp_320x240x16_vga[] = {
|
||||
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3a, 0x2f, 0x00, 0x00, 0x19, 0x74, 0x90, 0x00, 0x46, 0x4e, 0x20,
|
||||
0x00, 0x2a, 0x02, 0x80, 0x02, 0x58, 0x00, 0x00, 0x7a, 0xee, 0x00, 0x00,
|
||||
0x00, 0x3e, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x01, 0xb2, 0x00, 0x1e,
|
||||
0x01, 0xe0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x01, 0xe8, 0x48, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xc6, 0x00, 0x8d, 0x00, 0x15, 0x02, 0xac, 0x00, 0x8d,
|
||||
0x00, 0x97, 0x04, 0x19, 0x03, 0xfd, 0x00, 0x3f, 0x00, 0x3d, 0x03, 0xfd,
|
||||
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05,
|
||||
0x01, 0x40
|
||||
};
|
||||
|
||||
const byte scp_640x400x8_rgb[] = {
|
||||
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@ -226,37 +192,3 @@ byte scp_640x480x8_vga[] = {
|
||||
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08,
|
||||
0x01, 0x40
|
||||
};
|
||||
|
||||
const byte scp_640x480x16_rgb[] = {
|
||||
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x36, 0x34, 0x30, 0x2a,
|
||||
0x34, 0x38, 0x30, 0x2c, 0x20, 0x54, 0x72, 0x75, 0x65, 0x20, 0x43, 0x6f,
|
||||
0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x35, 0x30, 0x2e, 0x30, 0x20, 0x48, 0x7a,
|
||||
0x20, 0x28, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x2e, 0x29, 0x2c, 0x20,
|
||||
0x31, 0x35, 0x36, 0x32, 0x35, 0x20, 0x48, 0x7a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xa9, 0xc1, 0x08, 0x00, 0xc3, 0x80, 0xd4,
|
||||
0x01, 0x64, 0x05, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
|
||||
0x00, 0xc0, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x2c,
|
||||
0x00, 0xf0, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0xfe, 0x01, 0x32, 0x00, 0xb2, 0x00, 0x81, 0x01, 0x32,
|
||||
0x01, 0xb3, 0x02, 0x70, 0x02, 0x39, 0x00, 0x59, 0x00, 0x58, 0x02, 0x38,
|
||||
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06,
|
||||
0x02, 0x80
|
||||
};
|
||||
|
||||
const byte scp_640x480x16_vga[] = {
|
||||
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x36, 0x34, 0x30, 0x2a,
|
||||
0x34, 0x38, 0x30, 0x2c, 0x20, 0x54, 0x72, 0x75, 0x65, 0x20, 0x43, 0x6f,
|
||||
0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x36, 0x30, 0x2e, 0x30, 0x20, 0x48, 0x7a,
|
||||
0x2c, 0x20, 0x33, 0x31, 0x34, 0x37, 0x30, 0x20, 0x48, 0x7a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3a, 0x2f, 0x00, 0x00, 0x1a, 0xaa, 0xe0, 0x00, 0x45, 0x17, 0xd0,
|
||||
0x00, 0x2c, 0x02, 0x80, 0x02, 0x58, 0x00, 0x00, 0x7a, 0xee, 0x00, 0x00,
|
||||
0x00, 0x3e, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x01, 0x93, 0x00, 0x1f,
|
||||
0x01, 0xe0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x01, 0xe8, 0x48, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xc6, 0x00, 0x8e, 0x00, 0x16, 0x02, 0xb5, 0x00, 0x8e,
|
||||
0x00, 0x97, 0x04, 0x19, 0x03, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0x03, 0xff,
|
||||
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08,
|
||||
0x02, 0x80
|
||||
};
|
||||
|
@ -32,8 +32,6 @@ extern byte scp_320x200x8_vga[SCP_SIZE];
|
||||
|
||||
extern const byte scp_320x240x8_rgb[SCP_SIZE];
|
||||
extern byte scp_320x240x8_vga[SCP_SIZE];
|
||||
extern const byte scp_320x240x16_rgb[SCP_SIZE];
|
||||
extern const byte scp_320x240x16_vga[SCP_SIZE];
|
||||
|
||||
extern const byte scp_640x400x8_rgb[SCP_SIZE];
|
||||
extern const byte scp_640x400x8_rgb60[SCP_SIZE];
|
||||
@ -41,7 +39,5 @@ extern byte scp_640x400x8_vga[SCP_SIZE];
|
||||
|
||||
extern const byte scp_640x480x8_rgb[SCP_SIZE];
|
||||
extern byte scp_640x480x8_vga[SCP_SIZE];
|
||||
extern const byte scp_640x480x16_rgb[SCP_SIZE];
|
||||
extern const byte scp_640x480x16_vga[SCP_SIZE];
|
||||
|
||||
#endif
|
||||
|
@ -58,8 +58,8 @@ less hungry games even a CT2/DFB@50 MHz or the AfterBurner040 could be enough).
|
||||
- Custom (and optimal) drawing routines (especially for the cursor).
|
||||
|
||||
- Custom (Super)Videl resolutions for the best possible performance and visual
|
||||
experience (320x240 in RGB, chunky modes with SuperVidel, 640x480@16bpp for
|
||||
the overlay in RGB/SuperVidel, ...)
|
||||
experience (320x240 in RGB, chunky modes with SuperVidel, 640x480@8bpp for
|
||||
the overlay, ...)
|
||||
|
||||
- Custom (hardware based) aspect ratio correction (!)
|
||||
|
||||
@ -373,8 +373,6 @@ Future plans
|
||||
|
||||
- unified file paths in scummvm.ini
|
||||
|
||||
- 8bpp overlay (and get rid of all that 16bpp handling code)
|
||||
|
||||
- profiling :) (see also https://github.com/scummvm/scummvm/pull/2382)
|
||||
|
||||
- DSP-based sample mixer
|
||||
@ -412,7 +410,7 @@ Future plans
|
||||
|
||||
|
||||
Closing words
|
||||
—------------
|
||||
-------------
|
||||
|
||||
I have opened a pull request with all of my code
|
||||
(https://github.com/scummvm/scummvm/pull/4687) so who knows, maybe ScummVM
|
||||
|
Loading…
x
Reference in New Issue
Block a user