mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-04 16:26:53 +00:00
BACKENDS: ATARI: Refactor
This commit is contained in:
parent
740cf0989c
commit
6c5e3dbfd5
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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
1
configure
vendored
@ -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"
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user