BACKENDS: ATARI: Refactor

This commit is contained in:
Miro Kropacek 2023-03-05 14:30:47 +01:00
parent 740cf0989c
commit 6c5e3dbfd5
14 changed files with 303 additions and 293 deletions

View File

@ -19,8 +19,6 @@
* *
*/ */
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
#include "backends/events/atari/atari-events.h" #include "backends/events/atari/atari-events.h"
#include <mint/osbind.h> #include <mint/osbind.h>
@ -122,7 +120,7 @@ bool AtariEventSource::pollEvent(Common::Event &event) {
if (curMillis - startMillis >= 1000) { if (curMillis - startMillis >= 1000) {
float avgFps = avgFpsSum / avgFpsCount; float avgFps = avgFpsSum / avgFpsCount;
debug("*** Average FPS in 1s: %f ***", avgFps); //debug("*** Average FPS in 1s: %f ***", avgFps);
startMillis = curMillis; startMillis = curMillis;
avgFpsSum = 0; avgFpsSum = 0;
avgFpsCount = 0; avgFpsCount = 0;

View File

@ -22,32 +22,20 @@
#ifndef BACKENDS_GRAPHICS_ATARI_SUPERBLITTER_H #ifndef BACKENDS_GRAPHICS_ATARI_SUPERBLITTER_H
#define BACKENDS_GRAPHICS_ATARI_SUPERBLITTER_H #define BACKENDS_GRAPHICS_ATARI_SUPERBLITTER_H
#include <mint/trap14.h> #include <mint/cookie.h>
#include <mint/falcon.h>
#define ct60_vm(mode, value) (long)trap_14_wwl((short)0xc60e, (short)(mode), (long)(value))
#define ct60_vmalloc(value) ct60_vm(0, value)
#define ct60_vmfree(value) ct60_vm(1, value)
// bits 26:0
#define SV_BLITTER_SRC1 ((volatile long*)0x80010058)
#define SV_BLITTER_SRC2 ((volatile long*)0x8001005C)
#define SV_BLITTER_DST ((volatile long*)0x80010060)
// The amount of bytes that are to be copied in a horizontal line, minus 1
#define SV_BLITTER_COUNT ((volatile long*)0x80010064)
// The amount of bytes that are to be added to the line start adress after a line has been copied, in order to reach the next one
#define SV_BLITTER_SRC1_OFFSET ((volatile long*)0x80010068)
#define SV_BLITTER_SRC2_OFFSET ((volatile long*)0x8001006C)
#define SV_BLITTER_DST_OFFSET ((volatile long*)0x80010070)
// bits 11:0 - The amount of horizontal lines to do
#define SV_BLITTER_MASK_AND_LINES ((volatile long*)0x80010074)
// bit 0 - busy / start
// bits 4:1 - blit mode
#define SV_BLITTER_CONTROL ((volatile long*)0x80010078)
// bits 9:0 // bits 9:0
#define SV_VERSION ((volatile long*)0x8001007C) #define SV_VERSION ((volatile long*)0x8001007C)
// bit 0 - empty (read only)
// bit 1 - full (read only) inline static bool hasSuperVidel() {
// bits 31:0 - data (write only) static bool hasSuperVidel = VgetMonitor() == MON_VGA && Getcookie(C_SupV, NULL) == C_FOUND;
#define SV_BLITTER_FIFO ((volatile long*)0x80010080) return hasSuperVidel;
}
static int superVidelFwVersion = hasSuperVidel() ? *SV_VERSION & 0x01ff : 0;
void lockSuperBlitter();
void unlockSuperBlitter();
#endif #endif

View File

@ -22,75 +22,42 @@
#ifndef BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H #ifndef BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H
#define BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H #define BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H
#define USE_SV_BLITTER // TODO: into configure?
#include "backends/graphics/atari/atari-graphics.h" #include "backends/graphics/atari/atari-graphics.h"
#include <cstring>
#include <mint/osbind.h> #include <mint/osbind.h>
#ifdef USE_SV_BLITTER
#include "backends/graphics/atari/atari-graphics-superblitter.h" #include "backends/graphics/atari/atari-graphics-superblitter.h"
#endif
#include "backends/graphics/atari/videl-resolutions.h" #include "backends/graphics/atari/videl-resolutions.h"
#include "common/debug.h" // error() & warning()
#include "common/scummsys.h" #include "common/scummsys.h"
#include "common/textconsole.h" // for error()
class AtariSuperVidelManager : public AtariGraphicsManager { class AtariSuperVidelManager : public AtariGraphicsManager {
public: public:
AtariSuperVidelManager() { AtariSuperVidelManager() {
#ifdef USE_SV_BLITTER #ifdef USE_SV_BLITTER
_fwVersion = *SV_VERSION & 0x01ff; debug("SuperVidel FW Revision: %d, using %s", superVidelFwVersion, superVidelFwVersion >= 9
debug("SuperVidel FW Revision: %d, using %s", _fwVersion, _fwVersion >= 9 ? "fast async FIFO" : "slower sync blitting");
? "fast async FIFO" : "slower sync blitting" ); #else
debug("SuperVidel FW Revision: %d, SuperBlitter not used", superVidelFwVersion);
#endif #endif
if (Supexec(hasSvRamBoosted))
for (int i = 0; i < SCREENS; ++i) { debug("SV_XBIOS has the pmmu boost enabled");
if (!allocateAtariSurface(_screen[i], _screenSurface, else
SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8, warning("SV_XBIOS has the pmmu boost disabled, set 'pmmu_boost = true' in C:\\SV.INF");
MX_STRAM, 0xA0000000))
error("Failed to allocate screen memory in ST RAM");
_screenAligned[i] = (byte*)_screenSurface.getPixels();
}
_screenSurface.setPixels(_screenAligned[getDefaultGraphicsMode() <= 1 ? FRONT_BUFFER : BACK_BUFFER1]);
if (!allocateAtariSurface(_chunkyBuffer, _chunkySurface,
SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8,
MX_PREFTTRAM))
error("Failed to allocate chunky buffer memory in ST/TT RAM");
if (!allocateAtariSurface(_overlayScreen, _screenOverlaySurface,
getOverlayWidth(), getOverlayHeight(), getOverlayFormat(),
MX_STRAM, 0xA0000000))
error("Failed to allocate overlay memory in ST RAM");
if (!allocateAtariSurface(_overlayBuffer, _overlaySurface,
getOverlayWidth(), getOverlayHeight(), getOverlayFormat(),
MX_PREFTTRAM))
error("Failed to allocate overlay buffer memory in ST/TT RAM");
// patch SPSHIFT for SuperVidel's BPS8C // patch SPSHIFT for SuperVidel's BPS8C
for (byte *p : {scp_320x200x8_vga, scp_320x240x8_vga, scp_640x400x8_vga, scp_640x480x8_vga}) { for (byte *p : {scp_320x200x8_vga, scp_320x240x8_vga, scp_640x400x8_vga, scp_640x480x8_vga}) {
uint16 *p16 = (uint16*)(p + 122 + 30); uint16 *p16 = (uint16*)(p + 122 + 30);
*p16 |= 0x1000; *p16 |= 0x1000;
} }
// using virtual methods so must be done here
allocateSurfaces();
} }
~AtariSuperVidelManager() { ~AtariSuperVidelManager() {
#ifdef USE_SV_BLITTER // using virtual methods so must be done here
ct60_vmfree(_chunkyBuffer); freeSurfaces();
#else
Mfree(_chunkyBuffer);
#endif
_chunkyBuffer = nullptr;
#ifdef USE_SV_BLITTER
ct60_vmfree(_overlayBuffer);
#else
Mfree(_overlayBuffer);
#endif
_overlayBuffer = nullptr;
} }
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override { virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override {
@ -107,95 +74,56 @@ public:
int16 getOverlayHeight() const override { return 2 * OVERLAY_HEIGHT; } int16 getOverlayHeight() const override { return 2 * OVERLAY_HEIGHT; }
int16 getOverlayWidth() const override { return 2 * OVERLAY_WIDTH; } int16 getOverlayWidth() const override { return 2 * OVERLAY_WIDTH; }
protected:
AtariMemAlloc getStRamAllocFunc() const override {
return [](size_t bytes) {
uintptr ptr = Mxalloc(bytes, MX_STRAM);
if (ptr != 0)
ptr |= 0xA0000000;
return (void*)ptr;
};
}
AtariMemFree getStRamFreeFunc() const override {
return [](void *ptr) { Mfree((uintptr)ptr & 0x00FFFFFF); };
}
private: private:
virtual void* allocFast(size_t bytes) const override { void copyRectToSurface(Graphics::Surface &dstSurface,
#ifdef USE_SV_BLITTER const Graphics::Surface &srcSurface, int destX, int destY,
return (void*)ct60_vmalloc(bytes);
#else
return (void*)Mxalloc(bytes, MX_PREFTTRAM);
#endif
}
void copySurfaceToSurface(const Graphics::Surface &srcSurface, Graphics::Surface &dstSurface) const override {
#ifdef USE_SV_BLITTER
if (_fwVersion >= 9) {
*SV_BLITTER_FIFO = (long)srcSurface.getPixels(); // SV_BLITTER_SRC1
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2
*SV_BLITTER_FIFO = (long)dstSurface.getPixels(); // SV_BLITTER_DST
*SV_BLITTER_FIFO = srcSurface.w - 1; // SV_BLITTER_COUNT
*SV_BLITTER_FIFO = srcSurface.pitch; // SV_BLITTER_SRC1_OFFSET
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2_OFFSET
*SV_BLITTER_FIFO = dstSurface.pitch; // SV_BLITTER_DST_OFFSET
*SV_BLITTER_FIFO = srcSurface.h; // SV_BLITTER_MASK_AND_LINES
*SV_BLITTER_FIFO = 0x01; // SV_BLITTER_CONTROL
} else {
sync();
*SV_BLITTER_SRC1 = (long)srcSurface.getPixels();
*SV_BLITTER_SRC2 = 0x00000000;
*SV_BLITTER_DST = (long)dstSurface.getPixels();
*SV_BLITTER_COUNT = srcSurface.w - 1;
*SV_BLITTER_SRC1_OFFSET = srcSurface.pitch;
*SV_BLITTER_SRC2_OFFSET = 0x00000000;
*SV_BLITTER_DST_OFFSET = dstSurface.pitch;
*SV_BLITTER_MASK_AND_LINES = srcSurface.h;
*SV_BLITTER_CONTROL = 0x01;
}
#else
memcpy(dstSurface.getPixels(), srcSurface.getPixels(), srcSurface.h * srcSurface.pitch);
#endif
}
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, Graphics::Surface &dstSurface,
const Common::Rect &subRect) const override { const Common::Rect &subRect) const override {
#ifdef USE_SV_BLITTER
if (_fwVersion >= 9) {
*SV_BLITTER_FIFO = (long)srcSurface.getBasePtr(subRect.left, subRect.top); // SV_BLITTER_SRC1
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2
*SV_BLITTER_FIFO = (long)dstSurface.getBasePtr(destX, destY); // SV_BLITTER_DST
*SV_BLITTER_FIFO = subRect.width() - 1; // SV_BLITTER_COUNT
*SV_BLITTER_FIFO = srcSurface.pitch; // SV_BLITTER_SRC1_OFFSET
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2_OFFSET
*SV_BLITTER_FIFO = dstSurface.pitch; // SV_BLITTER_DST_OFFSET
*SV_BLITTER_FIFO = subRect.height(); // SV_BLITTER_MASK_AND_LINES
*SV_BLITTER_FIFO = 0x01; // SV_BLITTER_CONTROL
} else {
sync();
*SV_BLITTER_SRC1 = (long)srcSurface.getBasePtr(subRect.left, subRect.top);
*SV_BLITTER_SRC2 = 0x00000000;
*SV_BLITTER_DST = (long)dstSurface.getBasePtr(destX, destY);
*SV_BLITTER_COUNT = subRect.width() - 1;
*SV_BLITTER_SRC1_OFFSET = srcSurface.pitch;
*SV_BLITTER_SRC2_OFFSET = 0x00000000;
*SV_BLITTER_DST_OFFSET = dstSurface.pitch;
*SV_BLITTER_MASK_AND_LINES = subRect.height();
*SV_BLITTER_CONTROL = 0x01;
}
#else
dstSurface.copyRectToSurface(srcSurface, destX, destY, subRect); dstSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
#endif
} }
void copyRectToSurfaceWithKey(const Graphics::Surface &srcSurface, int destX, int destY, Graphics::Surface &dstSurface, void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface,
const Graphics::Surface &srcSurface, int destX, int destY,
const Common::Rect &subRect, uint32 key) const override { const Common::Rect &subRect, uint32 key) const override {
sync();
dstSurface.copyRectToSurfaceWithKey(srcSurface, destX, destY, subRect, key); dstSurface.copyRectToSurfaceWithKey(srcSurface, destX, destY, subRect, key);
} }
virtual void sync() const override { static long hasSvRamBoosted() {
#ifdef USE_SV_BLITTER register long ret __asm__ ("d0") = 0;
// while FIFO not empty...
if (_fwVersion >= 9)
while (!(*SV_BLITTER_FIFO & 1));
// while busy blitting...
while (*SV_BLITTER_CONTROL & 1);
#endif
}
#ifdef USE_SV_BLITTER __asm__ volatile(
int _fwVersion = 0; "\tmovec %%itt0,%%d1\n"
#endif "\tcmp.l #0xA007E060,%%d1\n"
"\tbne.s 1f\n"
"\tmovec %%dtt0,%%d1\n"
"\tcmp.l #0xA007E060,%%d1\n"
"\tbne.s 1f\n"
"\tmoveq #1,%%d0\n"
"1:\n"
: "=g"(ret) /* outputs */
: /* inputs */
: __CLOBBER_RETURN("d0") "d1", "cc"
);
return ret;
}
}; };
#endif #endif

View File

@ -24,40 +24,19 @@
#include "backends/graphics/atari/atari-graphics.h" #include "backends/graphics/atari/atari-graphics.h"
#include <mint/osbind.h>
#include "backends/graphics/atari/atari_c2p-asm.h" #include "backends/graphics/atari/atari_c2p-asm.h"
#include "common/system.h" #include "common/system.h"
#include "common/textconsole.h" // for error()
class AtariVidelManager : public AtariGraphicsManager { class AtariVidelManager : public AtariGraphicsManager {
public: public:
AtariVidelManager() { AtariVidelManager() {
for (int i = 0; i < SCREENS; ++i) { // using virtual methods so must be done here
if (!allocateAtariSurface(_screen[i], _screenSurface, SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8, MX_STRAM)) allocateSurfaces();
error("Failed to allocate screen memory in ST RAM");
_screenAligned[i] = (byte*)_screenSurface.getPixels();
}
_screenSurface.setPixels(_screenAligned[getDefaultGraphicsMode() <= 1 ? FRONT_BUFFER : BACK_BUFFER1]);
if (!allocateAtariSurface(_chunkyBuffer, _chunkySurface, SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8, MX_PREFTTRAM))
error("Failed to allocate chunky buffer memory in ST/TT RAM");
if (!allocateAtariSurface(_overlayScreen, _screenOverlaySurface, getOverlayWidth(), getOverlayHeight(),
getOverlayFormat(), MX_STRAM))
error("Failed to allocate overlay memory in ST RAM");
if (!allocateAtariSurface(_overlayBuffer, _overlaySurface, getOverlayWidth(), getOverlayHeight(),
getOverlayFormat(), MX_PREFTTRAM))
error("Failed to allocate overlay buffer memory in ST/TT RAM");
} }
~AtariVidelManager() { ~AtariVidelManager() {
Mfree(_chunkyBuffer); // using virtual methods so must be done here
_chunkyBuffer = nullptr; freeSurfaces();
Mfree(_overlayBuffer);
_overlayBuffer = nullptr;
} }
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override { virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override {
@ -89,35 +68,35 @@ public:
int16 getOverlayWidth() const override { return _vgaMonitor ? OVERLAY_WIDTH : 2 * OVERLAY_WIDTH; } int16 getOverlayWidth() const override { return _vgaMonitor ? OVERLAY_WIDTH : 2 * OVERLAY_WIDTH; }
private: private:
virtual void* allocFast(size_t bytes) const override { void copyRectToSurface(Graphics::Surface &dstSurface,
return (void*)Mxalloc(bytes, MX_PREFTTRAM); const Graphics::Surface &srcSurface, int destX, int destY,
} const Common::Rect &subRect) const override {
void copySurfaceToSurface(const Graphics::Surface &srcSurface, Graphics::Surface &dstSurface) const override {
asm_c2p1x1_8(
(const byte*)srcSurface.getPixels(),
(const byte*)srcSurface.getBasePtr(srcSurface.w, srcSurface.h-1),
(byte*)dstSurface.getPixels());
}
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect) const override {
// 'pChunkyEnd' is a delicate parameter: the c2p routine compares it to the address register // 'pChunkyEnd' is a delicate parameter: the c2p routine compares it to the address register
// used for pixel reading; two common mistakes: // used for pixel reading; two common mistakes:
// 1. (subRect.left, subRect.bottom) = beginning of the next line *including the offset* // 1. (subRect.left, subRect.bottom) = beginning of the next line *including the offset*
// 2. (subRect.right, subRect.bottom) = even worse, end of the *next* line, not current one // 2. (subRect.right, subRect.bottom) = even worse, end of the *next* line, not current one
asm_c2p1x1_8_rect( if (subRect.width() == dstSurface.w) {
(const byte*)srcSurface.getBasePtr(subRect.left, subRect.top), asm_c2p1x1_8(
(const byte*)srcSurface.getBasePtr(subRect.right, subRect.bottom-1), (const byte*)srcSurface.getBasePtr(subRect.left, subRect.top),
subRect.width(), (const byte*)srcSurface.getBasePtr(subRect.right, subRect.bottom-1),
srcSurface.pitch, (byte*)dstSurface.getBasePtr(destX, destY));
(byte*)dstSurface.getBasePtr(destX, destY), } else {
dstSurface.pitch); asm_c2p1x1_8_rect(
(const byte*)srcSurface.getBasePtr(subRect.left, subRect.top),
(const byte*)srcSurface.getBasePtr(subRect.right, subRect.bottom-1),
subRect.width(),
srcSurface.pitch,
(byte*)dstSurface.getBasePtr(destX, destY),
dstSurface.pitch);
}
} }
// TODO: allow specifying different background than _chunkySurface? // TODO: allow specifying different background than _chunkySurface?
void copyRectToSurfaceWithKey(const Graphics::Surface &srcSurface, int destX, int destY, // TODO: alignRect and this function could be perhaps better if we know that all surfaces
Graphics::Surface &dstSurface, const Common::Rect &subRect, uint32 key) const override { // are aligned on 16px and their pitch is % 16 as well?
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface,
const Graphics::Surface &srcSurface, int destX, int destY,
const Common::Rect &subRect, uint32 key) const override {
Common::Rect backgroundRect(destX, destY, destX + subRect.width(), destY + subRect.height()); 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 // ensure that background's left and right lie on a 16px boundary and double the width if needed
@ -144,9 +123,9 @@ private:
cachedSurface.copyRectToSurfaceWithKey(srcSurface, deltaX, 0, subRect, key); cachedSurface.copyRectToSurfaceWithKey(srcSurface, deltaX, 0, subRect, key);
copyRectToSurface( copyRectToSurface(
dstSurface,
cachedSurface, cachedSurface,
backgroundRect.left, backgroundRect.top, backgroundRect.left, backgroundRect.top,
dstSurface,
Common::Rect(cachedSurface.w, cachedSurface.h)); Common::Rect(cachedSurface.w, cachedSurface.h));
} }

View File

@ -26,6 +26,7 @@
#include <mint/osbind.h> #include <mint/osbind.h>
#include "backends/graphics/atari/atari-graphics-asm.h" #include "backends/graphics/atari/atari-graphics-asm.h"
#include "backends/graphics/atari/atari-graphics-superblitter.h"
#include "backends/graphics/atari/videl-resolutions.h" #include "backends/graphics/atari/videl-resolutions.h"
#include "backends/keymapper/action.h" #include "backends/keymapper/action.h"
#include "backends/keymapper/keymap.h" #include "backends/keymapper/keymap.h"
@ -67,14 +68,6 @@ AtariGraphicsManager::AtariGraphicsManager() {
AtariGraphicsManager::~AtariGraphicsManager() { AtariGraphicsManager::~AtariGraphicsManager() {
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
for (int i = 0; i < SCREENS; ++i) {
Mfree(_screen[i]);
_screen[i] = _screenAligned[i] = nullptr;
}
Mfree(_overlayScreen);
_overlayScreen = nullptr;
} }
bool AtariGraphicsManager::hasFeature(OSystem::Feature f) const { bool AtariGraphicsManager::hasFeature(OSystem::Feature f) const {
@ -293,6 +286,8 @@ void AtariGraphicsManager::updateScreen() {
bool screenUpdated = false; bool screenUpdated = false;
lockSuperBlitter();
if (isOverlayVisible()) { if (isOverlayVisible()) {
screenUpdated = updateOverlay(); screenUpdated = updateOverlay();
} else { } else {
@ -310,14 +305,14 @@ void AtariGraphicsManager::updateScreen() {
} }
} }
unlockSuperBlitter();
//if (_cursor.outOfScreen) //if (_cursor.outOfScreen)
// warning("mouse out of screen"); // warning("mouse out of screen");
bool vsync = _vsync; bool vsync = _vsync;
if (_screenModified) { if (_screenModified) {
sync();
if (_currentState.mode == GraphicsMode::DoubleBuffering) { if (_currentState.mode == GraphicsMode::DoubleBuffering) {
byte *tmp = _screenAligned[FRONT_BUFFER]; byte *tmp = _screenAligned[FRONT_BUFFER];
_screenAligned[FRONT_BUFFER] = _screenAligned[BACK_BUFFER1]; _screenAligned[FRONT_BUFFER] = _screenAligned[BACK_BUFFER1];
@ -532,6 +527,9 @@ void AtariGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int h
bool dontScale, const Graphics::PixelFormat *format, const byte *mask) { bool dontScale, const Graphics::PixelFormat *format, const byte *mask) {
//debug("setMouseCursor: %d, %d, %d, %d, %d, %d", w, h, hotspotX, hotspotY, keycolor, format ? format->bytesPerPixel : 1); //debug("setMouseCursor: %d, %d, %d, %d, %d, %d", w, h, hotspotX, hotspotY, keycolor, format ? format->bytesPerPixel : 1);
if (mask)
warning("AtariGraphicsManager::setMouseCursor: Masks are not supported");
const Graphics::PixelFormat cursorFormat = format ? *format : PIXELFORMAT8; const Graphics::PixelFormat cursorFormat = format ? *format : PIXELFORMAT8;
_cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor, cursorFormat); _cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor, cursorFormat);
} }
@ -575,21 +573,38 @@ Common::Keymap *AtariGraphicsManager::getKeymap() const {
return keymap; return keymap;
} }
bool AtariGraphicsManager::allocateAtariSurface( void AtariGraphicsManager::allocateSurfaces() {
byte *&buf, Graphics::Surface &surface, int width, int height, for (int i = 0; i < SCREENS; ++i) {
const Graphics::PixelFormat &format, int mode, uintptr mask) { if (!(_screen[i] = allocateAtariSurface(_screenSurface,
buf = (mode == MX_STRAM) SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8,
? (byte*)Mxalloc(width * height * format.bytesPerPixel + 15, mode) getStRamAllocFunc())))
: (byte*)allocFast(width * height * format.bytesPerPixel + 15); error("Failed to allocate screen memory in ST RAM");
_screenAligned[i] = (byte*)_screenSurface.getPixels();
}
_screenSurface.setPixels(_screenAligned[getDefaultGraphicsMode() <= 1 ? FRONT_BUFFER : BACK_BUFFER1]);
if (!buf) _chunkySurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8);
return false;
byte *bufAligned = (byte*)((((uintptr)buf + 15) | mask) & 0xfffffff0); if (!(_overlayScreen = allocateAtariSurface(_screenOverlaySurface,
memset(bufAligned, 0, width * height * format.bytesPerPixel); getOverlayWidth(), getOverlayHeight(), getOverlayFormat(),
getStRamAllocFunc())))
error("Failed to allocate overlay memory in ST RAM");
surface.init(width, height, width * format.bytesPerPixel, bufAligned, format); _overlaySurface.create(getOverlayWidth(), getOverlayHeight(), getOverlayFormat());
return true; }
void AtariGraphicsManager::freeSurfaces() {
for (int i = 0; i < SCREENS; ++i) {
freeAtariSurface(_screen[i], _screenSurface, getStRamFreeFunc());
_screen[i] = _screenAligned[i] = nullptr;
}
_chunkySurface.free();
freeAtariSurface(_overlayScreen, _screenOverlaySurface, getStRamFreeFunc());
_overlayScreen = nullptr;
_overlaySurface.free();
} }
void AtariGraphicsManager::setVidelResolution() const { void AtariGraphicsManager::setVidelResolution() const {
@ -755,10 +770,7 @@ bool AtariGraphicsManager::updateSingleBuffer() {
if (!drawCursor && !_cursor.outOfScreen && _cursor.visible) if (!drawCursor && !_cursor.outOfScreen && _cursor.visible)
drawCursor = rect.intersects(_cursor.dstRect); drawCursor = rect.intersects(_cursor.dstRect);
if (rect.width() == _screenSurface.w && rect.height() == _screenSurface.h) copyRectToSurface(_screenSurface, _chunkySurface, rect.left, rect.top, rect);
copySurfaceToSurface(_chunkySurface, _screenSurface);
else
copyRectToSurface(_chunkySurface, rect.left, rect.top, _screenSurface, rect);
_modifiedChunkyRects.pop_back(); _modifiedChunkyRects.pop_back();
@ -770,8 +782,10 @@ bool AtariGraphicsManager::updateSingleBuffer() {
if ((_cursor.positionChanged || !_cursor.visible) && !_oldCursorRect.isEmpty()) { if ((_cursor.positionChanged || !_cursor.visible) && !_oldCursorRect.isEmpty()) {
alignRect(_chunkySurface, _oldCursorRect); alignRect(_chunkySurface, _oldCursorRect);
copyRectToSurface(_chunkySurface, _oldCursorRect.left, _oldCursorRect.top, copyRectToSurface(
_screenSurface, _oldCursorRect); _screenSurface, _chunkySurface,
_oldCursorRect.left, _oldCursorRect.top,
_oldCursorRect);
_oldCursorRect = Common::Rect(); _oldCursorRect = Common::Rect();
@ -780,8 +794,10 @@ bool AtariGraphicsManager::updateSingleBuffer() {
if (drawCursor && _cursor.visible) { if (drawCursor && _cursor.visible) {
//debug("Redraw cursor (single): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height()); //debug("Redraw cursor (single): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
copyRectToSurfaceWithKey(_cursor.surface, _cursor.dstRect.left, _cursor.dstRect.top, copyRectToSurfaceWithKey(
_screenSurface, _cursor.srcRect, _cursor.keycolor); _screenSurface, _cursor.surface,
_cursor.dstRect.left, _cursor.dstRect.top,
_cursor.srcRect, _cursor.keycolor);
_cursor.positionChanged = _cursor.surfaceChanged = false; _cursor.positionChanged = _cursor.surfaceChanged = false;
_oldCursorRect = _cursor.dstRect; _oldCursorRect = _cursor.dstRect;
@ -799,7 +815,10 @@ bool AtariGraphicsManager::updateDoubleAndTripleBuffer() {
if (_screenModified) { if (_screenModified) {
drawCursor = true; drawCursor = true;
copySurfaceToSurface(_chunkySurface, _screenSurface); copyRectToSurface(
_screenSurface, _chunkySurface,
0, 0,
Common::Rect(_chunkySurface.w, _chunkySurface.h));
// updated in screen swapping // updated in screen swapping
//_screenModified = false; //_screenModified = false;
@ -816,8 +835,10 @@ bool AtariGraphicsManager::updateDoubleAndTripleBuffer() {
if ((_cursor.positionChanged || !_cursor.visible) && !_oldCursorRect.isEmpty() && !_screenModified) { if ((_cursor.positionChanged || !_cursor.visible) && !_oldCursorRect.isEmpty() && !_screenModified) {
alignRect(_chunkySurface, _oldCursorRect); alignRect(_chunkySurface, _oldCursorRect);
copyRectToSurface(_chunkySurface, _oldCursorRect.left, _oldCursorRect.top, copyRectToSurface(
frontBufferScreenSurface, _oldCursorRect); frontBufferScreenSurface, _chunkySurface,
_oldCursorRect.left, _oldCursorRect.top,
_oldCursorRect);
_oldCursorRect = Common::Rect(); _oldCursorRect = Common::Rect();
@ -827,8 +848,10 @@ bool AtariGraphicsManager::updateDoubleAndTripleBuffer() {
if (drawCursor && _cursor.visible) { if (drawCursor && _cursor.visible) {
//debug("Redraw cursor (double/triple): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height()); //debug("Redraw cursor (double/triple): %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
copyRectToSurfaceWithKey(_cursor.surface, _cursor.dstRect.left, _cursor.dstRect.top, copyRectToSurfaceWithKey(
frontBufferScreenSurface, _cursor.srcRect, _cursor.keycolor); frontBufferScreenSurface, _cursor.surface,
_cursor.dstRect.left, _cursor.dstRect.top,
_cursor.srcRect, _cursor.keycolor);
_cursor.positionChanged = _cursor.surfaceChanged = false; _cursor.positionChanged = _cursor.surfaceChanged = false;
_oldCursorRect = _cursor.dstRect; _oldCursorRect = _cursor.dstRect;
@ -839,6 +862,26 @@ bool AtariGraphicsManager::updateDoubleAndTripleBuffer() {
return updated; return updated;
} }
byte *AtariGraphicsManager::allocateAtariSurface(Graphics::Surface &surface,
int width, int height, const Graphics::PixelFormat &format,
const AtariMemAlloc &allocFunc) {
byte *buf = (byte*)allocFunc(width * height * format.bytesPerPixel + 15);
if (!buf)
return buf;
byte *bufAligned = (byte*)(((uintptr)buf + 15) & 0xfffffff0);
memset(bufAligned, 0, width * height * format.bytesPerPixel);
surface.init(width, height, width * format.bytesPerPixel, bufAligned, format);
return buf;
}
void AtariGraphicsManager::freeAtariSurface(byte *ptr, Graphics::Surface &surface,
const AtariMemFree &freeFunc) {
surface = Graphics::Surface();
freeFunc(ptr);
}
void AtariGraphicsManager::copySurface8ToSurface16( void AtariGraphicsManager::copySurface8ToSurface16(
const Graphics::Surface &srcSurface, const byte *srcPalette, const Graphics::Surface &srcSurface, const byte *srcPalette,
Graphics::Surface &dstSurface, int destX, int destY, Graphics::Surface &dstSurface, int destX, int destY,

View File

@ -24,6 +24,8 @@
#include "backends/graphics/graphics.h" #include "backends/graphics/graphics.h"
#include <mint/osbind.h>
#include "common/array.h" #include "common/array.h"
#include "common/events.h" #include "common/events.h"
#include "common/rect.h" #include "common/rect.h"
@ -92,11 +94,20 @@ public:
protected: protected:
const Graphics::PixelFormat PIXELFORMAT8 = Graphics::PixelFormat::createFormatCLUT8(); const Graphics::PixelFormat PIXELFORMAT8 = Graphics::PixelFormat::createFormatCLUT8();
const Graphics::PixelFormat PIXELFORMAT16 = getOverlayFormat();
bool allocateAtariSurface(byte *&buf, Graphics::Surface &surface, typedef void* (*AtariMemAlloc)(size_t bytes);
int width, int height, const Graphics::PixelFormat &format, typedef void (*AtariMemFree)(void *ptr);
int mode, uintptr mask = 0x00000000);
virtual AtariMemAlloc getStRamAllocFunc() const {
return [](size_t bytes) { return (void*)Mxalloc(bytes, MX_STRAM); };
}
virtual AtariMemFree getStRamFreeFunc() const {
return [](void *ptr) { Mfree(ptr); };
}
void allocateSurfaces();
void freeSurfaces();
bool _vgaMonitor = true; bool _vgaMonitor = true;
@ -129,18 +140,8 @@ protected:
static const int FRONT_BUFFER = 0; static const int FRONT_BUFFER = 0;
static const int BACK_BUFFER1 = 1; static const int BACK_BUFFER1 = 1;
static const int BACK_BUFFER2 = 2; static const int BACK_BUFFER2 = 2;
byte *_screen[SCREENS] = {}; // for Mfree() purposes only
byte *_screenAligned[SCREENS] = {};
Graphics::Surface _screenSurface;
byte *_chunkyBuffer = nullptr; // for Mfree() purposes only Graphics::Surface _chunkySurface; // for Videl's copyRectToSurfaceWithKey
Graphics::Surface _chunkySurface;
byte *_overlayScreen = nullptr; // for Mfree() purposes only
Graphics::Surface _screenOverlaySurface;
byte *_overlayBuffer = nullptr; // for Mfree() purposes only
Graphics::Surface _overlaySurface;
private: private:
enum CustomEventAction { enum CustomEventAction {
@ -155,15 +156,19 @@ private:
bool updateSingleBuffer(); bool updateSingleBuffer();
bool updateDoubleAndTripleBuffer(); bool updateDoubleAndTripleBuffer();
virtual void* allocFast(size_t bytes) const = 0; byte *allocateAtariSurface(Graphics::Surface &surface,
int width, int height, const Graphics::PixelFormat &format,
const AtariMemAlloc &allocFunc);
virtual void copySurfaceToSurface(const Graphics::Surface &srcSurface, Graphics::Surface &dstSurface) const = 0; void freeAtariSurface(byte *ptr, Graphics::Surface &surface, const AtariMemFree &freeFunc);
virtual void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect) const = 0; virtual void copyRectToSurface(Graphics::Surface &dstSurface,
virtual void copyRectToSurfaceWithKey(const Graphics::Surface &srcSurface, int destX, int destY, const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect, uint32 key) const = 0; const Common::Rect &subRect) const = 0;
virtual void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface,
const Graphics::Surface &srcSurface, int destX, int destY,
const Common::Rect &subRect, uint32 key) const = 0;
virtual void alignRect(const Graphics::Surface &srcSurface, Common::Rect &rect) const {} virtual void alignRect(const Graphics::Surface &srcSurface, Common::Rect &rect) const {}
virtual void sync() const {}
enum class ScaleMode { enum class ScaleMode {
NONE, NONE,
@ -195,12 +200,19 @@ private:
}; };
int _pendingScreenChange = kPendingScreenChangeNone; int _pendingScreenChange = kPendingScreenChangeNone;
bool _screenModified = false; // double/triple buffering only byte *_screen[SCREENS] = {}; // for Mfree() purposes only
byte *_screenAligned[SCREENS] = {};
Graphics::Surface _screenSurface;
Common::Rect _modifiedScreenRect; // direct rendering only Common::Rect _modifiedScreenRect; // direct rendering only
bool _screenModified = false; // double/triple buffering only
Common::Array<Common::Rect> _modifiedChunkyRects; Common::Array<Common::Rect> _modifiedChunkyRects;
byte *_overlayScreen = nullptr; // for Mfree() purposes only
Graphics::Surface _screenOverlaySurface;
bool _overlayVisible = false; bool _overlayVisible = false;
Graphics::Surface _overlaySurface;
Common::Array<Common::Rect> _modifiedOverlayRects; Common::Array<Common::Rect> _modifiedOverlayRects;
struct Cursor { struct Cursor {

View File

@ -20,15 +20,12 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <mint/cookie.h> #include <mint/cookie.h>
#include <mint/falcon.h>
#include <mint/osbind.h> #include <mint/osbind.h>
// We use some stdio.h functionality here thus we need to allow some
// symbols. Alternatively, we could simply allow everything by defining
// FORBIDDEN_SYMBOL_ALLOW_ALL
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE #define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#define FORBIDDEN_SYMBOL_EXCEPTION_stdout #define FORBIDDEN_SYMBOL_EXCEPTION_stdout
#define FORBIDDEN_SYMBOL_EXCEPTION_stderr #define FORBIDDEN_SYMBOL_EXCEPTION_stderr
@ -51,6 +48,7 @@
#include "backends/events/default/default-events.h" #include "backends/events/default/default-events.h"
#include "backends/mixer/atari/atari-mixer.h" #include "backends/mixer/atari/atari-mixer.h"
#include "backends/graphics/atari/atari-graphics.h" #include "backends/graphics/atari/atari-graphics.h"
#include "backends/graphics/atari/atari-graphics-superblitter.h"
#include "backends/graphics/atari/atari-graphics-supervidel.h" #include "backends/graphics/atari/atari-graphics-supervidel.h"
#include "backends/graphics/atari/atari-graphics-videl.h" #include "backends/graphics/atari/atari-graphics-videl.h"
#include "gui/debugger.h" #include "gui/debugger.h"
@ -115,8 +113,6 @@ void OSystem_Atari::initBackend() {
_startTime = clock(); _startTime = clock();
bool superVidel = VgetMonitor() == MON_VGA && Getcookie(C_SupV, NULL) == C_FOUND;
_timerManager = new DefaultTimerManager(); _timerManager = new DefaultTimerManager();
_savefileManager = new DefaultSaveFileManager("saves"); _savefileManager = new DefaultSaveFileManager("saves");
@ -125,7 +121,7 @@ void OSystem_Atari::initBackend() {
// AtariGraphicsManager needs _eventManager ready // AtariGraphicsManager needs _eventManager ready
AtariGraphicsManager *atariGraphicsManager; AtariGraphicsManager *atariGraphicsManager;
if (superVidel) if (hasSuperVidel())
atariGraphicsManager = new AtariSuperVidelManager(); atariGraphicsManager = new AtariSuperVidelManager();
else else
atariGraphicsManager = new AtariVidelManager(); atariGraphicsManager = new AtariVidelManager();

View File

@ -24,8 +24,6 @@
#include "backends/modular-backend.h" #include "backends/modular-backend.h"
#include <time.h>
class OSystem_Atari : public ModularMixerBackend, public ModularGraphicsBackend { class OSystem_Atari : public ModularMixerBackend, public ModularGraphicsBackend {
public: public:
OSystem_Atari(); OSystem_Atari();
@ -51,7 +49,7 @@ public:
void update(); void update();
private: private:
clock_t _startTime; long _startTime;
bool _video_initialized = false; bool _video_initialized = false;
bool _ikbd_initialized = false; bool _ikbd_initialized = false;

View File

@ -254,9 +254,7 @@ means that if the SuperVidel is detected, it does the following:
- when SuperVidel FW version >= 9 is detected, the async FIFO buffer is used - when SuperVidel FW version >= 9 is detected, the async FIFO buffer is used
instead of the slower sync blitting (where one has to wait for every instead of the slower sync blitting (where one has to wait for every
rectangle blit to finish). This applies only for chunky buffer -> screen rectangle blit to finish), this sometimes leads to nearly zero-cost rendering
surfaces copy (as the generic surface copy can't rely on this behavior) but
despite this limitation it sometimes leads to nearly zero-cost rendering
and makes a *huge* difference for 640x480 fullscreen updates. and makes a *huge* difference for 640x480 fullscreen updates.
@ -269,7 +267,7 @@ to avoid unpleasant playing experiences.
Game engines with unexpected performance hit Game engines with unexpected performance hit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A typical example from this category is the Gobliins engine (and its A typical example from this category is the Gobliiins engine (and its
sequels). At first it looks like our machine / backend is doing something sequels). At first it looks like our machine / backend is doing something
terribly wrong but the truth is it is the engine itself which is doing a lot of terribly wrong but the truth is it is the engine itself which is doing a lot of
unnecessary redraws and updates, sometimes even before reaching the backend. unnecessary redraws and updates, sometimes even before reaching the backend.
@ -383,8 +381,7 @@ Future plans
- avoid loading music/speech files (and thus slowing down everything) if muted - avoid loading music/speech files (and thus slowing down everything) if muted
- assembly copy routines for screen/chunky surfaces (even with SuperVidel - assembly copy routines when SuperVidel is not present or can't be used
present it is not possible to use the SuperBlitter for every surface)
- cached audio/video streams (i.e. don't load only "output_samples" number of - cached audio/video streams (i.e. don't load only "output_samples" number of
samples but cache, say, 1 second so disk i/o wont be so stressed) samples but cache, say, 1 second so disk i/o wont be so stressed)
@ -408,6 +405,12 @@ Future plans
- OPL2LPT and Retrowave support (if I manage to purchase it somewhere) - OPL2LPT and Retrowave support (if I manage to purchase it somewhere)
- engines based on Graphics::Screen don't have to use my chunky buffer (however
it may be tricky to detect this situation)
- C2P could support 4- and 6-bit depth
Closing words Closing words
—------------ —------------

1
configure vendored
View File

@ -3967,6 +3967,7 @@ case $_backend in
;; ;;
atari) atari)
define_in_config_if_yes yes "ATARI" define_in_config_if_yes yes "ATARI"
define_in_config_if_yes yes "USE_SV_BLITTER"
append_var DEFINES "-DDISABLE_LAUNCHERDISPLAY_GRID" append_var DEFINES "-DDISABLE_LAUNCHERDISPLAY_GRID"
#append_var DEFINES "-DDISABLE_FANCY_THEMES" #append_var DEFINES "-DDISABLE_FANCY_THEMES"
#append_var DEFINES "-DDISABLE_SID" #append_var DEFINES "-DDISABLE_SID"

View File

@ -27,15 +27,68 @@
#include <mint/cookie.h> #include <mint/cookie.h>
#include <mint/falcon.h> #include <mint/falcon.h>
#include <mint/trap14.h>
#define ct60_vm(mode, value) (long)trap_14_wwl((short)0xc60e, (short)(mode), (long)(value))
#define ct60_vmalloc(value) ct60_vm(0, value)
#define ct60_vmfree(value) ct60_vm(1, value)
#include "backends/graphics/atari/atari-graphics-superblitter.h" #include "backends/graphics/atari/atari-graphics-superblitter.h"
#include "common/textconsole.h" // error #include "common/textconsole.h" // error
// bits 26:0
#define SV_BLITTER_SRC1 ((volatile long*)0x80010058)
#define SV_BLITTER_SRC2 ((volatile long*)0x8001005C)
#define SV_BLITTER_DST ((volatile long*)0x80010060)
// The amount of bytes that are to be copied in a horizontal line, minus 1
#define SV_BLITTER_COUNT ((volatile long*)0x80010064)
// The amount of bytes that are to be added to the line start adress after a line has been copied, in order to reach the next one
#define SV_BLITTER_SRC1_OFFSET ((volatile long*)0x80010068)
#define SV_BLITTER_SRC2_OFFSET ((volatile long*)0x8001006C)
#define SV_BLITTER_DST_OFFSET ((volatile long*)0x80010070)
// bits 11:0 - The amount of horizontal lines to do
#define SV_BLITTER_MASK_AND_LINES ((volatile long*)0x80010074)
// bit 0 - busy / start
// bits 4:1 - blit mode
#define SV_BLITTER_CONTROL ((volatile long*)0x80010078)
// bit 0 - empty (read only)
// bit 1 - full (read only)
// bits 31:0 - data (write only)
#define SV_BLITTER_FIFO ((volatile long*)0x80010080)
static bool isSuperBlitterLocked;
static void syncSuperBlitter() {
// if externally locked, let the owner decide when to sync (unlock)
if (isSuperBlitterLocked)
return;
// while FIFO not empty...
if (superVidelFwVersion >= 9)
while (!(*SV_BLITTER_FIFO & 1));
// while busy blitting...
while (*SV_BLITTER_CONTROL & 1);
}
static inline bool hasMove16() { static inline bool hasMove16() {
long val; long val;
static bool hasMove16 = Getcookie(C__CPU, &val) == C_FOUND && val >= 40; static bool hasMove16 = Getcookie(C__CPU, &val) == C_FOUND && val >= 40;
return hasMove16; return hasMove16;
} }
void lockSuperBlitter() {
assert(!isSuperBlitterLocked);
isSuperBlitterLocked = true;
}
void unlockSuperBlitter() {
assert(isSuperBlitterLocked);
isSuperBlitterLocked = false;
if (hasSuperVidel())
syncSuperBlitter();
}
namespace Graphics { namespace Graphics {
constexpr size_t ALIGN = 16; // 16 bytes constexpr size_t ALIGN = 16; // 16 bytes
@ -53,7 +106,7 @@ void Surface::create(int16 width, int16 height, const PixelFormat &f) {
pitch = (w * format.bytesPerPixel + ALIGN - 1) & (-ALIGN); pitch = (w * format.bytesPerPixel + ALIGN - 1) & (-ALIGN);
if (width && height) { if (width && height) {
if (VgetMonitor() == MON_VGA && Getcookie(C_SupV, NULL) == C_FOUND) { if (hasSuperVidel()) {
pixels = (void *)ct60_vmalloc(height * pitch); pixels = (void *)ct60_vmalloc(height * pitch);
if (!pixels) if (!pixels)
@ -97,21 +150,32 @@ void copyBlit(byte *dst, const byte *src,
return; return;
if (((uintptr)src & 0xFF000000) >= 0xA0000000 && ((uintptr)dst & 0xFF000000) >= 0xA0000000) { if (((uintptr)src & 0xFF000000) >= 0xA0000000 && ((uintptr)dst & 0xFF000000) >= 0xA0000000) {
// while busy blitting... if (superVidelFwVersion >= 9) {
while (*SV_BLITTER_CONTROL & 1); *SV_BLITTER_FIFO = (long)src; // SV_BLITTER_SRC1
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2
*SV_BLITTER_FIFO = (long)dst; // SV_BLITTER_DST
*SV_BLITTER_FIFO = w * bytesPerPixel - 1; // SV_BLITTER_COUNT
*SV_BLITTER_FIFO = srcPitch; // SV_BLITTER_SRC1_OFFSET
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2_OFFSET
*SV_BLITTER_FIFO = dstPitch; // SV_BLITTER_DST_OFFSET
*SV_BLITTER_FIFO = h; // SV_BLITTER_MASK_AND_LINES
*SV_BLITTER_FIFO = 0x01; // SV_BLITTER_CONTROL
} else {
// make sure the blitter is idle
while (*SV_BLITTER_CONTROL & 1);
*SV_BLITTER_SRC1 = (long)src; *SV_BLITTER_SRC1 = (long)src;
*SV_BLITTER_SRC2 = 0x00000000; *SV_BLITTER_SRC2 = 0x00000000;
*SV_BLITTER_DST = (long)dst; *SV_BLITTER_DST = (long)dst;
*SV_BLITTER_COUNT = w * bytesPerPixel - 1; *SV_BLITTER_COUNT = w * bytesPerPixel - 1;
*SV_BLITTER_SRC1_OFFSET = srcPitch; *SV_BLITTER_SRC1_OFFSET = srcPitch;
*SV_BLITTER_SRC2_OFFSET = 0x00000000; *SV_BLITTER_SRC2_OFFSET = 0x00000000;
*SV_BLITTER_DST_OFFSET = dstPitch; *SV_BLITTER_DST_OFFSET = dstPitch;
*SV_BLITTER_MASK_AND_LINES = h; *SV_BLITTER_MASK_AND_LINES = h;
*SV_BLITTER_CONTROL = 0x01; *SV_BLITTER_CONTROL = 0x01;
}
// wait until we finish otherwise we may overwrite pixels written manually afterwards syncSuperBlitter();
while (*SV_BLITTER_CONTROL & 1);
} else if (dstPitch == srcPitch && ((w * bytesPerPixel) == dstPitch)) { } else if (dstPitch == srcPitch && ((w * bytesPerPixel) == dstPitch)) {
if (hasMove16() && ((uintptr)src & (ALIGN - 1)) == 0 && ((uintptr)dst & (ALIGN - 1)) == 0) { if (hasMove16() && ((uintptr)src & (ALIGN - 1)) == 0 && ((uintptr)dst & (ALIGN - 1)) == 0) {
__asm__ volatile( __asm__ volatile(

View File

@ -25,7 +25,7 @@
namespace Graphics { namespace Graphics {
// see graphics/blit-atari.cpp, Atari Falcon's SuperVidel addon allows accelerated blitting // see graphics/blit-atari.cpp, Atari Falcon's SuperVidel addon allows accelerated blitting
#ifndef ATARI #ifndef USE_SV_BLITTER
// Function to blit a rect // Function to blit a rect
void copyBlit(byte *dst, const byte *src, void copyBlit(byte *dst, const byte *src,
const uint dstPitch, const uint srcPitch, const uint dstPitch, const uint srcPitch,

View File

@ -63,7 +63,7 @@ MODULE_OBJS += \
scaler/downscalerARM.o scaler/downscalerARM.o
endif endif
ifdef ATARI ifdef USE_SV_BLITTER
MODULE_OBJS += \ MODULE_OBJS += \
blit-atari.o blit-atari.o
endif endif

View File

@ -64,7 +64,7 @@ void Surface::drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY,
} }
// see graphics/blit-atari.cpp, Atari Falcon's SuperVidel addon allows accelerated blitting // see graphics/blit-atari.cpp, Atari Falcon's SuperVidel addon allows accelerated blitting
#ifndef ATARI #ifndef USE_SV_BLITTER
void Surface::create(int16 width, int16 height, const PixelFormat &f) { void Surface::create(int16 width, int16 height, const PixelFormat &f) {
assert(width >= 0 && height >= 0); assert(width >= 0 && height >= 0);
free(); free();