[Scummvm-git-logs] scummvm master -> 30670e0a46b234808d8e44f4978f4afd0e2bea20
mikrosk
noreply at scummvm.org
Mon Jul 15 17:43:42 UTC 2024
This automated email contains information about 13 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c6e0584ed8 BACKENDS: ATARI: Enable HE games (using bink)
ee3421b283 BACKENDS: SDL: Fix a crash
08bd51f38a BACKENDS: ATARI: Fix a buffer overflow
3482685a07 BACKENDS: ATARI: Complete Eiffel support
b34af00210 BACKENDS: ATARI: Silence some of dlmalloc warnings
e9c7c8e03c JANITORIAL: atari_c2p-asm -> atari-c2p-asm
957aa15e7e BACKENDS: ATARI: Move Cursor outside AtariGraphicsManager
c7bc03d4f4 BACKENDS: ATARI: Move Screen outside AtariGraphicsManager
0c77d67845 BACKENDS: ATARI: Make Cursor Screen's property
dd49c9e3ce BACKENDS: ATARI: QoL improvements
4c98561eec BACKENDS: ATARI: Move timer interrupt to ossystem_atari.cpp
7dabb755dd BACKENDS: ATARI: Fixes to build scripts
30670e0a46 BACKENDS: ATARI: Add support for -mfastcall
Commit: c6e0584ed85391f2ceda77b3d9e141a29a24a4e6
https://github.com/scummvm/scummvm/commit/c6e0584ed85391f2ceda77b3d9e141a29a24a4e6
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:50+02:00
Commit Message:
BACKENDS: ATARI: Enable HE games (using bink)
It's doesn't cost that much (400k) and it's reasonably fast on CT60.
Changed paths:
backends/platform/atari/build-release.sh
diff --git a/backends/platform/atari/build-release.sh b/backends/platform/atari/build-release.sh
index 856169a0fe1..dbbd47ea15c 100755
--- a/backends/platform/atari/build-release.sh
+++ b/backends/platform/atari/build-release.sh
@@ -30,7 +30,6 @@ then
--disable-translation \
--disable-eventrecorder \
--disable-tts \
- --disable-bink \
--opengl-mode=none \
--enable-verbose-build \
--enable-text-console \
Commit: ee3421b283eee9b9ed292b9695b3edf6e347be50
https://github.com/scummvm/scummvm/commit/ee3421b283eee9b9ed292b9695b3edf6e347be50
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:50+02:00
Commit Message:
BACKENDS: SDL: Fix a crash
Returning Common::Path(0) in case that neither $HOME or $XDG_CONFIG_HOME
is found leads to a crash in Common::FSNode as it is not prepared to
handle such an object.
Changed paths:
backends/platform/sdl/posix/posix.cpp
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index d406eb7f77d..f2330f7fc4c 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -140,13 +140,11 @@ Common::Path OSystem_POSIX::getDefaultConfigFileName() {
envVar = getenv("XDG_CONFIG_HOME");
if (!envVar || !*envVar) {
envVar = getenv("HOME");
- if (!envVar) {
- return 0;
- }
-
- if (Posix::assureDirectoryExists(".config", envVar)) {
- prefix = envVar;
- prefix += "/.config";
+ if (envVar && *envVar) {
+ if (Posix::assureDirectoryExists(".config", envVar)) {
+ prefix = envVar;
+ prefix += "/.config";
+ }
}
} else {
prefix = envVar;
Commit: 08bd51f38a84b799bcb4cfde31937abb59942ebb
https://github.com/scummvm/scummvm/commit/08bd51f38a84b799bcb4cfde31937abb59942ebb
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:50+02:00
Commit Message:
BACKENDS: ATARI: Fix a buffer overflow
Apparently 1024 characters is not enough for everyone.
Changed paths:
backends/platform/atari/osystem_atari.cpp
diff --git a/backends/platform/atari/osystem_atari.cpp b/backends/platform/atari/osystem_atari.cpp
index 8547b00db03..5b3a9cd7ec0 100644
--- a/backends/platform/atari/osystem_atari.cpp
+++ b/backends/platform/atari/osystem_atari.cpp
@@ -381,7 +381,7 @@ void OSystem_Atari::logMessage(LogMessageType::Type type, const char *message) {
output = stderr;
static char str[1024+1];
- sprintf(str, "[%08d] %s", getMillis(), message);
+ snprintf(str, sizeof(str), "[%08d] %s", getMillis(), message);
fputs(str, output);
fflush(output);
Commit: 3482685a075b0982520fb1e66d8c295540d94448
https://github.com/scummvm/scummvm/commit/3482685a075b0982520fb1e66d8c295540d94448
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:50+02:00
Commit Message:
BACKENDS: ATARI: Complete Eiffel support
Also, pass proper keycode of the modifier keys instead of
KEYCODE_INVALID.
Changed paths:
backends/events/atari/atari-events.cpp
backends/events/atari/atari-events.h
diff --git a/backends/events/atari/atari-events.cpp b/backends/events/atari/atari-events.cpp
index ae6d1d46b93..ce848acbebe 100644
--- a/backends/events/atari/atari-events.cpp
+++ b/backends/events/atari/atari-events.cpp
@@ -60,7 +60,12 @@ AtariEventSource::AtariEventSource() {
_scancodeToKeycode[0x0e] = Common::KEYCODE_BACKSPACE;
_scancodeToKeycode[0x0f] = Common::KEYCODE_TAB;
_scancodeToKeycode[0x1c] = Common::KEYCODE_RETURN;
+ _scancodeToKeycode[0x1d] = Common::KEYCODE_LCTRL; // Eiffel doesn't recognise RCTRL
+ _scancodeToKeycode[0x2a] = Common::KEYCODE_LSHIFT;
+ _scancodeToKeycode[0x36] = Common::KEYCODE_RSHIFT;
+ _scancodeToKeycode[0x38] = Common::KEYCODE_LALT; // Eiffel doesn't recognise RALT
_scancodeToKeycode[0x39] = Common::KEYCODE_SPACE;
+ _scancodeToKeycode[0x3a] = Common::KEYCODE_CAPSLOCK;
_scancodeToKeycode[0x3b] = Common::KEYCODE_F1;
_scancodeToKeycode[0x3c] = Common::KEYCODE_F2;
_scancodeToKeycode[0x3d] = Common::KEYCODE_F3;
@@ -75,19 +80,24 @@ AtariEventSource::AtariEventSource() {
_scancodeToKeycode[0x46] = Common::KEYCODE_PAGEDOWN; // Eiffel only
_scancodeToKeycode[0x47] = Common::KEYCODE_HOME;
_scancodeToKeycode[0x48] = Common::KEYCODE_UP;
+ _scancodeToKeycode[0x49] = Common::KEYCODE_PRINT; // Eiffel only
_scancodeToKeycode[0x4a] = Common::KEYCODE_KP_MINUS;
_scancodeToKeycode[0x4b] = Common::KEYCODE_LEFT;
- _scancodeToKeycode[0x4c] = Common::KEYCODE_LMETA;
+ _scancodeToKeycode[0x4c] = Common::KEYCODE_SCROLLOCK; // Eiffel only (on Milan: AltGr!)
_scancodeToKeycode[0x4d] = Common::KEYCODE_RIGHT;
_scancodeToKeycode[0x4e] = Common::KEYCODE_KP_PLUS;
_scancodeToKeycode[0x4f] = Common::KEYCODE_PAUSE; // Eiffel only
_scancodeToKeycode[0x50] = Common::KEYCODE_DOWN;
_scancodeToKeycode[0x52] = Common::KEYCODE_INSERT;
_scancodeToKeycode[0x53] = Common::KEYCODE_DELETE;
+ _scancodeToKeycode[0x54] = Common::KEYCODE_NUMLOCK; // Eiffel only
_scancodeToKeycode[0x55] = Common::KEYCODE_END; // Eiffel only
+ _scancodeToKeycode[0x56] = Common::KEYCODE_LMETA; // Eiffel only
+ _scancodeToKeycode[0x57] = Common::KEYCODE_RMETA; // Eiffel only
+ _scancodeToKeycode[0x58] = Common::KEYCODE_MENU; // Eiffel only
_scancodeToKeycode[0x5b] = Common::KEYCODE_TILDE; // Eiffel only
- _scancodeToKeycode[0x61] = Common::KEYCODE_F12; // UNDO
- _scancodeToKeycode[0x62] = Common::KEYCODE_F11; // HELP
+ _scancodeToKeycode[0x61] = Common::KEYCODE_F12; // UNDO (there's also Common::KEYCODE_UNDO available...)
+ _scancodeToKeycode[0x62] = Common::KEYCODE_F11; // HELP (there's also Common::KEYCODE_HELP available...)
_scancodeToKeycode[0x63] = Common::KEYCODE_LEFTPAREN; // KEYPAD (
_scancodeToKeycode[0x64] = Common::KEYCODE_RIGHTPAREN; // KEYPAD )
_scancodeToKeycode[0x65] = Common::KEYCODE_KP_DIVIDE; // KEYPAD /
@@ -177,6 +187,27 @@ bool AtariEventSource::pollEvent(Common::Event &event) {
if (scancode == 0x3a && pressed)
_capslockActive = !_capslockActive;
+ if (scancode == 0x4c && pressed)
+ _scrolllockActive = !_scrolllockActive;
+
+ if (scancode == 0x54 && pressed)
+ _numlockActive = !_numlockActive;
+
+ // Eiffel only
+ if (scancode == 0x37) {
+ if (pressed) {
+ _mmbDown = true;
+ event.type = Common::EVENT_MBUTTONDOWN;
+ event.mouse = _graphicsManager->getMousePosition();
+ return true;
+ } else if (_mmbDown) {
+ _mmbDown = false;
+ event.type = Common::EVENT_MBUTTONUP;
+ event.mouse = _graphicsManager->getMousePosition();
+ return true;
+ }
+ }
+
// Eiffel only
if (scancode == 0x59) {
event.type = Common::EVENT_WHEELUP;
@@ -269,6 +300,8 @@ bool AtariEventSource::pollEvent(Common::Event &event) {
event.kbd.flags |= _altActive ? Common::KBD_ALT : 0;
event.kbd.flags |= (_lshiftActive || _rshiftActive) ? Common::KBD_SHIFT : 0;
event.kbd.flags |= _capslockActive ? Common::KBD_CAPS : 0;
+ event.kbd.flags |= _scrolllockActive ? Common::KBD_SCRL : 0;
+ event.kbd.flags |= _numlockActive ? Common::KBD_NUM : 0;
return true;
}
diff --git a/backends/events/atari/atari-events.h b/backends/events/atari/atari-events.h
index 38c29019090..cb12fa258dc 100644
--- a/backends/events/atari/atari-events.h
+++ b/backends/events/atari/atari-events.h
@@ -45,6 +45,7 @@ private:
AtariGraphicsManager *_graphicsManager = nullptr;
bool _lmbDown = false;
+ bool _mmbDown = false;
bool _rmbDown = false;
bool _lshiftActive = false;
@@ -52,6 +53,8 @@ private:
bool _ctrlActive = false;
bool _altActive = false;
bool _capslockActive = false;
+ bool _scrolllockActive = false;
+ bool _numlockActive = false;
byte _unshiftToAscii[128];
byte _shiftToAscii[128];
Commit: b34af00210be49daf32f7862d149e7e8571f3086
https://github.com/scummvm/scummvm/commit/b34af00210be49daf32f7862d149e7e8571f3086
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:50+02:00
Commit Message:
BACKENDS: ATARI: Silence some of dlmalloc warnings
They were printed every time something has been changed in
atari-graphics.cpp.
Changed paths:
backends/platform/atari/dlmalloc.h
diff --git a/backends/platform/atari/dlmalloc.h b/backends/platform/atari/dlmalloc.h
index eb8232c946d..0ac3fbf360f 100644
--- a/backends/platform/atari/dlmalloc.h
+++ b/backends/platform/atari/dlmalloc.h
@@ -31,6 +31,12 @@
#define MSPACES 1
#define MALLOC_ALIGNMENT ((size_t)16U) /* 16B cache line */
+#pragma GCC diagnostic push
+/* warning: 'mallinfo mallinfo()' hides constructor for 'struct mallinfo' [-Wshadow] */
+#pragma GCC diagnostic ignored "-Wshadow"
+/* warning: this use of "defined" may not be portable [-Wexpansion-to-defined] */
+#pragma GCC diagnostic ignored "-Wexpansion-to-defined"
+
/*
Copyright 2023 Doug Lea
@@ -1461,4 +1467,6 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int);
} /* end of extern "C" */
#endif /* __cplusplus */
+#pragma GCC diagnostic pop
+
#endif /* PLATFORM_ATARI_DLMALLOC_H */
Commit: e9c7c8e03c9270b2bd33cd7761a416a24f5fe96e
https://github.com/scummvm/scummvm/commit/e9c7c8e03c9270b2bd33cd7761a416a24f5fe96e
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:50+02:00
Commit Message:
JANITORIAL: atari_c2p-asm -> atari-c2p-asm
Changed paths:
A backends/graphics/atari/atari-c2p-asm.S
A backends/graphics/atari/atari-c2p-asm.h
R backends/graphics/atari/atari_c2p-asm.S
R backends/graphics/atari/atari_c2p-asm.h
backends/graphics/atari/atari-graphics-videl.h
backends/module.mk
diff --git a/backends/graphics/atari/atari_c2p-asm.S b/backends/graphics/atari/atari-c2p-asm.S
similarity index 100%
rename from backends/graphics/atari/atari_c2p-asm.S
rename to backends/graphics/atari/atari-c2p-asm.S
diff --git a/backends/graphics/atari/atari_c2p-asm.h b/backends/graphics/atari/atari-c2p-asm.h
similarity index 100%
rename from backends/graphics/atari/atari_c2p-asm.h
rename to backends/graphics/atari/atari-c2p-asm.h
diff --git a/backends/graphics/atari/atari-graphics-videl.h b/backends/graphics/atari/atari-graphics-videl.h
index 584b699c01f..862409b91f1 100644
--- a/backends/graphics/atari/atari-graphics-videl.h
+++ b/backends/graphics/atari/atari-graphics-videl.h
@@ -24,8 +24,8 @@
#include "backends/graphics/atari/atari-graphics.h"
+#include "backends/graphics/atari/atari-c2p-asm.h"
#include "backends/graphics/atari/atari-graphics-asm.h"
-#include "backends/graphics/atari/atari_c2p-asm.h"
#include "common/system.h"
class AtariVidelManager : public AtariGraphicsManager {
diff --git a/backends/module.mk b/backends/module.mk
index 5d885c96ca0..cdbe853f735 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -367,7 +367,7 @@ endif
ifeq ($(BACKEND),atari)
MODULE_OBJS += \
events/atari/atari-events.o \
- graphics/atari/atari_c2p-asm.o \
+ graphics/atari/atari-c2p-asm.o \
graphics/atari/atari-graphics.o \
graphics/atari/atari-graphics-asm.o \
mixer/atari/atari-mixer.o
Commit: 957aa15e7e7b520ebf9aca8e73785f7a8cd42670
https://github.com/scummvm/scummvm/commit/957aa15e7e7b520ebf9aca8e73785f7a8cd42670
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: Move Cursor outside AtariGraphicsManager
Changed paths:
A backends/graphics/atari/atari-cursor.cpp
A backends/graphics/atari/atari-cursor.h
backends/graphics/atari/atari-graphics.cpp
backends/graphics/atari/atari-graphics.h
backends/module.mk
diff --git a/backends/graphics/atari/atari-cursor.cpp b/backends/graphics/atari/atari-cursor.cpp
new file mode 100644
index 00000000000..dab54c911b9
--- /dev/null
+++ b/backends/graphics/atari/atari-cursor.cpp
@@ -0,0 +1,150 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "atari-cursor.h"
+
+#include <cassert>
+
+extern bool g_unalignedPitch;
+
+void Cursor::update(const Graphics::Surface &screen, bool isModified) {
+ if (!_buf) {
+ outOfScreen = true;
+ return;
+ }
+
+ if (!visible || !isModified)
+ return;
+
+ srcRect = Common::Rect(_width, _height);
+
+ dstRect = Common::Rect(
+ _x - _hotspotX, // left
+ _y - _hotspotY, // top
+ _x - _hotspotX + _width, // right
+ _y - _hotspotY + _height); // bottom
+
+ outOfScreen = !screen.clip(srcRect, dstRect);
+
+ assert(srcRect.width() == dstRect.width());
+ assert(srcRect.height() == dstRect.height());
+}
+
+void Cursor::updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen) {
+ _x += deltaX;
+ _y += deltaY;
+
+ if (_x < 0)
+ _x = 0;
+ else if (_x >= screen.w)
+ _x = screen.w - 1;
+
+ if (_y < 0)
+ _y = 0;
+ else if (_y >= screen.h)
+ _y = screen.h - 1;
+}
+
+void Cursor::setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor) {
+ if (w == 0 || h == 0 || buf == nullptr) {
+ _buf = nullptr;
+ return;
+ }
+
+ _buf = (const byte *)buf;
+ _width = w;
+ _height = h;
+ _hotspotX = hotspotX;
+ _hotspotY = hotspotY;
+ _keycolor = keycolor;
+}
+
+void Cursor::convertTo(const Graphics::PixelFormat &format) {
+ const int cursorWidth = (srcRect.width() + 15) & (-16);
+ const int cursorHeight = _height;
+ const bool isCLUT8 = format.isCLUT8();
+
+ if (surface.w != cursorWidth || surface.h != cursorHeight || surface.format != format) {
+ if (!isCLUT8 && surface.format != format) {
+ _rShift = format.rLoss - format.rShift;
+ _gShift = format.gLoss - format.gShift;
+ _bShift = format.bLoss - format.bShift;
+
+ _rMask = format.rMax() << format.rShift;
+ _gMask = format.gMax() << format.gShift;
+ _bMask = format.bMax() << format.bShift;
+ }
+
+ surface.create(cursorWidth, cursorHeight, format);
+
+ const bool old_unalignedPitch = g_unalignedPitch;
+ g_unalignedPitch = true;
+ surfaceMask.create(surface.w / 8, surface.h, format); // 1 bpl
+ g_unalignedPitch = old_unalignedPitch;
+ }
+
+ const int srcRectWidth = srcRect.width();
+
+ const byte *src = _buf + srcRect.left;
+ byte *dst = (byte *)surface.getPixels();
+ uint16 *dstMask = (uint16 *)surfaceMask.getPixels();
+ const int srcPadding = _width - srcRectWidth;
+ const int dstPadding = surface.w - srcRectWidth;
+
+ for (int j = 0; j < cursorHeight; ++j) {
+ for (int i = 0; i < srcRectWidth; ++i) {
+ const uint32 color = *src++;
+ const uint16 bit = 1 << (15 - (i % 16));
+
+ if (color != _keycolor) {
+ if (!isCLUT8) {
+ // Convert CLUT8 to RGB332/RGB121 palette
+ *dst++ = ((palette[color*3 + 0] >> _rShift) & _rMask)
+ | ((palette[color*3 + 1] >> _gShift) & _gMask)
+ | ((palette[color*3 + 2] >> _bShift) & _bMask);
+ } else {
+ *dst++ = color;
+ }
+
+ // clear bit
+ *dstMask &= ~bit;
+ } else {
+ *dst++ = 0x00;
+
+ // set bit
+ *dstMask |= bit;
+ }
+
+ if (bit == 0x0001)
+ dstMask++;
+ }
+
+ src += srcPadding;
+
+ if (dstPadding) {
+ memset(dst, 0x00, dstPadding);
+ dst += dstPadding;
+
+ *dstMask |= ((1 << dstPadding) - 1);
+ dstMask++;
+ }
+ }
+}
diff --git a/backends/graphics/atari/atari-cursor.h b/backends/graphics/atari/atari-cursor.h
new file mode 100644
index 00000000000..7f1795ab0ce
--- /dev/null
+++ b/backends/graphics/atari/atari-cursor.h
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_ATARI_CURSOR_H
+#define BACKENDS_GRAPHICS_ATARI_CURSOR_H
+
+#include "common/rect.h"
+#include "common/scummsys.h"
+#include "graphics/surface.h"
+
+struct Cursor {
+ void update(const Graphics::Surface &screen, bool isModified);
+
+ bool visible = false;
+
+ // position
+ Common::Point getPosition() const {
+ return Common::Point(_x, _y);
+ }
+ void setPosition(int x, int y) {
+ _x = x;
+ _y = y;
+ }
+ void updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen);
+ void swap() {
+ const int tmpX = _oldX;
+ const int tmpY = _oldY;
+
+ _oldX = _x;
+ _oldY = _y;
+
+ _x = tmpX;
+ _y = tmpY;
+ }
+
+ // surface
+ void setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor);
+ void convertTo(const Graphics::PixelFormat &format);
+ Graphics::Surface surface;
+ Graphics::Surface surfaceMask;
+
+ // rects (valid only if !outOfScreen)
+ bool isClipped() const {
+ return outOfScreen ? false : _width != srcRect.width();
+ }
+ bool outOfScreen = true;
+ Common::Rect srcRect;
+ Common::Rect dstRect;
+
+ // palette (only used for the overlay)
+ byte palette[256*3] = {};
+
+private:
+ int _x = -1, _y = -1;
+ int _oldX = -1, _oldY = -1;
+
+ // related to 'surface'
+ const byte *_buf = nullptr;
+ int _width;
+ int _height;
+ int _hotspotX;
+ int _hotspotY;
+ uint32 _keycolor;
+
+ int _rShift, _gShift, _bShift;
+ int _rMask, _gMask, _bMask;
+};
+
+#endif // BACKENDS_GRAPHICS_ATARI_CURSOR_H
diff --git a/backends/graphics/atari/atari-graphics.cpp b/backends/graphics/atari/atari-graphics.cpp
index 08ac79d8a69..8ce12b34a9b 100644
--- a/backends/graphics/atari/atari-graphics.cpp
+++ b/backends/graphics/atari/atari-graphics.cpp
@@ -1050,10 +1050,7 @@ bool AtariGraphicsManager::updateScreenInternal(const Graphics::Surface &srcSurf
//debug("Redraw cursor: %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
if (cursorSurfaceChanged || _cursor.isClipped()) {
- if (dstSurface->format.isCLUT8())
- _cursor.convertTo<true>(dstSurface->format);
- else
- _cursor.convertTo<false>(dstSurface->format);
+ _cursor.convertTo(dstSurface->format);
{
// copy in-place (will do nothing on regular Surface::copyRectToSurface)
Graphics::Surface surf;
@@ -1311,128 +1308,3 @@ void AtariGraphicsManager::Screen::restoreBackground(const Common::Rect &rect) {
rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
offsettedSurf->format.bytesPerPixel);
}
-
-
-void AtariGraphicsManager::Cursor::update(const Graphics::Surface &screen, bool isModified) {
- if (!_buf) {
- outOfScreen = true;
- return;
- }
-
- if (!visible || !isModified)
- return;
-
- srcRect = Common::Rect(_width, _height);
-
- dstRect = Common::Rect(
- _x - _hotspotX, // left
- _y - _hotspotY, // top
- _x - _hotspotX + _width, // right
- _y - _hotspotY + _height); // bottom
-
- outOfScreen = !screen.clip(srcRect, dstRect);
-
- assert(srcRect.width() == dstRect.width());
- assert(srcRect.height() == dstRect.height());
-}
-
-void AtariGraphicsManager::Cursor::updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen) {
- _x += deltaX;
- _y += deltaY;
-
- if (_x < 0)
- _x = 0;
- else if (_x >= screen.w)
- _x = screen.w - 1;
-
- if (_y < 0)
- _y = 0;
- else if (_y >= screen.h)
- _y = screen.h - 1;
-}
-
-void AtariGraphicsManager::Cursor::setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor) {
- if (w == 0 || h == 0 || buf == nullptr) {
- _buf = nullptr;
- return;
- }
-
- _buf = (const byte *)buf;
- _width = w;
- _height = h;
- _hotspotX = hotspotX;
- _hotspotY = hotspotY;
- _keycolor = keycolor;
-}
-
-template <bool isClut8> // hopefully compiler optimizes all the branching out
-void AtariGraphicsManager::Cursor::convertTo(const Graphics::PixelFormat &format) {
- const int cursorWidth = (srcRect.width() + 15) & (-16);
- const int cursorHeight = _height;
-
- if (surface.w != cursorWidth || surface.h != cursorHeight || surface.format != format) {
- if (!isClut8 && surface.format != format) {
- _rShift = format.rLoss - format.rShift;
- _gShift = format.gLoss - format.gShift;
- _bShift = format.bLoss - format.bShift;
-
- _rMask = format.rMax() << format.rShift;
- _gMask = format.gMax() << format.gShift;
- _bMask = format.bMax() << format.bShift;
- }
-
- surface.create(cursorWidth, cursorHeight, format);
-
- const bool old_unalignedPitch = g_unalignedPitch;
- g_unalignedPitch = true;
- surfaceMask.create(surface.w / 8, surface.h, format); // 1 bpl
- g_unalignedPitch = old_unalignedPitch;
- }
-
- const int srcRectWidth = srcRect.width();
-
- const byte *src = _buf + srcRect.left;
- byte *dst = (byte *)surface.getPixels();
- uint16 *dstMask = (uint16 *)surfaceMask.getPixels();
- const int srcPadding = _width - srcRectWidth;
- const int dstPadding = surface.w - srcRectWidth;
-
- for (int j = 0; j < cursorHeight; ++j) {
- for (int i = 0; i < srcRectWidth; ++i) {
- const uint32 color = *src++;
- const uint16 bit = 1 << (15 - (i % 16));
-
- if (color != _keycolor) {
- if (!isClut8) {
- // Convert CLUT8 to RGB332/RGB121 palette
- *dst++ = ((palette[color*3 + 0] >> _rShift) & _rMask)
- | ((palette[color*3 + 1] >> _gShift) & _gMask)
- | ((palette[color*3 + 2] >> _bShift) & _bMask);
- } else {
- *dst++ = color;
- }
-
- // clear bit
- *dstMask &= ~bit;
- } else {
- *dst++ = 0x00;
-
- // set bit
- *dstMask |= bit;
- }
-
- if (bit == 0x0001)
- dstMask++;
- }
-
- src += srcPadding;
-
- if (dstPadding) {
- memset(dst, 0x00, dstPadding);
- dst += dstPadding;
-
- *dstMask |= ((1 << dstPadding) - 1);
- dstMask++;
- }
- }
-}
diff --git a/backends/graphics/atari/atari-graphics.h b/backends/graphics/atari/atari-graphics.h
index 0ca1a5e2ce1..c057d4a1389 100644
--- a/backends/graphics/atari/atari-graphics.h
+++ b/backends/graphics/atari/atari-graphics.h
@@ -29,6 +29,7 @@
#include <mint/ostruct.h>
#include <unordered_set>
+#include "atari-cursor.h"
#include "common/rect.h"
#include "graphics/surface.h"
@@ -318,64 +319,6 @@ private:
bool _overlayVisible = false;
Graphics::Surface _overlaySurface;
- struct Cursor {
- void update(const Graphics::Surface &screen, bool isModified);
-
- bool visible = false;
-
- // position
- Common::Point getPosition() const {
- return Common::Point(_x, _y);
- }
- void setPosition(int x, int y) {
- _x = x;
- _y = y;
- }
- void updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen);
- void swap() {
- const int tmpX = _oldX;
- const int tmpY = _oldY;
-
- _oldX = _x;
- _oldY = _y;
-
- _x = tmpX;
- _y = tmpY;
- }
-
- // surface
- void setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor);
- template <bool isClut8>
- void convertTo(const Graphics::PixelFormat &format);
- Graphics::Surface surface;
- Graphics::Surface surfaceMask;
-
- // rects (valid only if !outOfScreen)
- bool isClipped() const {
- return outOfScreen ? false : _width != srcRect.width();
- }
- bool outOfScreen = true;
- Common::Rect srcRect;
- Common::Rect dstRect;
-
- // palette (only used for the overlay)
- byte palette[256*3] = {};
-
- private:
- int _x = -1, _y = -1;
- int _oldX = -1, _oldY = -1;
-
- // related to 'surface'
- const byte *_buf = nullptr;
- int _width;
- int _height;
- int _hotspotX;
- int _hotspotY;
- uint32 _keycolor;
-
- int _rShift, _gShift, _bShift;
- int _rMask, _gMask, _bMask;
- };
Cursor _cursor;
Palette _palette;
diff --git a/backends/module.mk b/backends/module.mk
index cdbe853f735..7595b86dfd1 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -368,6 +368,7 @@ ifeq ($(BACKEND),atari)
MODULE_OBJS += \
events/atari/atari-events.o \
graphics/atari/atari-c2p-asm.o \
+ graphics/atari/atari-cursor.o \
graphics/atari/atari-graphics.o \
graphics/atari/atari-graphics-asm.o \
mixer/atari/atari-mixer.o
Commit: c7bc03d4f48e873fc4e1bab80d2653b5f0ced405
https://github.com/scummvm/scummvm/commit/c7bc03d4f48e873fc4e1bab80d2653b5f0ced405
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: Move Screen outside AtariGraphicsManager
Changed paths:
A backends/graphics/atari/atari-screen.cpp
A backends/graphics/atari/atari-screen.h
backends/graphics/atari/atari-graphics.cpp
backends/graphics/atari/atari-graphics.h
backends/module.mk
diff --git a/backends/graphics/atari/atari-graphics.cpp b/backends/graphics/atari/atari-graphics.cpp
index 8ce12b34a9b..818be679cee 100644
--- a/backends/graphics/atari/atari-graphics.cpp
+++ b/backends/graphics/atari/atari-graphics.cpp
@@ -21,18 +21,15 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE // atari-graphics.h's unordered_set
-#include "backends/graphics/atari/atari-graphics.h"
+#include "atari-graphics.h"
#include <mint/cookie.h>
-#include <mint/falcon.h>
#include <mint/osbind.h>
#include <mint/sysvars.h>
-#include "backends/graphics/atari/atari-graphics-superblitter.h"
+#include "backends/platform/atari/dlmalloc.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymap.h"
-#include "backends/platform/atari/dlmalloc.h"
-
#include "common/config-manager.h"
#include "common/str.h"
#include "common/textconsole.h" // for warning() & error()
@@ -41,10 +38,9 @@
#include "graphics/blit.h"
#include "gui/ThemeEngine.h"
-#define SCREEN_ACTIVE
+#include "atari-graphics-superblitter.h"
-#define MAX_HZ_SHAKE 16 // Falcon only
-#define MAX_V_SHAKE 16
+#define SCREEN_ACTIVE
bool g_unalignedPitch = false;
mspace g_mspace = nullptr;
@@ -991,15 +987,15 @@ template <bool directRendering> // hopefully compiler optimizes all the branchin
bool AtariGraphicsManager::updateScreenInternal(const Graphics::Surface &srcSurface) {
//debug("updateScreenInternal");
- const DirtyRects &dirtyRects = _workScreen->dirtyRects;
- Graphics::Surface *dstSurface = _workScreen->offsettedSurf;
- bool &cursorPositionChanged = _workScreen->cursorPositionChanged;
- bool &cursorSurfaceChanged = _workScreen->cursorSurfaceChanged;
- bool &cursorVisibilityChanged = _workScreen->cursorVisibilityChanged;
- Common::Rect &oldCursorRect = _workScreen->oldCursorRect;
- const bool &fullRedraw = _workScreen->fullRedraw;
+ const Screen::DirtyRects &dirtyRects = _workScreen->dirtyRects;
+ Graphics::Surface *dstSurface = _workScreen->offsettedSurf;
+ bool &cursorPositionChanged = _workScreen->cursorPositionChanged;
+ bool &cursorSurfaceChanged = _workScreen->cursorSurfaceChanged;
+ bool &cursorVisibilityChanged = _workScreen->cursorVisibilityChanged;
+ Common::Rect &oldCursorRect = _workScreen->oldCursorRect;
+ const bool &fullRedraw = _workScreen->fullRedraw;
- const int dstBitsPerPixel = getBitsPerPixel(dstSurface->format);
+ const int dstBitsPerPixel = getBitsPerPixel(dstSurface->format);
bool updated = false;
@@ -1129,182 +1125,3 @@ bool AtariGraphicsManager::isOverlayDirectRendering() const {
#endif
;
}
-
-AtariGraphicsManager::Screen::Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette_)
- : _manager(manager)
- , palette(palette_) {
- const AtariMemAlloc &allocFunc = _manager->getStRamAllocFunc();
-
- surf.init(
- width + (_manager->_tt ? 0 : 2 * MAX_HZ_SHAKE),
- height + 2 * MAX_V_SHAKE,
- (width + (_manager->_tt ? 0 : 2 * MAX_HZ_SHAKE)) * _manager->getBitsPerPixel(format) / 8,
- nullptr,
- format);
-
- void *pixelsUnaligned = allocFunc(sizeof(uintptr) + (surf.h * surf.pitch) + ALIGN - 1);
- if (!pixelsUnaligned) {
- error("Failed to allocate memory in ST RAM");
- }
-
- surf.setPixels((void *)(((uintptr)pixelsUnaligned + sizeof(uintptr) + ALIGN - 1) & (-ALIGN)));
-
- // store the unaligned pointer for later release
- *((uintptr *)surf.getPixels() - 1) = (uintptr)pixelsUnaligned;
-
- memset(surf.getPixels(), 0, surf.h * surf.pitch);
-
- _offsettedSurf.init(
- width, height, surf.pitch,
- surf.getBasePtr((surf.w - width) / 2, (surf.h - height) / 2),
- surf.format);
-}
-
-AtariGraphicsManager::Screen::~Screen() {
- const AtariMemFree &freeFunc = _manager->getStRamFreeFunc();
-
- freeFunc((void *)*((uintptr *)surf.getPixels() - 1));
-}
-
-void AtariGraphicsManager::Screen::reset(int width, int height, int bitsPerPixel) {
- cursorPositionChanged = true;
- cursorSurfaceChanged = true;
- cursorVisibilityChanged = false;
- clearDirtyRects();
- oldCursorRect = Common::Rect();
- rez = -1;
- mode = -1;
-
- // erase old screen
- _offsettedSurf.fillRect(Common::Rect(_offsettedSurf.w, _offsettedSurf.h), 0);
-
- if (_manager->_tt) {
- if (width <= 320 && height <= 240) {
- surf.w = 320;
- surf.h = 240 + 2 * MAX_V_SHAKE;
- surf.pitch = 2 * surf.w * bitsPerPixel / 8;
- rez = kRezValueTTLow;
- } else {
- surf.w = 640;
- surf.h = 480 + 2 * MAX_V_SHAKE;
- surf.pitch = surf.w * bitsPerPixel / 8;
- rez = kRezValueTTMid;
- }
- } else {
- mode = VsetMode(VM_INQUIRE) & PAL;
-
- if (_manager->_vgaMonitor) {
- mode |= VGA | (bitsPerPixel == 4 ? BPS4 : (hasSuperVidel() ? BPS8C : BPS8));
-
- if (width <= 320 && height <= 240) {
- surf.w = 320;
- surf.h = 240;
- mode |= VERTFLAG | COL40;
- } else {
- surf.w = 640;
- surf.h = 480;
- mode |= COL80;
- }
- } else {
- mode |= TV | (bitsPerPixel == 4 ? BPS4 : BPS8);
-
- if (width <= 320 && height <= 200) {
- surf.w = 320;
- surf.h = 200;
- mode |= COL40;
- } else if (width <= 320*1.2 && height <= 200*1.2) {
- surf.w = 320*1.2;
- surf.h = 200*1.2;
- mode |= OVERSCAN | COL40;
- } else if (width <= 640 && height <= 400) {
- surf.w = 640;
- surf.h = 400;
- mode |= VERTFLAG | COL80;
- } else {
- surf.w = 640*1.2;
- surf.h = 400*1.2;
- mode |= VERTFLAG | OVERSCAN | COL80;
- }
- }
-
- surf.w += 2 * MAX_HZ_SHAKE;
- surf.h += 2 * MAX_V_SHAKE;
- surf.pitch = surf.w * bitsPerPixel / 8;
- }
-
- _offsettedSurf.init(
- width, height, surf.pitch,
- surf.getBasePtr((surf.w - width) / 2, (surf.h - height) / 2),
- surf.format);
-}
-
-void AtariGraphicsManager::Screen::addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rect &rect, bool directRendering) {
- if (fullRedraw)
- return;
-
- if ((rect.width() == srcSurface.w && rect.height() == srcSurface.h)
- || dirtyRects.size() == 128) { // 320x200 can hold at most 250 16x16 rectangles
- //debug("addDirtyRect[%d]: purge %d x %d", (int)dirtyRects.size(), srcSurface.w, srcSurface.h);
-
- dirtyRects.clear();
- dirtyRects.emplace(srcSurface.w, srcSurface.h);
-
- oldCursorRect = Common::Rect();
-
- fullRedraw = true;
- return;
- }
-
- dirtyRects.insert(rect);
-
- if (!oldCursorRect.isEmpty()) {
- const Common::Rect alignedOldCursorRect = _manager->alignRect(oldCursorRect);
-
- // we have to check *aligned* oldCursorRect because it is background which gets copied,
- // i.e. it has to be up to date even outside the cursor rectangle.
- // do it now to avoid complex checking in updateScreenInternal()
- if (rect.contains(alignedOldCursorRect)) {
- oldCursorRect = Common::Rect();
- } else if (rect.intersects(alignedOldCursorRect)) {
- if (!directRendering) {
- _manager->copyRectToSurface(
- *offsettedSurf, _manager->getBitsPerPixel(offsettedSurf->format), srcSurface,
- alignedOldCursorRect.left, alignedOldCursorRect.top,
- alignedOldCursorRect);
- } else {
- restoreBackground(alignedOldCursorRect);
- }
-
- oldCursorRect = Common::Rect();
- }
- }
-}
-
-void AtariGraphicsManager::Screen::storeBackground(const Common::Rect &rect) {
- const int bitsPerPixel = _manager->getBitsPerPixel(offsettedSurf->format);
-
- if (_cursorBackgroundSurf.w != rect.width()
- || _cursorBackgroundSurf.h != rect.height()
- || _cursorBackgroundSurf.format != offsettedSurf->format) {
- _cursorBackgroundSurf.create(rect.width(), rect.height(), offsettedSurf->format);
- _cursorBackgroundSurf.pitch = _cursorBackgroundSurf.pitch * bitsPerPixel / 8;
- }
-
- Graphics::copyBlit(
- (byte *)_cursorBackgroundSurf.getPixels(),
- (const byte *)offsettedSurf->getPixels() + rect.top * offsettedSurf->pitch + rect.left * bitsPerPixel / 8,
- _cursorBackgroundSurf.pitch, offsettedSurf->pitch,
- rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
- offsettedSurf->format.bytesPerPixel);
-}
-
-void AtariGraphicsManager::Screen::restoreBackground(const Common::Rect &rect) {
- const int bitsPerPixel = _manager->getBitsPerPixel(offsettedSurf->format);
-
- Graphics::copyBlit(
- (byte *)offsettedSurf->getPixels() + rect.top * offsettedSurf->pitch + rect.left * bitsPerPixel / 8,
- (const byte *)_cursorBackgroundSurf.getPixels(),
- offsettedSurf->pitch, _cursorBackgroundSurf.pitch,
- rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
- offsettedSurf->format.bytesPerPixel);
-}
diff --git a/backends/graphics/atari/atari-graphics.h b/backends/graphics/atari/atari-graphics.h
index c057d4a1389..164d32232b3 100644
--- a/backends/graphics/atari/atari-graphics.h
+++ b/backends/graphics/atari/atari-graphics.h
@@ -26,25 +26,19 @@
#include "common/events.h"
#include <mint/osbind.h>
-#include <mint/ostruct.h>
-#include <unordered_set>
-#include "atari-cursor.h"
#include "common/rect.h"
#include "graphics/surface.h"
-template<>
-struct std::hash<Common::Rect>
-{
- std::size_t operator()(Common::Rect const& rect) const noexcept
- {
- return 31 * (31 * (31 * rect.left + rect.top) + rect.right) + rect.bottom;
- }
-};
+#include "atari-cursor.h"
+#include "atari-screen.h"
-///////////////////////////////////////////////////////////////////////////////
+#define MAX_HZ_SHAKE 16 // Falcon only
+#define MAX_V_SHAKE 16
class AtariGraphicsManager : public GraphicsManager, Common::EventObserver {
+ friend class Screen;
+
public:
AtariGraphicsManager();
virtual ~AtariGraphicsManager();
@@ -116,42 +110,11 @@ protected:
void allocateSurfaces();
void freeSurfaces();
- enum class GraphicsMode : int {
- DirectRendering = 0,
- SingleBuffering = 1,
- TripleBuffering = 3
- };
-
- struct GraphicsState {
- GraphicsState(GraphicsMode mode_)
- : mode(mode_)
- , width(0)
- , height(0) {
- }
-
- GraphicsMode mode;
- int width;
- int height;
- Graphics::PixelFormat format;
- };
- GraphicsState _pendingState{ (GraphicsMode)getDefaultGraphicsMode() };
-
private:
- using DirtyRects = std::unordered_set<Common::Rect>;
-
enum CustomEventAction {
kActionToggleAspectRatioCorrection = 100,
};
- enum SteTtRezValue {
- kRezValueSTLow = 0, // 320x200 at 4bpp, ST palette
- kRezValueSTMid = 1, // 640x200 at 2bpp, ST palette
- kRezValueSTHigh = 2, // 640x400 at 1bpp, ST palette
- kRezValueTTLow = 7, // 320x480 at 8bpp, TT palette
- kRezValueTTMid = 4, // 640x480 at 4bpp, TT palette
- kRezValueTTHigh = 6 // 1280x960 at 1bpp, TT palette
- };
-
int16 getMaximumScreenHeight() const { return 480; }
int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 640 : 640*1.2); }
@@ -236,6 +199,25 @@ private:
bool _oldAspectRatioCorrection = false;
bool _checkUnalignedPitch = false;
+ enum class GraphicsMode : int {
+ DirectRendering = 0,
+ SingleBuffering = 1,
+ TripleBuffering = 3
+ };
+
+ struct GraphicsState {
+ GraphicsState(GraphicsMode mode_)
+ : mode(mode_)
+ , width(0)
+ , height(0) {
+ }
+
+ GraphicsMode mode;
+ int width;
+ int height;
+ Graphics::PixelFormat format;
+ };
+ GraphicsState _pendingState{ (GraphicsMode)getDefaultGraphicsMode() };
GraphicsState _currentState{ (GraphicsMode)getDefaultGraphicsMode() };
enum PendingScreenChange {
@@ -253,63 +235,6 @@ private:
OVERLAY_BUFFER,
BUFFER_COUNT
};
-
- class Palette {
- public:
- void clear() {
- memset(data, 0, sizeof(data));
- }
-
- uint16 *const tt = reinterpret_cast<uint16*>(data);
- _RGB *const falcon = reinterpret_cast<_RGB*>(data);
-
- private:
- byte data[256*4] = {};
- };
-
- struct Screen {
- Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette);
- ~Screen();
-
- void reset(int width, int height, int bitsPerPixel);
- // must be called before any rectangle drawing
- void addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rect &rect, bool directRendering);
-
- void clearDirtyRects() {
- dirtyRects.clear();
- fullRedraw = false;
- }
-
- void storeBackground(const Common::Rect &rect);
- void restoreBackground(const Common::Rect &rect);
-
- Graphics::Surface surf;
- const Palette *palette;
- bool cursorPositionChanged = true;
- bool cursorSurfaceChanged = true;
- bool cursorVisibilityChanged = false;
- DirtyRects dirtyRects;
- bool fullRedraw = false;
- Common::Rect oldCursorRect;
- int rez = -1;
- int mode = -1;
- Graphics::Surface *const offsettedSurf = &_offsettedSurf;
-
- int oldScreenSurfaceWidth = -1;
- int oldScreenSurfaceHeight = -1;
- int oldScreenSurfacePitch = -1;
- int oldOffsettedSurfaceWidth = -1;
- int oldOffsettedSurfaceHeight = -1;
-
- private:
- static constexpr size_t ALIGN = 16; // 16 bytes
-
- const AtariGraphicsManager *_manager;
-
- Graphics::Surface _offsettedSurf;
- // used by direct rendering
- Graphics::Surface _cursorBackgroundSurf;
- };
Screen *_screen[BUFFER_COUNT] = {};
Screen *_workScreen = nullptr;
Screen *_oldWorkScreen = nullptr; // used in hideOverlay()
diff --git a/backends/graphics/atari/atari-screen.cpp b/backends/graphics/atari/atari-screen.cpp
new file mode 100644
index 00000000000..d1f30dd66aa
--- /dev/null
+++ b/backends/graphics/atari/atari-screen.cpp
@@ -0,0 +1,208 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "atari-screen.h"
+
+#include <mint/falcon.h>
+
+#include "graphics/blit.h"
+
+#include "atari-graphics.h"
+#include "atari-graphics-superblitter.h"
+
+Screen::Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette_)
+ : _manager(manager)
+ , palette(palette_) {
+ const AtariGraphicsManager::AtariMemAlloc &allocFunc = _manager->getStRamAllocFunc();
+
+ surf.init(
+ width + (_manager->_tt ? 0 : 2 * MAX_HZ_SHAKE),
+ height + 2 * MAX_V_SHAKE,
+ (width + (_manager->_tt ? 0 : 2 * MAX_HZ_SHAKE)) * _manager->getBitsPerPixel(format) / 8,
+ nullptr,
+ format);
+
+ void *pixelsUnaligned = allocFunc(sizeof(uintptr) + (surf.h * surf.pitch) + ALIGN - 1);
+ if (!pixelsUnaligned) {
+ error("Failed to allocate memory in ST RAM");
+ }
+
+ surf.setPixels((void *)(((uintptr)pixelsUnaligned + sizeof(uintptr) + ALIGN - 1) & (-ALIGN)));
+
+ // store the unaligned pointer for later release
+ *((uintptr *)surf.getPixels() - 1) = (uintptr)pixelsUnaligned;
+
+ memset(surf.getPixels(), 0, surf.h * surf.pitch);
+
+ _offsettedSurf.init(
+ width, height, surf.pitch,
+ surf.getBasePtr((surf.w - width) / 2, (surf.h - height) / 2),
+ surf.format);
+}
+
+Screen::~Screen() {
+ const AtariGraphicsManager::AtariMemFree &freeFunc = _manager->getStRamFreeFunc();
+
+ freeFunc((void *)*((uintptr *)surf.getPixels() - 1));
+}
+
+void Screen::reset(int width, int height, int bitsPerPixel) {
+ cursorPositionChanged = true;
+ cursorSurfaceChanged = true;
+ cursorVisibilityChanged = false;
+ clearDirtyRects();
+ oldCursorRect = Common::Rect();
+ rez = -1;
+ mode = -1;
+
+ // erase old screen
+ _offsettedSurf.fillRect(Common::Rect(_offsettedSurf.w, _offsettedSurf.h), 0);
+
+ if (_manager->_tt) {
+ if (width <= 320 && height <= 240) {
+ surf.w = 320;
+ surf.h = 240 + 2 * MAX_V_SHAKE;
+ surf.pitch = 2 * surf.w * bitsPerPixel / 8;
+ rez = kRezValueTTLow;
+ } else {
+ surf.w = 640;
+ surf.h = 480 + 2 * MAX_V_SHAKE;
+ surf.pitch = surf.w * bitsPerPixel / 8;
+ rez = kRezValueTTMid;
+ }
+ } else {
+ mode = VsetMode(VM_INQUIRE) & PAL;
+
+ if (_manager->_vgaMonitor) {
+ mode |= VGA | (bitsPerPixel == 4 ? BPS4 : (hasSuperVidel() ? BPS8C : BPS8));
+
+ if (width <= 320 && height <= 240) {
+ surf.w = 320;
+ surf.h = 240;
+ mode |= VERTFLAG | COL40;
+ } else {
+ surf.w = 640;
+ surf.h = 480;
+ mode |= COL80;
+ }
+ } else {
+ mode |= TV | (bitsPerPixel == 4 ? BPS4 : BPS8);
+
+ if (width <= 320 && height <= 200) {
+ surf.w = 320;
+ surf.h = 200;
+ mode |= COL40;
+ } else if (width <= 320*1.2 && height <= 200*1.2) {
+ surf.w = 320*1.2;
+ surf.h = 200*1.2;
+ mode |= OVERSCAN | COL40;
+ } else if (width <= 640 && height <= 400) {
+ surf.w = 640;
+ surf.h = 400;
+ mode |= VERTFLAG | COL80;
+ } else {
+ surf.w = 640*1.2;
+ surf.h = 400*1.2;
+ mode |= VERTFLAG | OVERSCAN | COL80;
+ }
+ }
+
+ surf.w += 2 * MAX_HZ_SHAKE;
+ surf.h += 2 * MAX_V_SHAKE;
+ surf.pitch = surf.w * bitsPerPixel / 8;
+ }
+
+ _offsettedSurf.init(
+ width, height, surf.pitch,
+ surf.getBasePtr((surf.w - width) / 2, (surf.h - height) / 2),
+ surf.format);
+}
+
+void Screen::addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rect &rect, bool directRendering) {
+ if (fullRedraw)
+ return;
+
+ if ((rect.width() == srcSurface.w && rect.height() == srcSurface.h)
+ || dirtyRects.size() == 128) { // 320x200 can hold at most 250 16x16 rectangles
+ //debug("addDirtyRect[%d]: purge %d x %d", (int)dirtyRects.size(), srcSurface.w, srcSurface.h);
+
+ dirtyRects.clear();
+ dirtyRects.emplace(srcSurface.w, srcSurface.h);
+
+ oldCursorRect = Common::Rect();
+
+ fullRedraw = true;
+ return;
+ }
+
+ dirtyRects.insert(rect);
+
+ if (!oldCursorRect.isEmpty()) {
+ const Common::Rect alignedOldCursorRect = _manager->alignRect(oldCursorRect);
+
+ // we have to check *aligned* oldCursorRect because it is background which gets copied,
+ // i.e. it has to be up to date even outside the cursor rectangle.
+ // do it now to avoid complex checking in updateScreenInternal()
+ if (rect.contains(alignedOldCursorRect)) {
+ oldCursorRect = Common::Rect();
+ } else if (rect.intersects(alignedOldCursorRect)) {
+ if (!directRendering) {
+ _manager->copyRectToSurface(
+ *offsettedSurf, _manager->getBitsPerPixel(offsettedSurf->format), srcSurface,
+ alignedOldCursorRect.left, alignedOldCursorRect.top,
+ alignedOldCursorRect);
+ } else {
+ restoreBackground(alignedOldCursorRect);
+ }
+
+ oldCursorRect = Common::Rect();
+ }
+ }
+}
+
+void Screen::storeBackground(const Common::Rect &rect) {
+ const int bitsPerPixel = _manager->getBitsPerPixel(offsettedSurf->format);
+
+ if (_cursorBackgroundSurf.w != rect.width()
+ || _cursorBackgroundSurf.h != rect.height()
+ || _cursorBackgroundSurf.format != offsettedSurf->format) {
+ _cursorBackgroundSurf.create(rect.width(), rect.height(), offsettedSurf->format);
+ _cursorBackgroundSurf.pitch = _cursorBackgroundSurf.pitch * bitsPerPixel / 8;
+ }
+
+ Graphics::copyBlit(
+ (byte *)_cursorBackgroundSurf.getPixels(),
+ (const byte *)offsettedSurf->getPixels() + rect.top * offsettedSurf->pitch + rect.left * bitsPerPixel / 8,
+ _cursorBackgroundSurf.pitch, offsettedSurf->pitch,
+ rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
+ offsettedSurf->format.bytesPerPixel);
+}
+
+void Screen::restoreBackground(const Common::Rect &rect) {
+ const int bitsPerPixel = _manager->getBitsPerPixel(offsettedSurf->format);
+
+ Graphics::copyBlit(
+ (byte *)offsettedSurf->getPixels() + rect.top * offsettedSurf->pitch + rect.left * bitsPerPixel / 8,
+ (const byte *)_cursorBackgroundSurf.getPixels(),
+ offsettedSurf->pitch, _cursorBackgroundSurf.pitch,
+ rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
+ offsettedSurf->format.bytesPerPixel);
+}
diff --git a/backends/graphics/atari/atari-screen.h b/backends/graphics/atari/atari-screen.h
new file mode 100644
index 00000000000..7ffd188a5e7
--- /dev/null
+++ b/backends/graphics/atari/atari-screen.h
@@ -0,0 +1,110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_ATARI_SCREEN_H
+#define BACKENDS_GRAPHICS_ATARI_SCREEN_H
+
+#include <unordered_set>
+#include <mint/ostruct.h>
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+template<>
+struct std::hash<Common::Rect>
+{
+ std::size_t operator()(Common::Rect const& rect) const noexcept
+ {
+ return 31 * (31 * (31 * rect.left + rect.top) + rect.right) + rect.bottom;
+ }
+};
+
+class AtariGraphicsManager;
+
+class Palette {
+public:
+ void clear() {
+ memset(data, 0, sizeof(data));
+ }
+
+ uint16 *const tt = reinterpret_cast<uint16*>(data);
+ _RGB *const falcon = reinterpret_cast<_RGB*>(data);
+
+private:
+ byte data[256*4] = {};
+};
+
+struct Screen {
+ using DirtyRects = std::unordered_set<Common::Rect>;
+
+ Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette);
+ ~Screen();
+
+ void reset(int width, int height, int bitsPerPixel);
+ // must be called before any rectangle drawing
+ void addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rect &rect, bool directRendering);
+
+ void clearDirtyRects() {
+ dirtyRects.clear();
+ fullRedraw = false;
+ }
+
+ void storeBackground(const Common::Rect &rect);
+ void restoreBackground(const Common::Rect &rect);
+
+ Graphics::Surface surf;
+ const Palette *palette;
+ bool cursorPositionChanged = true;
+ bool cursorSurfaceChanged = true;
+ bool cursorVisibilityChanged = false;
+ DirtyRects dirtyRects;
+ bool fullRedraw = false;
+ Common::Rect oldCursorRect;
+ int rez = -1;
+ int mode = -1;
+ Graphics::Surface *const offsettedSurf = &_offsettedSurf;
+
+ int oldScreenSurfaceWidth = -1;
+ int oldScreenSurfaceHeight = -1;
+ int oldScreenSurfacePitch = -1;
+ int oldOffsettedSurfaceWidth = -1;
+ int oldOffsettedSurfaceHeight = -1;
+
+private:
+ static constexpr size_t ALIGN = 16; // 16 bytes
+
+ enum SteTtRezValue {
+ kRezValueSTLow = 0, // 320x200 at 4bpp, ST palette
+ kRezValueSTMid = 1, // 640x200 at 2bpp, ST palette
+ kRezValueSTHigh = 2, // 640x400 at 1bpp, ST palette
+ kRezValueTTLow = 7, // 320x480 at 8bpp, TT palette
+ kRezValueTTMid = 4, // 640x480 at 4bpp, TT palette
+ kRezValueTTHigh = 6 // 1280x960 at 1bpp, TT palette
+ };
+
+ const AtariGraphicsManager *_manager;
+
+ Graphics::Surface _offsettedSurf;
+ // used by direct rendering
+ Graphics::Surface _cursorBackgroundSurf;
+};
+
+#endif // BACKENDS_GRAPHICS_ATARI_SCREEN_H
diff --git a/backends/module.mk b/backends/module.mk
index 7595b86dfd1..8cb79e3601e 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -371,6 +371,7 @@ MODULE_OBJS += \
graphics/atari/atari-cursor.o \
graphics/atari/atari-graphics.o \
graphics/atari/atari-graphics-asm.o \
+ graphics/atari/atari-screen.o \
mixer/atari/atari-mixer.o
endif
Commit: 0c77d678452d599f52da6fbb5162b21dc87d0718
https://github.com/scummvm/scummvm/commit/0c77d678452d599f52da6fbb5162b21dc87d0718
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: Make Cursor Screen's property
Instead of having one globally in AtariGraphicsManager. This simplifies
code and cleans up a lot of dark corners in AtariGraphicsManager.
A slight disadvantage is that now the cursor surface has be to converted
for each buffer.
Changed paths:
backends/graphics/atari/atari-cursor.cpp
backends/graphics/atari/atari-cursor.h
backends/graphics/atari/atari-graphics.cpp
backends/graphics/atari/atari-graphics.h
backends/graphics/atari/atari-screen.cpp
backends/graphics/atari/atari-screen.h
diff --git a/backends/graphics/atari/atari-cursor.cpp b/backends/graphics/atari/atari-cursor.cpp
index dab54c911b9..ec178b19a47 100644
--- a/backends/graphics/atari/atari-cursor.cpp
+++ b/backends/graphics/atari/atari-cursor.cpp
@@ -23,44 +23,56 @@
#include <cassert>
+#include "graphics/blit.h"
+
+#include "atari-graphics.h"
+#include "atari-screen.h"
+
extern bool g_unalignedPitch;
-void Cursor::update(const Graphics::Surface &screen, bool isModified) {
+byte Cursor::_palette[256*3] = {};
+
+void Cursor::update() {
if (!_buf) {
- outOfScreen = true;
+ _outOfScreen = true;
return;
}
- if (!visible || !isModified)
+ if (!_visible || (!_positionChanged && !_surfaceChanged))
return;
- srcRect = Common::Rect(_width, _height);
+ _srcRect = Common::Rect(_width, _height);
- dstRect = Common::Rect(
+ _dstRect = Common::Rect(
_x - _hotspotX, // left
_y - _hotspotY, // top
_x - _hotspotX + _width, // right
_y - _hotspotY + _height); // bottom
- outOfScreen = !screen.clip(srcRect, dstRect);
+ _outOfScreen = !_parentScreen->offsettedSurf->clip(_srcRect, _dstRect);
- assert(srcRect.width() == dstRect.width());
- assert(srcRect.height() == dstRect.height());
+ assert(_srcRect.width() == _dstRect.width());
+ assert(_srcRect.height() == _dstRect.height());
}
-void Cursor::updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen) {
+void Cursor::updatePosition(int deltaX, int deltaY) {
+ if (deltaX == 0 && deltaY == 0)
+ return;
+
_x += deltaX;
_y += deltaY;
if (_x < 0)
_x = 0;
- else if (_x >= screen.w)
- _x = screen.w - 1;
+ else if (_x >= _parentScreen->offsettedSurf->w)
+ _x = _parentScreen->offsettedSurf->w - 1;
if (_y < 0)
_y = 0;
- else if (_y >= screen.h)
- _y = screen.h - 1;
+ else if (_y >= _parentScreen->offsettedSurf->h)
+ _y = _parentScreen->offsettedSurf->h - 1;
+
+ _positionChanged = true;
}
void Cursor::setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor) {
@@ -75,15 +87,24 @@ void Cursor::setSurface(const void *buf, int w, int h, int hotspotX, int hotspot
_hotspotX = hotspotX;
_hotspotY = hotspotY;
_keycolor = keycolor;
+
+ _surfaceChanged = true;
+}
+
+void Cursor::setPalette(const byte *colors, uint start, uint num) {
+ if (colors)
+ memcpy(&_palette[start * 3], colors, num * 3);
+
+ _surfaceChanged = true;
}
void Cursor::convertTo(const Graphics::PixelFormat &format) {
- const int cursorWidth = (srcRect.width() + 15) & (-16);
+ const int cursorWidth = (_srcRect.width() + 15) & (-16);
const int cursorHeight = _height;
const bool isCLUT8 = format.isCLUT8();
- if (surface.w != cursorWidth || surface.h != cursorHeight || surface.format != format) {
- if (!isCLUT8 && surface.format != format) {
+ if (_surface.w != cursorWidth || _surface.h != cursorHeight || _surface.format != format) {
+ if (!isCLUT8 && _surface.format != format) {
_rShift = format.rLoss - format.rShift;
_gShift = format.gLoss - format.gShift;
_bShift = format.bLoss - format.bShift;
@@ -93,21 +114,21 @@ void Cursor::convertTo(const Graphics::PixelFormat &format) {
_bMask = format.bMax() << format.bShift;
}
- surface.create(cursorWidth, cursorHeight, format);
+ _surface.create(cursorWidth, cursorHeight, format);
const bool old_unalignedPitch = g_unalignedPitch;
g_unalignedPitch = true;
- surfaceMask.create(surface.w / 8, surface.h, format); // 1 bpl
+ _surfaceMask.create(_surface.w / 8, _surface.h, format); // 1 bpl
g_unalignedPitch = old_unalignedPitch;
}
- const int srcRectWidth = srcRect.width();
+ const int srcRectWidth = _srcRect.width();
- const byte *src = _buf + srcRect.left;
- byte *dst = (byte *)surface.getPixels();
- uint16 *dstMask = (uint16 *)surfaceMask.getPixels();
+ const byte *src = _buf + _srcRect.left;
+ byte *dst = (byte *)_surface.getPixels();
+ uint16 *dstMask = (uint16 *)_surfaceMask.getPixels();
const int srcPadding = _width - srcRectWidth;
- const int dstPadding = surface.w - srcRectWidth;
+ const int dstPadding = _surface.w - srcRectWidth;
for (int j = 0; j < cursorHeight; ++j) {
for (int i = 0; i < srcRectWidth; ++i) {
@@ -117,9 +138,9 @@ void Cursor::convertTo(const Graphics::PixelFormat &format) {
if (color != _keycolor) {
if (!isCLUT8) {
// Convert CLUT8 to RGB332/RGB121 palette
- *dst++ = ((palette[color*3 + 0] >> _rShift) & _rMask)
- | ((palette[color*3 + 1] >> _gShift) & _gMask)
- | ((palette[color*3 + 2] >> _bShift) & _bMask);
+ *dst++ = ((_palette[color*3 + 0] >> _rShift) & _rMask)
+ | ((_palette[color*3 + 1] >> _gShift) & _gMask)
+ | ((_palette[color*3 + 2] >> _bShift) & _bMask);
} else {
*dst++ = color;
}
@@ -148,3 +169,106 @@ void Cursor::convertTo(const Graphics::PixelFormat &format) {
}
}
}
+
+void Cursor::flushBackground(const Graphics::Surface &srcSurface, const Common::Rect &rect) {
+ if (_savedRect.isEmpty())
+ return;
+
+ if (rect.contains(_savedRect)) {
+ _savedRect = Common::Rect();
+ } else if (rect.intersects(_savedRect)) {
+ restoreBackground(srcSurface, true);
+ }
+}
+
+bool Cursor::restoreBackground(const Graphics::Surface &srcSurface, bool force) {
+ if (_savedRect.isEmpty() || (!force && !isChanged()))
+ return false;
+
+ Graphics::Surface &dstSurface = *_parentScreen->offsettedSurf;
+ const int dstBitsPerPixel = _manager->getBitsPerPixel(dstSurface.format);
+
+ //debug("Cursor::restoreBackground: %d %d %d %d", _savedRect.left, _savedRect.top, _savedRect.width(), _savedRect.height());
+
+ if (srcSurface.getPixels()) {
+ _manager->copyRectToSurface(
+ dstSurface, dstBitsPerPixel, srcSurface,
+ _savedRect.left, _savedRect.top,
+ _savedRect);
+ } else {
+ const int bytesPerPixel = dstSurface.format.bytesPerPixel;
+
+ // restore native pixels (i.e. bitplanes)
+ Graphics::copyBlit(
+ (byte *)dstSurface.getPixels() + _savedRect.top * dstSurface.pitch + _savedRect.left * dstBitsPerPixel / 8,
+ (const byte *)_savedBackground.getPixels(),
+ dstSurface.pitch, _savedBackground.pitch,
+ _savedRect.width() * dstBitsPerPixel / 8, _savedRect.height(), // fake 4bpp by 8bpp's width/2
+ bytesPerPixel);
+ }
+
+ _savedRect = Common::Rect();
+ return true;
+}
+
+bool Cursor::draw(bool directRendering, bool force) {
+ if (!isVisible() || (!force && !isChanged())) {
+ _visibilityChanged = _positionChanged = _surfaceChanged = false;
+ return false;
+ }
+
+ Graphics::Surface &dstSurface = *_parentScreen->offsettedSurf;
+ const int dstBitsPerPixel = _manager->getBitsPerPixel(dstSurface.format);
+
+ //debug("Cursor::draw: %d %d %d %d", _dstRect.left, _dstRect.top, _dstRect.width(), _dstRect.height());
+
+ // always work with aligned rect
+ _savedRect = _manager->alignRect(_dstRect);
+
+ if (_surfaceChanged || _width != _srcRect.width()) {
+ // TODO: check for change, not just different width so it's not called over and over again ...
+ // TODO: some sort of in-place C2P directly into convertTo() ...
+ convertTo(dstSurface.format);
+ {
+ // c2p in-place (will do nothing on regular Surface::copyRectToSurface)
+ Graphics::Surface surf;
+ surf.init(
+ _surface.w,
+ _surface.h,
+ _surface.pitch * dstBitsPerPixel / 8, // 4bpp is not byte per pixel anymore
+ _surface.getPixels(),
+ _surface.format);
+ _manager->copyRectToSurface(
+ surf, dstBitsPerPixel, _surface,
+ 0, 0,
+ Common::Rect(_surface.w, _surface.h));
+ }
+ }
+
+ if (directRendering) {
+ // store native pixels (i.e. bitplanes)
+ if (_savedBackground.w != _savedRect.width()
+ || _savedBackground.h != _savedRect.height()
+ || _savedBackground.format != dstSurface.format) {
+ _savedBackground.create(_savedRect.width(), _savedRect.height(), dstSurface.format);
+ _savedBackground.pitch = _savedBackground.pitch * dstBitsPerPixel / 8;
+ }
+
+ Graphics::copyBlit(
+ (byte *)_savedBackground.getPixels(),
+ (const byte *)dstSurface.getPixels() + _savedRect.top * dstSurface.pitch + _savedRect.left * dstBitsPerPixel / 8,
+ _savedBackground.pitch, dstSurface.pitch,
+ _savedRect.width() * dstBitsPerPixel / 8, _savedRect.height(), // fake 4bpp by 8bpp's width/2
+ dstSurface.format.bytesPerPixel);
+ }
+
+ // don't use _srcRect.right as 'x2' as this must be aligned first
+ // (_surface.w is recalculated thanks to convertTo())
+ _manager->drawMaskedSprite(
+ dstSurface, dstBitsPerPixel, _surface, _surfaceMask,
+ _dstRect.left, _dstRect.top,
+ Common::Rect(0, _srcRect.top, _surface.w, _srcRect.bottom));
+
+ _visibilityChanged = _positionChanged = _surfaceChanged = false;
+ return true;
+}
diff --git a/backends/graphics/atari/atari-cursor.h b/backends/graphics/atari/atari-cursor.h
index 7f1795ab0ce..2de90f5da3a 100644
--- a/backends/graphics/atari/atari-cursor.h
+++ b/backends/graphics/atari/atari-cursor.h
@@ -26,51 +26,100 @@
#include "common/scummsys.h"
#include "graphics/surface.h"
+class AtariGraphicsManager;
+struct Screen;
+
+// Global state consists of:
+// - palette (used for the overlay only atm)
+// - shape (surface, dimensions, hotspot, keycolor)
+// - visibility
+// These always get updates by ScummVM, no need to differentiate between engines and the overlay.
+
struct Cursor {
- void update(const Graphics::Surface &screen, bool isModified);
+ Cursor(AtariGraphicsManager *manager, Screen *screen)
+ : _manager(manager)
+ , _parentScreen(screen) {
+ }
+
+ void reset() {
+ _positionChanged = true;
+ _surfaceChanged = true;
+ _visibilityChanged = false;
+
+ _savedRect = Common::Rect();
+ }
+
+ // updates outOfScreen OR srcRect/dstRect (only if visible/needed)
+ void update();
+
+ // visibility
+ bool setVisible(bool visible) {
+ if (_visible == visible) {
+ return _visible;
+ }
+
+ bool last = _visible;
+
+ _visible = visible;
+
+ _visibilityChanged = true;
- bool visible = false;
+ return last;
+ }
// position
Common::Point getPosition() const {
return Common::Point(_x, _y);
}
void setPosition(int x, int y) {
+ if (_x == x && _y == y)
+ return;
+
_x = x;
_y = y;
- }
- void updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen);
- void swap() {
- const int tmpX = _oldX;
- const int tmpY = _oldY;
- _oldX = _x;
- _oldY = _y;
-
- _x = tmpX;
- _y = tmpY;
+ _positionChanged = true;
}
+ void updatePosition(int deltaX, int deltaY);
// surface
void setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor);
+ void setPalette(const byte *colors, uint start, uint num);
void convertTo(const Graphics::PixelFormat &format);
- Graphics::Surface surface;
- Graphics::Surface surfaceMask;
- // rects (valid only if !outOfScreen)
- bool isClipped() const {
- return outOfScreen ? false : _width != srcRect.width();
+ bool isVisible() const {
+ return !_outOfScreen && _visible;
+ }
+ bool isChanged() const {
+ return _positionChanged || _surfaceChanged || _visibilityChanged;
}
- bool outOfScreen = true;
- Common::Rect srcRect;
- Common::Rect dstRect;
- // palette (only used for the overlay)
- byte palette[256*3] = {};
+ bool intersects(const Common::Rect &rect) const {
+ return rect.intersects(_dstRect);
+ }
+
+ void flushBackground(const Graphics::Surface &srcSurface, const Common::Rect &rect);
+ bool restoreBackground(const Graphics::Surface &srcSurface, bool force);
+ bool draw(bool directRendering, bool force);
private:
+ static byte _palette[256*3];
+
+ AtariGraphicsManager *_manager;
+ Screen *_parentScreen;
+
+ bool _positionChanged = true;
+ bool _surfaceChanged = true;
+ bool _visibilityChanged = false;
+
+ bool _visible = false;
int _x = -1, _y = -1;
- int _oldX = -1, _oldY = -1;
+ bool _outOfScreen = true;
+ Common::Rect _srcRect;
+ Common::Rect _dstRect;
+
+ Graphics::Surface _savedBackground; // used by direct rendering
+ Common::Rect _savedRect;
// related to 'surface'
const byte *_buf = nullptr;
@@ -80,6 +129,8 @@ private:
int _hotspotY;
uint32 _keycolor;
+ Graphics::Surface _surface;
+ Graphics::Surface _surfaceMask;
int _rShift, _gShift, _bShift;
int _rMask, _gMask, _bMask;
};
diff --git a/backends/graphics/atari/atari-graphics.cpp b/backends/graphics/atari/atari-graphics.cpp
index 818be679cee..405a9ff2014 100644
--- a/backends/graphics/atari/atari-graphics.cpp
+++ b/backends/graphics/atari/atari-graphics.cpp
@@ -345,9 +345,9 @@ OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
_chunkySurface.init(_pendingState.width, _pendingState.height, _pendingState.width,
_chunkySurface.getPixels(), _pendingState.format);
- _screen[FRONT_BUFFER]->reset(_pendingState.width, _pendingState.height, 8);
- _screen[BACK_BUFFER1]->reset(_pendingState.width, _pendingState.height, 8);
- _screen[BACK_BUFFER2]->reset(_pendingState.width, _pendingState.height, 8);
+ _screen[FRONT_BUFFER]->reset(_pendingState.width, _pendingState.height, 8, true);
+ _screen[BACK_BUFFER1]->reset(_pendingState.width, _pendingState.height, 8, true);
+ _screen[BACK_BUFFER2]->reset(_pendingState.width, _pendingState.height, 8, true);
_workScreen = _screen[_pendingState.mode <= GraphicsMode::SingleBuffering ? FRONT_BUFFER : BACK_BUFFER1];
s_screenSurf = nullptr;
@@ -361,15 +361,6 @@ OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
_palette.clear();
_pendingScreenChange = kPendingScreenChangeMode | kPendingScreenChangeScreen | kPendingScreenChangePalette;
- static bool firstRun = true;
- if (firstRun) {
- _cursor.setPosition(getOverlayWidth() / 2, getOverlayHeight() / 2);
- _cursor.swap();
- firstRun = false;
- }
-
- warpMouse(_pendingState.width / 2, _pendingState.height / 2);
-
_currentState = _pendingState;
return OSystem::kTransactionSuccess;
@@ -513,30 +504,29 @@ void AtariGraphicsManager::updateScreen() {
_checkUnalignedPitch = false;
}
- // updates outOfScreen OR srcRect/dstRect (only if visible/needed)
- _cursor.update(*lockScreen(), _workScreen->cursorPositionChanged || _workScreen->cursorSurfaceChanged);
+ _workScreen->cursor.update();
bool screenUpdated = false;
if (isOverlayVisible()) {
assert(_workScreen == _screen[OVERLAY_BUFFER]);
if (isOverlayDirectRendering())
- screenUpdated = updateScreenInternal<true>(Graphics::Surface());
+ screenUpdated = updateScreenInternal(Graphics::Surface());
else
- screenUpdated = updateScreenInternal<false>(_overlaySurface);
+ screenUpdated = updateScreenInternal(_overlaySurface);
} else {
switch (_currentState.mode) {
case GraphicsMode::DirectRendering:
assert(_workScreen == _screen[FRONT_BUFFER]);
- screenUpdated = updateScreenInternal<true>(Graphics::Surface());
+ screenUpdated = updateScreenInternal(Graphics::Surface());
break;
case GraphicsMode::SingleBuffering:
assert(_workScreen == _screen[FRONT_BUFFER]);
- screenUpdated = updateScreenInternal<false>(_chunkySurface);
+ screenUpdated = updateScreenInternal(_chunkySurface);
break;
case GraphicsMode::TripleBuffering:
assert(_workScreen == _screen[BACK_BUFFER1]);
- screenUpdated = updateScreenInternal<false>(_chunkySurface);
+ screenUpdated = updateScreenInternal(_chunkySurface);
break;
}
}
@@ -725,21 +715,17 @@ void AtariGraphicsManager::showOverlay(bool inGUI) {
return;
if (_currentState.mode == GraphicsMode::DirectRendering) {
- // make sure that _oldCursorRect is used to restore the original game graphics
- // (but only if resolution hasn't changed, see endGFXTransaction())
- bool wasVisible = showMouse(false);
-
- // revert back but don't update screen
- _cursor.visible = wasVisible;
+ _workScreen->cursor.restoreBackground(Graphics::Surface(), true);
}
- _cursor.swap();
_oldWorkScreen = _workScreen;
_workScreen = _screen[OVERLAY_BUFFER];
// do not cache dirtyRects and oldCursorRect
const int bitsPerPixel = getBitsPerPixel(getOverlayFormat());
- _workScreen->reset(getOverlayWidth(), getOverlayHeight(), bitsPerPixel);
+ static bool resetCursorPosition = true;
+ _workScreen->reset(getOverlayWidth(), getOverlayHeight(), bitsPerPixel, resetCursorPosition);
+ resetCursorPosition = false;
_pendingScreenChange = kPendingScreenChangeMode | kPendingScreenChangeScreen | kPendingScreenChangePalette;
@@ -756,7 +742,6 @@ void AtariGraphicsManager::hideOverlay() {
_workScreen = _oldWorkScreen;
_oldWorkScreen = nullptr;
- _cursor.swap();
// FIXME: perhaps there's a better way but this will do for now
_checkUnalignedPitch = true;
@@ -886,14 +871,13 @@ void AtariGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x,
bool AtariGraphicsManager::showMouse(bool visible) {
//debug("showMouse: %d", visible);
- if (_cursor.visible == visible) {
- return visible;
- }
+ bool last = _workScreen->cursor.setVisible(visible);
- bool last = _cursor.visible;
- _cursor.visible = visible;
+ if (!isOverlayVisible() && _currentState.mode == GraphicsMode::TripleBuffering) {
+ _screen[BACK_BUFFER2]->cursor.setVisible(visible);
+ _screen[FRONT_BUFFER]->cursor.setVisible(visible);
+ }
- cursorVisibilityChanged();
// don't rely on engines to call it (if they don't it confuses the cursor restore logic)
updateScreen();
@@ -903,8 +887,12 @@ bool AtariGraphicsManager::showMouse(bool visible) {
void AtariGraphicsManager::warpMouse(int x, int y) {
//debug("warpMouse: %d, %d", x, y);
- _cursor.setPosition(x, y);
- cursorPositionChanged();
+ _workScreen->cursor.setPosition(x, y);
+
+ if (!isOverlayVisible() && _currentState.mode == GraphicsMode::TripleBuffering) {
+ _screen[BACK_BUFFER2]->cursor.setPosition(x, y);
+ _screen[FRONT_BUFFER]->cursor.setPosition(x, y);
+ }
}
void AtariGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor,
@@ -917,20 +905,33 @@ void AtariGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int h
if (format)
assert(*format == PIXELFORMAT_CLUT8);
- _cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor);
- cursorSurfaceChanged();
+ _workScreen->cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor);
+
+ if (!isOverlayVisible() && _currentState.mode == GraphicsMode::TripleBuffering) {
+ _screen[BACK_BUFFER2]->cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor);
+ _screen[FRONT_BUFFER]->cursor.setSurface(buf, (int)w, (int)h, hotspotX, hotspotY, keycolor);
+ }
}
void AtariGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) {
debug("setCursorPalette: %d, %d", start, num);
- memcpy(&_cursor.palette[start * 3], colors, num * 3);
- cursorSurfaceChanged();
+ _workScreen->cursor.setPalette(colors, start, num);
+
+ if (!isOverlayVisible() && _currentState.mode == GraphicsMode::TripleBuffering) {
+ // avoid copying the same (shared) palette two more times...
+ _screen[BACK_BUFFER2]->cursor.setPalette(nullptr, 0, 0);
+ _screen[FRONT_BUFFER]->cursor.setPalette(nullptr, 0, 0);
+ }
}
void AtariGraphicsManager::updateMousePosition(int deltaX, int deltaY) {
- _cursor.updatePosition(deltaX, deltaY, *lockScreen());
- cursorPositionChanged();
+ _workScreen->cursor.updatePosition(deltaX, deltaY);
+
+ if (!isOverlayVisible() && _currentState.mode == GraphicsMode::TripleBuffering) {
+ _screen[BACK_BUFFER2]->cursor.updatePosition(deltaX, deltaY);
+ _screen[FRONT_BUFFER]->cursor.updatePosition(deltaX, deltaY);
+ }
}
bool AtariGraphicsManager::notifyEvent(const Common::Event &event) {
@@ -983,103 +984,38 @@ void AtariGraphicsManager::freeSurfaces() {
_overlaySurface.free();
}
-template <bool directRendering> // hopefully compiler optimizes all the branching out
bool AtariGraphicsManager::updateScreenInternal(const Graphics::Surface &srcSurface) {
//debug("updateScreenInternal");
const Screen::DirtyRects &dirtyRects = _workScreen->dirtyRects;
Graphics::Surface *dstSurface = _workScreen->offsettedSurf;
- bool &cursorPositionChanged = _workScreen->cursorPositionChanged;
- bool &cursorSurfaceChanged = _workScreen->cursorSurfaceChanged;
- bool &cursorVisibilityChanged = _workScreen->cursorVisibilityChanged;
- Common::Rect &oldCursorRect = _workScreen->oldCursorRect;
- const bool &fullRedraw = _workScreen->fullRedraw;
+ Cursor &cursor = _workScreen->cursor;
+ const bool directRendering = srcSurface.getPixels() == nullptr;
const int dstBitsPerPixel = getBitsPerPixel(dstSurface->format);
bool updated = false;
- const bool cursorDrawEnabled = !_cursor.outOfScreen && _cursor.visible;
- bool drawCursor = cursorDrawEnabled
- && (cursorPositionChanged || cursorSurfaceChanged || cursorVisibilityChanged || fullRedraw);
-
- assert(!fullRedraw || oldCursorRect.isEmpty());
-
- bool restoreCursor = !oldCursorRect.isEmpty()
- && (cursorPositionChanged || cursorSurfaceChanged || (cursorVisibilityChanged && !_cursor.visible));
+ const bool cursorDrawEnabled = cursor.isVisible();
+ bool forceCursorDraw = cursorDrawEnabled && (_workScreen->fullRedraw || cursor.isChanged());
lockSuperBlitter();
for (auto it = dirtyRects.begin(); it != dirtyRects.end(); ++it) {
- if (cursorDrawEnabled && !drawCursor)
- drawCursor = it->intersects(_cursor.dstRect);
+ if (cursorDrawEnabled && !forceCursorDraw)
+ forceCursorDraw = cursor.intersects(*it);
if (!directRendering) {
copyRectToSurface(*dstSurface, dstBitsPerPixel, srcSurface, it->left, it->top, *it);
- updated = true;
+ updated |= true;
}
}
- if (restoreCursor) {
- //debug("Restore cursor: %d %d %d %d", oldCursorRect.left, oldCursorRect.top, oldCursorRect.width(), oldCursorRect.height());
-
- // always restore aligned oldCursorRect
- oldCursorRect = alignRect(oldCursorRect);
-
- if (!directRendering) {
- copyRectToSurface(
- *dstSurface, dstBitsPerPixel, srcSurface,
- oldCursorRect.left, oldCursorRect.top,
- oldCursorRect);
- } else {
- _workScreen->restoreBackground(oldCursorRect);
- }
-
- oldCursorRect = Common::Rect();
-
- updated = true;
- }
+ updated |= cursor.restoreBackground(srcSurface, false);
unlockSuperBlitter();
- if (drawCursor) {
- //debug("Redraw cursor: %d %d %d %d", _cursor.dstRect.left, _cursor.dstRect.top, _cursor.dstRect.width(), _cursor.dstRect.height());
-
- if (cursorSurfaceChanged || _cursor.isClipped()) {
- _cursor.convertTo(dstSurface->format);
- {
- // copy in-place (will do nothing on regular Surface::copyRectToSurface)
- Graphics::Surface surf;
- surf.init(
- _cursor.surface.w,
- _cursor.surface.h,
- _cursor.surface.pitch * dstBitsPerPixel / 8, // 4bpp is not byte per pixel anymore
- _cursor.surface.getPixels(),
- _cursor.surface.format);
- copyRectToSurface(
- surf, dstBitsPerPixel, _cursor.surface,
- 0, 0,
- Common::Rect(_cursor.surface.w, _cursor.surface.h));
- }
- }
-
- if (directRendering)
- _workScreen->storeBackground(alignRect(_cursor.dstRect));
-
- // don't use _cursor.srcRect for width as this must be aligned first
- // (_cursor.surface.w is recalculated thanks to _cursor.isClipped())
- drawMaskedSprite(
- *dstSurface, dstBitsPerPixel, _cursor.surface, _cursor.surfaceMask,
- _cursor.dstRect.left, _cursor.dstRect.top,
- Common::Rect(0, _cursor.srcRect.top, _cursor.surface.w, _cursor.srcRect.bottom));
-
- cursorPositionChanged = cursorSurfaceChanged = false;
- oldCursorRect = _cursor.dstRect;
-
- updated = true;
- }
-
- cursorVisibilityChanged = false;
+ updated |= cursor.draw(directRendering, forceCursorDraw);
return updated;
}
diff --git a/backends/graphics/atari/atari-graphics.h b/backends/graphics/atari/atari-graphics.h
index 164d32232b3..4bc238a01c2 100644
--- a/backends/graphics/atari/atari-graphics.h
+++ b/backends/graphics/atari/atari-graphics.h
@@ -37,6 +37,7 @@
#define MAX_V_SHAKE 16
class AtariGraphicsManager : public GraphicsManager, Common::EventObserver {
+ friend class Cursor;
friend class Screen;
public:
@@ -97,7 +98,7 @@ public:
bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override;
void setCursorPalette(const byte *colors, uint start, uint num) override;
- Common::Point getMousePosition() const { return _cursor.getPosition(); }
+ Common::Point getMousePosition() const { return _workScreen->cursor.getPosition(); }
void updateMousePosition(int deltaX, int deltaY);
bool notifyEvent(const Common::Event &event) override;
@@ -118,7 +119,6 @@ private:
int16 getMaximumScreenHeight() const { return 480; }
int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 640 : 640*1.2); }
- template <bool directRendering>
bool updateScreenInternal(const Graphics::Surface &srcSurface);
void copyRectToScreenInternal(const void *buf, int pitch, int x, int y, int w, int h,
@@ -152,39 +152,6 @@ private:
return alignRect(rect.left, rect.top, rect.width(), rect.height());
}
- void cursorPositionChanged() {
- if (_overlayVisible) {
- _screen[OVERLAY_BUFFER]->cursorPositionChanged = true;
- } else {
- _screen[FRONT_BUFFER]->cursorPositionChanged
- = _screen[BACK_BUFFER1]->cursorPositionChanged
- = _screen[BACK_BUFFER2]->cursorPositionChanged
- = true;
- }
- }
-
- void cursorSurfaceChanged() {
- if (_overlayVisible) {
- _screen[OVERLAY_BUFFER]->cursorSurfaceChanged = true;
- } else {
- _screen[FRONT_BUFFER]->cursorSurfaceChanged
- = _screen[BACK_BUFFER1]->cursorSurfaceChanged
- = _screen[BACK_BUFFER2]->cursorSurfaceChanged
- = true;
- }
- }
-
- void cursorVisibilityChanged() {
- if (_overlayVisible) {
- _screen[OVERLAY_BUFFER]->cursorVisibilityChanged = true;
- } else {
- _screen[FRONT_BUFFER]->cursorVisibilityChanged
- = _screen[BACK_BUFFER1]->cursorVisibilityChanged
- = _screen[BACK_BUFFER2]->cursorVisibilityChanged
- = true;
- }
- }
-
int getOverlayPaletteSize() const {
#ifndef DISABLE_FANCY_THEMES
return _tt ? 16 : 256;
@@ -244,8 +211,6 @@ private:
bool _overlayVisible = false;
Graphics::Surface _overlaySurface;
- Cursor _cursor;
-
Palette _palette;
Palette _overlayPalette;
};
diff --git a/backends/graphics/atari/atari-screen.cpp b/backends/graphics/atari/atari-screen.cpp
index d1f30dd66aa..a5e8ca713bc 100644
--- a/backends/graphics/atari/atari-screen.cpp
+++ b/backends/graphics/atari/atari-screen.cpp
@@ -23,13 +23,12 @@
#include <mint/falcon.h>
-#include "graphics/blit.h"
-
#include "atari-graphics.h"
#include "atari-graphics-superblitter.h"
Screen::Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette_)
: _manager(manager)
+ , cursor(manager, this)
, palette(palette_) {
const AtariGraphicsManager::AtariMemAlloc &allocFunc = _manager->getStRamAllocFunc();
@@ -64,12 +63,11 @@ Screen::~Screen() {
freeFunc((void *)*((uintptr *)surf.getPixels() - 1));
}
-void Screen::reset(int width, int height, int bitsPerPixel) {
- cursorPositionChanged = true;
- cursorSurfaceChanged = true;
- cursorVisibilityChanged = false;
+void Screen::reset(int width, int height, int bitsPerPixel, bool resetCursorPosition) {
clearDirtyRects();
- oldCursorRect = Common::Rect();
+ cursor.reset();
+ if (resetCursorPosition)
+ cursor.setPosition(width / 2, height / 2);
rez = -1;
mode = -1;
@@ -147,62 +145,13 @@ void Screen::addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rec
dirtyRects.clear();
dirtyRects.emplace(srcSurface.w, srcSurface.h);
- oldCursorRect = Common::Rect();
+ cursor.reset();
fullRedraw = true;
- return;
- }
-
- dirtyRects.insert(rect);
-
- if (!oldCursorRect.isEmpty()) {
- const Common::Rect alignedOldCursorRect = _manager->alignRect(oldCursorRect);
-
- // we have to check *aligned* oldCursorRect because it is background which gets copied,
- // i.e. it has to be up to date even outside the cursor rectangle.
- // do it now to avoid complex checking in updateScreenInternal()
- if (rect.contains(alignedOldCursorRect)) {
- oldCursorRect = Common::Rect();
- } else if (rect.intersects(alignedOldCursorRect)) {
- if (!directRendering) {
- _manager->copyRectToSurface(
- *offsettedSurf, _manager->getBitsPerPixel(offsettedSurf->format), srcSurface,
- alignedOldCursorRect.left, alignedOldCursorRect.top,
- alignedOldCursorRect);
- } else {
- restoreBackground(alignedOldCursorRect);
- }
-
- oldCursorRect = Common::Rect();
- }
- }
-}
-
-void Screen::storeBackground(const Common::Rect &rect) {
- const int bitsPerPixel = _manager->getBitsPerPixel(offsettedSurf->format);
+ } else {
+ dirtyRects.insert(rect);
- if (_cursorBackgroundSurf.w != rect.width()
- || _cursorBackgroundSurf.h != rect.height()
- || _cursorBackgroundSurf.format != offsettedSurf->format) {
- _cursorBackgroundSurf.create(rect.width(), rect.height(), offsettedSurf->format);
- _cursorBackgroundSurf.pitch = _cursorBackgroundSurf.pitch * bitsPerPixel / 8;
+ // do it now to avoid checking in AtariGraphicsManager::updateScreenInternal()
+ cursor.flushBackground(directRendering ? Graphics::Surface() : srcSurface, rect);
}
-
- Graphics::copyBlit(
- (byte *)_cursorBackgroundSurf.getPixels(),
- (const byte *)offsettedSurf->getPixels() + rect.top * offsettedSurf->pitch + rect.left * bitsPerPixel / 8,
- _cursorBackgroundSurf.pitch, offsettedSurf->pitch,
- rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
- offsettedSurf->format.bytesPerPixel);
-}
-
-void Screen::restoreBackground(const Common::Rect &rect) {
- const int bitsPerPixel = _manager->getBitsPerPixel(offsettedSurf->format);
-
- Graphics::copyBlit(
- (byte *)offsettedSurf->getPixels() + rect.top * offsettedSurf->pitch + rect.left * bitsPerPixel / 8,
- (const byte *)_cursorBackgroundSurf.getPixels(),
- offsettedSurf->pitch, _cursorBackgroundSurf.pitch,
- rect.width() * bitsPerPixel / 8, rect.height(), // fake 4bpp by 8bpp's width/2
- offsettedSurf->format.bytesPerPixel);
}
diff --git a/backends/graphics/atari/atari-screen.h b/backends/graphics/atari/atari-screen.h
index 7ffd188a5e7..0355f649aee 100644
--- a/backends/graphics/atari/atari-screen.h
+++ b/backends/graphics/atari/atari-screen.h
@@ -28,6 +28,8 @@
#include "common/rect.h"
#include "graphics/surface.h"
+#include "atari-cursor.h"
+
template<>
struct std::hash<Common::Rect>
{
@@ -58,7 +60,7 @@ struct Screen {
Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette);
~Screen();
- void reset(int width, int height, int bitsPerPixel);
+ void reset(int width, int height, int bitsPerPixel, bool resetCursorPosition);
// must be called before any rectangle drawing
void addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rect &rect, bool directRendering);
@@ -67,17 +69,13 @@ struct Screen {
fullRedraw = false;
}
- void storeBackground(const Common::Rect &rect);
- void restoreBackground(const Common::Rect &rect);
-
Graphics::Surface surf;
const Palette *palette;
- bool cursorPositionChanged = true;
- bool cursorSurfaceChanged = true;
- bool cursorVisibilityChanged = false;
DirtyRects dirtyRects;
bool fullRedraw = false;
- Common::Rect oldCursorRect;
+
+ Cursor cursor;
+
int rez = -1;
int mode = -1;
Graphics::Surface *const offsettedSurf = &_offsettedSurf;
@@ -103,8 +101,6 @@ private:
const AtariGraphicsManager *_manager;
Graphics::Surface _offsettedSurf;
- // used by direct rendering
- Graphics::Surface _cursorBackgroundSurf;
};
#endif // BACKENDS_GRAPHICS_ATARI_SCREEN_H
Commit: dd49c9e3ceaf7717ba1cd9cc0de7e1c7b856f89d
https://github.com/scummvm/scummvm/commit/dd49c9e3ceaf7717ba1cd9cc0de7e1c7b856f89d
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: QoL improvements
- fixed aspect ratio correction (overlay destroyed
its state, keyboard shortcut didn't always work),
as well as significantly sped it up on VGA and
SuperVidel
- smoother transitions between video modes
- reduce the number of video mode changes
- fixed a few extreme cases when triple buffering
could lose an update
- lighter ST RAM usage in the lite build
- removed hardware accessing init/deinit routines
Changed paths:
backends/graphics/atari/atari-graphics-asm.S
backends/graphics/atari/atari-graphics-asm.h
backends/graphics/atari/atari-graphics.cpp
backends/graphics/atari/atari-graphics.h
backends/graphics/atari/atari-screen.h
backends/mixer/atari/atari-mixer.cpp
backends/platform/atari/osystem_atari.cpp
backends/platform/atari/osystem_atari.h
backends/platform/atari/readme.txt
base/main.cpp
diff --git a/backends/graphics/atari/atari-graphics-asm.S b/backends/graphics/atari/atari-graphics-asm.S
index a20963db501..90a811172db 100644
--- a/backends/graphics/atari/atari-graphics-asm.S
+++ b/backends/graphics/atari/atari-graphics-asm.S
@@ -21,172 +21,11 @@
#include "../../platform/atari/symbols.h"
- .global SYM(asm_screen_tt_save)
- .global SYM(asm_screen_falcon_save)
-
- .global SYM(asm_screen_tt_restore)
- .global SYM(asm_screen_falcon_restore)
-
.global SYM(asm_draw_4bpl_sprite)
.global SYM(asm_draw_8bpl_sprite)
.text
-| extern void asm_screen_tt_save(void);
-|
-SYM(asm_screen_tt_save):
- bsr wait_vbl | avoid flickering
-
- lea 0xffff8400.w,a0
- lea save_pal,a1
- moveq #256/2-1,d0
-
-tt_save_loop:
- move.l (a0)+,(a1)+
- dbra d0,tt_save_loop
-
- lea save_video,a1
- move.l 0xffff8200.w,(a1)+ | vidhm
- move.w 0xffff820c.w,(a1)+ | vidl
- move.w 0xffff8262.w,(a1)+ | tt shifter
- rts
-
-| extern void asm_screen_falcon_save(void);
-|
-SYM(asm_screen_falcon_save):
- movem.l d2-d7/a2,-(sp)
-
- bsr wait_vbl | avoid flickering
-
- lea 0xffff9800.w,a0 | save falcon palette
- lea save_pal,a1 |
- moveq #256/2-1,d7 |
- |
-falcon_save_loop:
- move.l (a0)+,(a1)+ |
- move.l (a0)+,(a1)+ |
- dbra d7,falcon_save_loop |
-
- movem.l 0xffff8240.w,d0-d7 | save st palette
- movem.l d0-d7,(a1) |
-
- lea save_video,a0
- move.l 0xffff8200.w,(a0)+ | vidhm
- move.w 0xffff820c.w,(a0)+ | vidl
-
- move.l 0xffff8282.w,(a0)+ | h-regs
- move.l 0xffff8286.w,(a0)+ |
- move.l 0xffff828a.w,(a0)+ |
-
- move.l 0xffff82a2.w,(a0)+ | v-regs
- move.l 0xffff82a6.w,(a0)+ |
- move.l 0xffff82aa.w,(a0)+ |
-
- move.w 0xffff82c0.w,(a0)+ | vco
- move.w 0xffff82c2.w,(a0)+ | c_s
-
- move.l 0xffff820e.w,(a0)+ | offset+width
- move.w 0xffff820a.w,(a0)+ | sync
-
- move.b 0xffff8265.w,(a0)+ | p_o
-
- cmpi.w #0xb0,0xffff8282.w | st(e) / falcon test
- sle (a0)+ | it's a falcon resolution
-
- move.w 0xffff8266.w,(a0)+ | f_s
- move.w 0xffff8260.w,(a0)+ | st_s
-
- movem.l (sp)+,d2-d7/a2
- rts
-
-| extern void asm_screen_tt_restore(void);
-|
-SYM(asm_screen_tt_restore):
- bsr wait_vbl | avoid flickering
-
- lea save_video,a1
- move.l (a1)+,0xffff8200.w | vidhm
- move.w (a1)+,0xffff820c.w | vidl
- move.w (a1)+,0xffff8262.w | tt shifter
-
- lea save_pal,a0
- lea 0xffff8400.w,a1
- moveq #256/2-1,d0
-
-.loop: move.l (a0)+,(a1)+
- dbra d0,.loop
- rts
-
-| extern void asm_screen_falcon_restore(void);
-|
-SYM(asm_screen_falcon_restore):
- movem.l d2-d7/a2,-(sp)
-
- bsr wait_vbl | avoid flickering
-
- lea save_video,a0
-
- move.l (a0)+,0xffff8200.w | videobase_address:h&m
- move.w (a0)+,0xffff820c.w | l
-
- move.l (a0)+,0xffff8282.w | h-regs
- move.l (a0)+,0xffff8286.w |
- move.l (a0)+,0xffff828a.w |
-
- move.l (a0)+,0xffff82a2.w | v-regs
- move.l (a0)+,0xffff82a6.w |
- move.l (a0)+,0xffff82aa.w |
-
- move.w (a0)+,0xffff82c0.w | vco
- move.w (a0)+,0xffff82c2.w | c_s
-
- move.l (a0)+,0xffff820e.w | offset+width
- move.w (a0)+,0xffff820a.w | sync
-
- move.b (a0)+,0xffff8265.w | p_o
-
- tst.b (a0)+ | st(e) compatible mode?
- bne falcon_restore_st_comp | yes
-
-falcon_restore_falcon:
- move.l a0,-(sp)
- bsr wait_vbl | Patch to avoid
- clr.w 0xffff8266.w | monochrome sync errors
- bsr wait_vbl | (ripped from
- move.l (sp)+,a0 | FreeMiNT kernel,
- move.w (a0),0xffff8266.w | by Draco/Yescrew)
-
- bra falcon_restore_restored
-
-falcon_restore_st_comp:
- move.w (a0)+,0xffff8266.w | falcon-shift
- move.w (a0),0xffff8260.w | st-shift
- lea save_video,a0
- move.w 32(a0),0xffff82c2.w | c_s
- move.l 34(a0),0xffff820e.w | offset+width
-
-falcon_restore_restored:
- lea save_pal,a0 | restore falcon palette
- lea 0xffff9800.w,a1 |
- moveq #128-1,d7 |
- |
-falcon_restore_loop:
- move.l (a0)+,(a1)+ |
- move.l (a0)+,(a1)+ |
- dbra d7,falcon_restore_loop |
-
- movem.l (a0),d0-d7 | restore st palette
- movem.l d0-d7,0xffff8240.w |
-
- movem.l (sp)+,d2-d7/a2
- rts
-
-wait_vbl:
- move.w #0x25,-(sp) | Vsync()
- trap #14 |
- addq.l #2,sp |
- rts
-
| extern void asm_draw_4bpl_sprite(uint16 *dstBuffer, const uint16 *srcBuffer, const uint16 *srcMask,
| uint destX, uint destY, uint dstPitch, uint w, uint h);
|
@@ -206,7 +45,7 @@ SYM(asm_draw_4bpl_sprite):
| Draws a 4 bitplane sprite at any position on screen.
| (c) 1999 Pieter van der Meer (EarX)
-
+|
| INPUT: d0.w: x position of sprite on screen (left side)
| d1.w: y position of sprite on screen (top side)
| d6.w: number of 16pixel X blocks to do
diff --git a/backends/graphics/atari/atari-graphics-asm.h b/backends/graphics/atari/atari-graphics-asm.h
index 26812443583..51a8bd40900 100644
--- a/backends/graphics/atari/atari-graphics-asm.h
+++ b/backends/graphics/atari/atari-graphics-asm.h
@@ -26,24 +26,6 @@
extern "C" {
-/**
- * Save Atari TT video registers.
- */
-void asm_screen_tt_save(void);
-/**
- * Save Atari Falcon video registers.
- */
-void asm_screen_falcon_save(void);
-
-/**
- * Restore Atari TT video registers.
- */
-void asm_screen_tt_restore(void);
-/**
- * Restore Atari Falcon video registers.
- */
-void asm_screen_falcon_restore(void);
-
/**
* Copy 4bpl sprite into 4bpl buffer. Sprite's width must be multiply of 16.
*
diff --git a/backends/graphics/atari/atari-graphics.cpp b/backends/graphics/atari/atari-graphics.cpp
index 405a9ff2014..0ef2662311e 100644
--- a/backends/graphics/atari/atari-graphics.cpp
+++ b/backends/graphics/atari/atari-graphics.cpp
@@ -24,6 +24,7 @@
#include "atari-graphics.h"
#include <mint/cookie.h>
+#include <mint/falcon.h>
#include <mint/osbind.h>
#include <mint/sysvars.h>
@@ -49,18 +50,49 @@ static const Graphics::PixelFormat PIXELFORMAT_CLUT8 = Graphics::PixelFormat::cr
static const Graphics::PixelFormat PIXELFORMAT_RGB332 = Graphics::PixelFormat(1, 3, 3, 2, 0, 5, 2, 0, 0);
static const Graphics::PixelFormat PIXELFORMAT_RGB121 = Graphics::PixelFormat(1, 1, 2, 1, 0, 3, 1, 0, 0);
+static bool s_shrinkVidelVisibleArea;
+
+static void shrinkVidelVisibleArea() {
+ // Active VGA screen area consists of 960 half-lines, i.e. 480 raster lines.
+ // In case of 320x240, the number is still 480 but data is fetched
+ // only for 240 lines so it doesn't make a difference to us.
+
+ if (hasSuperVidel()) {
+ const int vOffset = ((480 - 400) / 2) * 2; // *2 because of half-lines
+
+ // VDB = VBE = VDB + paddding/2
+ *((volatile uint16*)0xFFFF82A8) = *((volatile uint16*)0xFFFF82A6) = *((volatile uint16*)0xFFFF82A8) + vOffset;
+ // VDE = VBB = VDE - padding/2
+ *((volatile uint16*)0xFFFF82AA) = *((volatile uint16*)0xFFFF82A4) = *((volatile uint16*)0xFFFF82AA) - vOffset;
+ } else {
+ // 31500/60.1 = 524 raster lines
+ // vft = 524 * 2 + 1 = 1049 half-lines
+ // 480 visible lines = 960 half-lines
+ // 1049 - 960 = 89 half-lines reserved for borders
+ // we want 400 visible lines = 800 half-lines
+ // vft = 800 + 89 = 889 half-lines in total ~ 70.1 Hz vertical frequency
+ int16 vft = *((volatile int16*)0xFFFF82A2);
+ int16 vss = *((volatile int16*)0xFFFF82AC); // vss = vft - vss_sync
+ vss -= vft; // -vss_sync
+ *((volatile int16*)0xFFFF82A2) = 889;
+ *((volatile int16*)0xFFFF82AC) = 889 + vss;
+ }
+}
+
static bool s_tt;
static int s_shakeXOffset;
static int s_shakeYOffset;
-
+static int s_aspectRatioCorrectionYOffset;
static Graphics::Surface *s_screenSurf;
+
static void VblHandler() {
if (s_screenSurf) {
#ifdef SCREEN_ACTIVE
- const int bitsPerPixel = (s_screenSurf->format == PIXELFORMAT_RGB121 ? 4 : 8);
- uintptr p = (uintptr)s_screenSurf->getBasePtr(0, MAX_V_SHAKE + s_shakeYOffset);
+ uintptr p = (uintptr)s_screenSurf->getBasePtr(0, MAX_V_SHAKE + s_shakeYOffset + s_aspectRatioCorrectionYOffset);
if (!s_tt) {
+ const int bitsPerPixel = (s_screenSurf->format == PIXELFORMAT_RGB121 ? 4 : 8);
+
s_shakeXOffset = -s_shakeXOffset;
if (s_shakeXOffset >= 0) {
@@ -85,6 +117,11 @@ static void VblHandler() {
#endif
s_screenSurf = nullptr;
}
+
+ if (s_shrinkVidelVisibleArea) {
+ shrinkVidelVisibleArea();
+ s_shrinkVidelVisibleArea = false;
+ }
}
static uint32 InstallVblHandler() {
@@ -119,50 +156,36 @@ static uint32 UninstallVblHandler() {
return uninstalled;
}
-static void shrinkVidelVisibleArea() {
- // Active VGA screen area consists of 960 half-lines, i.e. 480 raster lines.
- // In case of 320x240, the number is still 480 but data is fetched
- // only for 240 lines so it doesn't make a difference to us.
- Vsync();
-
- if (hasSuperVidel()) {
- const int vOffset = ((480 - 400) / 2) * 2; // *2 because of half-lines
-
- // VDB = VBE = VDB + paddding/2
- *((volatile uint16*)0xFFFF82A8) = *((volatile uint16*)0xFFFF82A6) = *((volatile uint16*)0xFFFF82A8) + vOffset;
- // VDE = VBB = VDE - padding/2
- *((volatile uint16*)0xFFFF82AA) = *((volatile uint16*)0xFFFF82A4) = *((volatile uint16*)0xFFFF82AA) - vOffset;
- } else {
- // 31500/60.1 = 524 raster lines
- // vft = 524 * 2 + 1 = 1049 half-lines
- // 480 visible lines = 960 half-lines
- // 1049 - 960 = 89 half-lines reserved for borders
- // we want 400 visible lines = 800 half-lines
- // vft = 800 + 89 = 889 half-lines in total ~ 70.1 Hz vertical frequency
- int16 vft = *((volatile int16*)0xFFFF82A2);
- int16 vss = *((volatile int16*)0xFFFF82AC); // vss = vft - vss_sync
- vss -= vft; // -vss_sync
- *((volatile int16*)0xFFFF82A2) = 889;
- *((volatile int16*)0xFFFF82AC) = 889 + vss;
- }
-}
-
static int s_oldRez = -1;
static int s_oldMode = -1;
static void *s_oldPhysbase = nullptr;
+static Palette s_oldPalette;
void AtariGraphicsShutdown() {
Supexec(UninstallVblHandler);
if (s_oldRez != -1) {
Setscreen(SCR_NOCHANGE, s_oldPhysbase, s_oldRez);
+
+ EsetPalette(0, s_oldPalette.entries, s_oldPalette.tt);
} else if (s_oldMode != -1) {
- // prevent setting video base address just on the VDB line
- Vsync();
- if (hasSuperVidel())
+ static _RGB black[256];
+ VsetRGB(0, 256, black);
+
+ VsetScreen(SCR_NOCHANGE, s_oldPhysbase, SCR_NOCHANGE, SCR_NOCHANGE);
+
+ if (hasSuperVidel()) {
+ // SuperVidel XBIOS does not restore those (unlike TOS/EmuTOS)
+ long ssp = Super(SUP_SET);
+ //*((volatile char *)0xFFFF8265) = 0;
+ *((volatile short *)0xFFFF820E) = 0;
+ Super(ssp);
+
VsetMode(SVEXT | SVEXT_BASERES(0) | COL80 | BPS8C); // resync to proper 640x480
+ }
VsetMode(s_oldMode);
- VsetScreen(SCR_NOCHANGE, s_oldPhysbase, SCR_NOCHANGE, SCR_NOCHANGE);
+
+ VsetRGB(0, s_oldPalette.entries, s_oldPalette.falcon);
}
}
@@ -226,12 +249,31 @@ AtariGraphicsManager::AtariGraphicsManager() {
}
}
- // although we store/restore video hardware in OSystem_Atari,
- // make sure that internal OS structures are updated correctly, too
if (_tt) {
s_oldRez = Getrez();
+ // EgetPalette / EsetPalette doesn't care about current resolution's number of colors
+ s_oldPalette.entries = 256;
+ EgetPalette(0, 256, s_oldPalette.tt);
} else {
s_oldMode = VsetMode(VM_INQUIRE);
+ switch (s_oldMode & NUMCOLS) {
+ case BPS1:
+ s_oldPalette.entries = 2;
+ break;
+ case BPS2:
+ s_oldPalette.entries = 4;
+ break;
+ case BPS4:
+ s_oldPalette.entries = 16;
+ break;
+ case BPS8:
+ case BPS8C:
+ s_oldPalette.entries = 256;
+ break;
+ default:
+ s_oldPalette.entries = 0;
+ }
+ VgetRGB(0, s_oldPalette.entries, s_oldPalette.falcon);
}
s_oldPhysbase = Physbase();
@@ -253,7 +295,7 @@ AtariGraphicsManager::~AtariGraphicsManager() {
bool AtariGraphicsManager::hasFeature(OSystem::Feature f) const {
switch (f) {
case OSystem::Feature::kFeatureAspectRatioCorrection:
- //debug("hasFeature(kFeatureAspectRatioCorrection): %d", !_vgaMonitor);
+ //debug("hasFeature(kFeatureAspectRatioCorrection): %d", !_tt);
return !_tt;
case OSystem::Feature::kFeatureCursorPalette:
// FIXME: pretend to have cursor palette at all times, this function
@@ -266,14 +308,21 @@ bool AtariGraphicsManager::hasFeature(OSystem::Feature f) const {
default:
return false;
}
+
+ // TODO: kFeatureDisplayLogFile?, kFeatureClipboardSupport, kFeatureSystemBrowserDialog
}
void AtariGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ if (!hasFeature(f))
+ return;
+
switch (f) {
case OSystem::Feature::kFeatureAspectRatioCorrection:
//debug("setFeatureState(kFeatureAspectRatioCorrection): %d", enable);
- _oldAspectRatioCorrection = _aspectRatioCorrection;
- _aspectRatioCorrection = enable;
+ _pendingState.aspectRatioCorrection = enable;
+
+ if (_currentState.aspectRatioCorrection != _pendingState.aspectRatioCorrection)
+ _pendingState.change |= GraphicsState::kAspectRatioCorrection;
break;
default:
break;
@@ -284,7 +333,7 @@ bool AtariGraphicsManager::getFeatureState(OSystem::Feature f) const {
switch (f) {
case OSystem::Feature::kFeatureAspectRatioCorrection:
//debug("getFeatureState(kFeatureAspectRatioCorrection): %d", _aspectRatioCorrection);
- return _aspectRatioCorrection;
+ return _currentState.aspectRatioCorrection;
case OSystem::Feature::kFeatureCursorPalette:
//debug("getFeatureState(kFeatureCursorPalette): %d", isOverlayVisible());
//return isOverlayVisible();
@@ -297,14 +346,13 @@ bool AtariGraphicsManager::getFeatureState(OSystem::Feature f) const {
bool AtariGraphicsManager::setGraphicsMode(int mode, uint flags) {
debug("setGraphicsMode: %d, %d", mode, flags);
- GraphicsMode graphicsMode = (GraphicsMode)mode;
+ _pendingState.mode = (GraphicsMode)mode;
- if (graphicsMode >= GraphicsMode::DirectRendering && graphicsMode <= GraphicsMode::TripleBuffering) {
- _pendingState.mode = graphicsMode;
- return true;
- }
+ if (_currentState.mode != _pendingState.mode)
+ _pendingState.change |= GraphicsState::kScreenAddress;
- return false;
+ // this doesn't seem to be checked anywhere
+ return true;
}
void AtariGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
@@ -313,10 +361,20 @@ void AtariGraphicsManager::initSize(uint width, uint height, const Graphics::Pix
_pendingState.width = width;
_pendingState.height = height;
_pendingState.format = format ? *format : PIXELFORMAT_CLUT8;
+
+ if ((_pendingState.width > 0 && _pendingState.height > 0)
+ && (_currentState.width != _pendingState.width || _currentState.height != _pendingState.height)) {
+ _pendingState.change |= GraphicsState::kVideoMode;
+ }
}
void AtariGraphicsManager::beginGFXTransaction() {
debug("beginGFXTransaction");
+
+ // these serve as a flag whether we are launching a game; if not, they will be always zeroed
+ _pendingState.width = 0;
+ _pendingState.height = 0;
+ _pendingState.change &= ~GraphicsState::kVideoMode;
}
OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
@@ -324,24 +382,42 @@ OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
int error = OSystem::TransactionError::kTransactionSuccess;
+ if (_pendingState.mode < GraphicsMode::DirectRendering || _pendingState.mode > GraphicsMode::TripleBuffering)
+ error |= OSystem::TransactionError::kTransactionModeSwitchFailed;
+
if (_pendingState.format != PIXELFORMAT_CLUT8)
error |= OSystem::TransactionError::kTransactionFormatNotSupported;
- if (_pendingState.width > getMaximumScreenWidth() || _pendingState.height > getMaximumScreenHeight())
- error |= OSystem::TransactionError::kTransactionSizeChangeFailed;
+ if (_pendingState.width > 0 && _pendingState.height > 0) {
+ if (_pendingState.width > getMaximumScreenWidth() || _pendingState.height > getMaximumScreenHeight())
+ error |= OSystem::TransactionError::kTransactionSizeChangeFailed;
- if (_pendingState.width % 16 != 0 && !hasSuperVidel()) {
- warning("Requested width not divisible by 16, please report");
- error |= OSystem::TransactionError::kTransactionSizeChangeFailed;
+ if (_pendingState.width % 16 != 0 && !hasSuperVidel()) {
+ warning("Requested width not divisible by 16, please report");
+ error |= OSystem::TransactionError::kTransactionSizeChangeFailed;
+ }
}
if (error != OSystem::TransactionError::kTransactionSuccess) {
warning("endGFXTransaction failed: %02x", (int)error);
- // all our errors are fatal but engine.cpp takes only this one seriously
+ // all our errors are fatal as we don't support rollback so make sure that
+ // initGraphicsAny() fails (note: setupGraphics() doesn't check errors at all)
error |= OSystem::TransactionError::kTransactionSizeChangeFailed;
return static_cast<OSystem::TransactionError>(error);
}
+ // don't exit overlay unless there is real video mode to be set
+ if (_pendingState.width == 0 || _pendingState.height == 0) {
+ _ignoreHideOverlay = true;
+ return OSystem::kTransactionSuccess;
+ } else if (_overlayVisible) {
+ // that's it, really. updateScreen() will take care of everything.
+ _ignoreHideOverlay = false;
+ _overlayVisible = false;
+ // if being in the overlay, reset everything (same as hideOverlay() does)
+ _pendingState.change |= GraphicsState::kAll;
+ }
+
_chunkySurface.init(_pendingState.width, _pendingState.height, _pendingState.width,
_chunkySurface.getPixels(), _pendingState.format);
@@ -350,18 +426,16 @@ OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
_screen[BACK_BUFFER2]->reset(_pendingState.width, _pendingState.height, 8, true);
_workScreen = _screen[_pendingState.mode <= GraphicsMode::SingleBuffering ? FRONT_BUFFER : BACK_BUFFER1];
- s_screenSurf = nullptr;
- s_shakeXOffset = 0;
- s_shakeYOffset = 0;
-
- // in case of resolution change from GUI
- if (_oldWorkScreen)
- _oldWorkScreen = _workScreen;
-
_palette.clear();
- _pendingScreenChange = kPendingScreenChangeMode | kPendingScreenChangeScreen | kPendingScreenChangePalette;
+ _pendingState.change |= GraphicsState::kPalette;
+ // no point of setting this in updateScreen(), it would only complicate code
_currentState = _pendingState;
+ // currently there is no use for this
+ _currentState.change = GraphicsState::kNone;
+
+ // apply new screen changes
+ updateScreen();
return OSystem::kTransactionSuccess;
}
@@ -387,7 +461,7 @@ void AtariGraphicsManager::setPalette(const byte *colors, uint start, uint num)
}
}
- _pendingScreenChange |= kPendingScreenChangePalette;
+ _pendingState.change |= GraphicsState::kPalette;
}
void AtariGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {
@@ -464,6 +538,8 @@ void AtariGraphicsManager::fillScreen(uint32 col) {
}
void AtariGraphicsManager::fillScreen(const Common::Rect &r, uint32 col) {
+ debug("fillScreen: %dx%d %d", r.width(), r.height(), col);
+
Graphics::Surface *screen = lockScreen();
if (screen)
screen->fillRect(r, col);
@@ -528,26 +604,20 @@ void AtariGraphicsManager::updateScreen() {
assert(_workScreen == _screen[BACK_BUFFER1]);
screenUpdated = updateScreenInternal(_chunkySurface);
break;
+ default:
+ warning("Unknown graphics mode %d", (int)_currentState.mode);
}
}
_workScreen->clearDirtyRects();
-#ifdef SCREEN_ACTIVE
- // first change video mode so we can modify video regs later
- if (_pendingScreenChange & kPendingScreenChangeMode) {
- if (_workScreen->rez != -1) {
- // unfortunately this reinitializes VDI, too
- Setscreen(SCR_NOCHANGE, SCR_NOCHANGE, _workScreen->rez);
- } else if (_workScreen->mode != -1) {
- VsetMode(_workScreen->mode);
- }
+ if (!_overlayPending && (_pendingState.width == 0 || _pendingState.height == 0)) {
+ return;
}
- if (_pendingScreenChange & kPendingScreenChangeScreen) {
- // calling (V)SetScreen without Vsync() is dangerous (at least on Falcon)
- s_screenSurf = isOverlayVisible() ? &_screen[OVERLAY_BUFFER]->surf : &_screen[FRONT_BUFFER]->surf;
- } else if (screenUpdated && !isOverlayVisible() && _currentState.mode == GraphicsMode::TripleBuffering) {
+ if (screenUpdated
+ && !isOverlayVisible()
+ && _currentState.mode == GraphicsMode::TripleBuffering) {
// Triple buffer:
// - alternate BACK_BUFFER1 and BACK_BUFFER2
// - check if FRONT_BUFFER has been displayed for at least one frame
@@ -585,111 +655,125 @@ void AtariGraphicsManager::updateScreen() {
// FRONT_BUFFER is displayed and still contains previously finished frame
}
- if (_pendingScreenChange & kPendingScreenChangePalette) {
- if (_tt)
- EsetPalette(0, isOverlayVisible() ? getOverlayPaletteSize() : 256, _workScreen->palette->tt);
- else
- VsetRGB(0, isOverlayVisible() ? getOverlayPaletteSize() : 256, _workScreen->palette->falcon);
+ const GraphicsState oldPendingState = _pendingState;
+ if (_overlayPending) {
+ debug("Forcing overlay pending state");
+ _pendingState.change = GraphicsState::kAll;
}
- _pendingScreenChange = kPendingScreenChangeNone;
+ bool doShrinkVidelVisibleArea = false;
+ bool doSuperVidelReset = false;
+ if (_pendingState.change & GraphicsState::kAspectRatioCorrection) {
+ assert(_workScreen->mode != -1);
- if (_oldAspectRatioCorrection != _aspectRatioCorrection) {
- if (!isOverlayVisible() && _currentState.height == 200) {
+ if (_pendingState.aspectRatioCorrection && _currentState.height == 200 && !isOverlayVisible()) {
+ // apply machine-specific aspect ratio correction
if (!_vgaMonitor) {
- short mode = VsetMode(VM_INQUIRE);
- if (_aspectRatioCorrection) {
- // 60 Hz
- mode &= ~PAL;
- mode |= NTSC;
- } else {
- // 50 Hz
- mode &= ~NTSC;
- mode |= PAL;
- }
- VsetMode(mode);
- } else if (hasSuperVidel() || !_tt) {
- if (_aspectRatioCorrection) {
- for (int screenId : { FRONT_BUFFER, BACK_BUFFER1, BACK_BUFFER2 }) {
- Screen *screen = _screen[screenId];
- Graphics::Surface *offsettedSurf = screen->offsettedSurf;
-
- // erase old screen
- offsettedSurf->fillRect(Common::Rect(offsettedSurf->w, offsettedSurf->h), 0);
-
- // setup new screen
- screen->oldScreenSurfaceWidth = screen->surf.w;
- screen->oldScreenSurfaceHeight = screen->surf.h;
- screen->oldScreenSurfacePitch = screen->surf.pitch;
- screen->oldOffsettedSurfaceWidth = offsettedSurf->w;
- screen->oldOffsettedSurfaceHeight = offsettedSurf->h;
-
- screen->surf.w = 320 + 2 * MAX_HZ_SHAKE;
- screen->surf.h = 200 + 2 * MAX_V_SHAKE;
- screen->surf.pitch = screen->surf.w;
-
- offsettedSurf->init(
- 320, 200, screen->surf.pitch,
- screen->surf.getBasePtr((screen->surf.w - 320) / 2, (screen->surf.h - 200) / 2),
- screen->surf.format);
-
- screen->addDirtyRect(*lockScreen(), Common::Rect(offsettedSurf->w, offsettedSurf->h), _currentState.mode == GraphicsMode::DirectRendering);
- }
-
- Supexec(shrinkVidelVisibleArea);
- } else {
- for (int screenId : { FRONT_BUFFER, BACK_BUFFER1, BACK_BUFFER2 }) {
- Screen *screen = _screen[screenId];
- Graphics::Surface *offsettedSurf = screen->offsettedSurf;
-
- assert(screen->oldScreenSurfaceWidth != -1);
- assert(screen->oldScreenSurfaceHeight != -1);
- assert(screen->oldScreenSurfacePitch != -1);
- assert(screen->oldOffsettedSurfaceWidth != -1);
- assert(screen->oldOffsettedSurfaceHeight != -1);
-
- // erase old screen
- offsettedSurf->fillRect(Common::Rect(offsettedSurf->w, offsettedSurf->h), 0);
-
- // setup new screen
- screen->surf.w = screen->oldScreenSurfaceWidth;
- screen->surf.h = screen->oldScreenSurfaceHeight;
- screen->surf.pitch = screen->oldScreenSurfacePitch;
-
- offsettedSurf->init(
- screen->oldOffsettedSurfaceWidth, screen->oldOffsettedSurfaceHeight, screen->surf.pitch,
- screen->surf.getBasePtr(
- (screen->surf.w - screen->oldOffsettedSurfaceWidth) / 2,
- (screen->surf.h - screen->oldOffsettedSurfaceHeight) / 2),
- screen->surf.format);
-
- screen->oldScreenSurfaceWidth = -1;
- screen->oldScreenSurfaceHeight = -1;
- screen->oldScreenSurfacePitch = -1;
- screen->oldOffsettedSurfaceWidth = -1;
- screen->oldOffsettedSurfaceHeight = -1;
-
- screen->addDirtyRect(*lockScreen(), Common::Rect(offsettedSurf->w, offsettedSurf->h), _currentState.mode == GraphicsMode::DirectRendering);
- }
-
- if (hasSuperVidel())
- VsetMode(SVEXT | SVEXT_BASERES(0) | COL80 | BPS8C); // resync to proper 640x480
- VsetMode(_workScreen->mode);
- }
+ _workScreen->mode &= ~PAL;
+ // 60 Hz
+ _workScreen->mode |= NTSC;
+ _pendingState.change |= GraphicsState::kVideoMode;
} else {
- // TODO: some tricks with TT's 480 lines?
+ Screen *screen = _screen[FRONT_BUFFER];
+ s_aspectRatioCorrectionYOffset = (screen->surf.h - 2*MAX_V_SHAKE - screen->offsettedSurf->h) / 2;
+ _pendingState.change |= GraphicsState::kShakeScreen;
+
+ if (_pendingState.change & GraphicsState::kVideoMode)
+ doShrinkVidelVisibleArea = true;
+ else
+ s_shrinkVidelVisibleArea = true;
+ }
+ } else {
+ // reset back to default mode
+ if (!_vgaMonitor) {
+ _workScreen->mode &= ~NTSC;
+ // 50 Hz
+ _workScreen->mode |= PAL;
+ _pendingState.change |= GraphicsState::kVideoMode;
+ } else {
+ s_aspectRatioCorrectionYOffset = 0;
+ s_shrinkVidelVisibleArea = false;
+
+ if (hasSuperVidel())
+ doSuperVidelReset = true;
+ _pendingState.change |= GraphicsState::kVideoMode;
+ }
+ }
+
+ _pendingState.change &= ~GraphicsState::kAspectRatioCorrection;
+ }
+
+#ifdef SCREEN_ACTIVE
+ if (_pendingState.change & GraphicsState::kVideoMode) {
+ if (_workScreen->rez != -1) {
+ // unfortunately this reinitializes VDI, too
+ Setscreen(SCR_NOCHANGE, SCR_NOCHANGE, _workScreen->rez);
+
+ // strictly speaking, this is necessary only if kScreenAddress is set but makes code easier
+ static uint16 black[256];
+ // Vsync(); // done by Setscreen() above
+ EsetPalette(0, isOverlayVisible() ? 16 : 256, black);
+ } else if (_workScreen->mode != -1) {
+ // VsetMode() must be called first: it resets all hz/v, scrolling and line width registers
+ // so even if kScreenAddress wasn't scheduled, we have to set new s_screenSurf to refresh them
+ static _RGB black[256];
+ VsetRGB(0, 256, black);
+ // Vsync(); // done by (either) VsetMode() below
+
+ if (doSuperVidelReset) {
+ VsetMode(SVEXT | SVEXT_BASERES(0) | COL80 | BPS8C); // resync to proper 640x480
+ doSuperVidelReset = false;
}
- _oldAspectRatioCorrection = _aspectRatioCorrection;
+ debug("VsetMode: %04x", _workScreen->mode);
+ VsetMode(_workScreen->mode);
+ }
+
+ // due to implied Vsync() above
+ assert(s_screenSurf == nullptr);
+
+ // refresh Videl register settings
+ s_screenSurf = isOverlayVisible() ? &_screen[OVERLAY_BUFFER]->surf : &_screen[FRONT_BUFFER]->surf;
+ s_shrinkVidelVisibleArea = doShrinkVidelVisibleArea;
- _pendingScreenChange |= kPendingScreenChangeScreen;
- updateScreen();
+ // keep kVideoMode for resetting the palette later
+ _pendingState.change &= ~(GraphicsState::kScreenAddress | GraphicsState::kShakeScreen);
+ }
+
+ if (_pendingState.change & GraphicsState::kScreenAddress) {
+ // takes effect in the nearest VBL interrupt but we always wait for Vsync() in this case
+ Vsync();
+ assert(s_screenSurf == nullptr);
+
+ s_screenSurf = isOverlayVisible() ? &_screen[OVERLAY_BUFFER]->surf : &_screen[FRONT_BUFFER]->surf;
+ _pendingState.change &= ~GraphicsState::kScreenAddress;
+ }
+
+ if (_pendingState.change & GraphicsState::kShakeScreen) {
+ // takes effect in the nearest VBL interrupt
+ if (!s_screenSurf)
+ s_screenSurf = isOverlayVisible() ? &_screen[OVERLAY_BUFFER]->surf : &_screen[FRONT_BUFFER]->surf;
+ _pendingState.change &= ~GraphicsState::kShakeScreen;
+ }
+
+ if (_pendingState.change & (GraphicsState::kVideoMode | GraphicsState::kPalette)) {
+ if (!_tt) {
+ // takes effect in the nearest VBL interrupt
+ VsetRGB(0, isOverlayVisible() ? getOverlayPaletteSize() : 256, _workScreen->palette->falcon);
} else {
- // ignore new value in overlay
- _aspectRatioCorrection = _oldAspectRatioCorrection;
+ // takes effect immediatelly (it's possible that Vsync() hasn't been called: that's expected,
+ // don't cripple framerate only for a palette change)
+ EsetPalette(0, isOverlayVisible() ? getOverlayPaletteSize() : 256, _workScreen->palette->tt);
}
+ _pendingState.change &= ~(GraphicsState::kVideoMode | GraphicsState::kPalette);
}
#endif
+
+ if (_overlayPending) {
+ _pendingState = oldPendingState;
+ _overlayPending = false;
+ }
+
//debug("end of updateScreen");
}
@@ -704,12 +788,11 @@ void AtariGraphicsManager::setShakePos(int shakeXOffset, int shakeYOffset) {
s_shakeYOffset = shakeYOffset;
}
- _pendingScreenChange |= kPendingScreenChangeScreen;
- updateScreen();
+ _pendingState.change |= GraphicsState::kShakeScreen;
}
void AtariGraphicsManager::showOverlay(bool inGUI) {
- debug("showOverlay");
+ debug("showOverlay (visible: %d)", _overlayVisible);
if (_overlayVisible)
return;
@@ -722,34 +805,38 @@ void AtariGraphicsManager::showOverlay(bool inGUI) {
_workScreen = _screen[OVERLAY_BUFFER];
// do not cache dirtyRects and oldCursorRect
- const int bitsPerPixel = getBitsPerPixel(getOverlayFormat());
- static bool resetCursorPosition = true;
- _workScreen->reset(getOverlayWidth(), getOverlayHeight(), bitsPerPixel, resetCursorPosition);
- resetCursorPosition = false;
-
- _pendingScreenChange = kPendingScreenChangeMode | kPendingScreenChangeScreen | kPendingScreenChangePalette;
+ _workScreen->reset(getOverlayWidth(), getOverlayHeight(), getBitsPerPixel(getOverlayFormat()), false);
_overlayVisible = true;
+ assert(_pendingState.change == GraphicsState::kNone);
+ _overlayPending = true;
updateScreen();
}
void AtariGraphicsManager::hideOverlay() {
- debug("hideOverlay");
+ debug("hideOverlay (ignore: %d, visible: %d)", _ignoreHideOverlay, _overlayVisible);
if (!_overlayVisible)
return;
+ if (_ignoreHideOverlay) {
+ // faster than _workScreen->reset()
+ _workScreen->clearDirtyRects();
+ _workScreen->cursor.reset();
+ return;
+ }
+
_workScreen = _oldWorkScreen;
_oldWorkScreen = nullptr;
// FIXME: perhaps there's a better way but this will do for now
_checkUnalignedPitch = true;
- _pendingScreenChange = kPendingScreenChangeMode | kPendingScreenChangeScreen | kPendingScreenChangePalette;
-
_overlayVisible = false;
+ assert(_pendingState.change == GraphicsState::kNone);
+ _pendingState.change = GraphicsState::kAll;
updateScreen();
}
@@ -935,14 +1022,36 @@ void AtariGraphicsManager::updateMousePosition(int deltaX, int deltaY) {
}
bool AtariGraphicsManager::notifyEvent(const Common::Event &event) {
- if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) {
- return false;
- }
+ switch (event.type) {
+ case Common::EVENT_RETURN_TO_LAUNCHER:
+ case Common::EVENT_QUIT:
+ if (isOverlayVisible()) {
+ _ignoreHideOverlay = true;
+ return false;
+ }
+ break;
- switch ((CustomEventAction) event.customType) {
- case kActionToggleAspectRatioCorrection:
- _aspectRatioCorrection = !_aspectRatioCorrection;
- return true;
+ case Common::EVENT_CUSTOM_BACKEND_ACTION_START:
+ switch ((CustomEventAction) event.customType) {
+ case kActionToggleAspectRatioCorrection:
+ if (hasFeature(OSystem::Feature::kFeatureAspectRatioCorrection)) {
+ _pendingState.aspectRatioCorrection = !_pendingState.aspectRatioCorrection;
+
+ if (_currentState.aspectRatioCorrection != _pendingState.aspectRatioCorrection) {
+ _pendingState.change |= GraphicsState::kAspectRatioCorrection;
+
+ // would be updated in updateScreen() anyway
+ _currentState.aspectRatioCorrection = _pendingState.aspectRatioCorrection;
+ updateScreen();
+ }
+ return true;
+ }
+ break;
+ }
+ break;
+
+ default:
+ return false;
}
return false;
@@ -967,7 +1076,9 @@ void AtariGraphicsManager::allocateSurfaces() {
_screen[i] = new Screen(this, getMaximumScreenWidth(), getMaximumScreenHeight(), PIXELFORMAT_CLUT8, &_palette);
}
- _screen[OVERLAY_BUFFER] = new Screen(this, getOverlayWidth(), getOverlayHeight(), getOverlayFormat(), &_overlayPalette);
+ // overlay is the default screen upon start
+ _workScreen = _screen[OVERLAY_BUFFER] = new Screen(this, getOverlayWidth(), getOverlayHeight(), getOverlayFormat(), &_overlayPalette);
+ _workScreen->reset(getOverlayWidth(), getOverlayHeight(), getBitsPerPixel(getOverlayFormat()), true);
_chunkySurface.create(getMaximumScreenWidth(), getMaximumScreenHeight(), PIXELFORMAT_CLUT8);
_overlaySurface.create(getOverlayWidth(), getOverlayHeight(), getOverlayFormat());
diff --git a/backends/graphics/atari/atari-graphics.h b/backends/graphics/atari/atari-graphics.h
index 4bc238a01c2..36c6066d678 100644
--- a/backends/graphics/atari/atari-graphics.h
+++ b/backends/graphics/atari/atari-graphics.h
@@ -112,12 +112,24 @@ protected:
void freeSurfaces();
private:
+ enum class GraphicsMode : int {
+ Unknown = -1,
+ DirectRendering = 0,
+ SingleBuffering = 1,
+ TripleBuffering = 3
+ };
+
enum CustomEventAction {
kActionToggleAspectRatioCorrection = 100,
};
+#ifndef DISABLE_FANCY_THEMES
int16 getMaximumScreenHeight() const { return 480; }
int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 640 : 640*1.2); }
+#else
+ int16 getMaximumScreenHeight() const { return _tt ? 480 : 240; }
+ int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 320 : 320*1.2); }
+#endif
bool updateScreenInternal(const Graphics::Surface &srcSurface);
@@ -162,38 +174,28 @@ private:
bool _vgaMonitor = true;
bool _tt = false;
- bool _aspectRatioCorrection = false;
- bool _oldAspectRatioCorrection = false;
bool _checkUnalignedPitch = false;
- enum class GraphicsMode : int {
- DirectRendering = 0,
- SingleBuffering = 1,
- TripleBuffering = 3
- };
-
struct GraphicsState {
- GraphicsState(GraphicsMode mode_)
- : mode(mode_)
- , width(0)
- , height(0) {
- }
-
- GraphicsMode mode;
- int width;
- int height;
+ GraphicsMode mode = GraphicsMode::Unknown;
+ int width = 0;
+ int height = 0;
Graphics::PixelFormat format;
+ bool aspectRatioCorrection = false;
+
+ enum PendingScreenChange {
+ kNone = 0,
+ kVideoMode = 1<<0,
+ kScreenAddress = 1<<1,
+ kPalette = 1<<2,
+ kAspectRatioCorrection = 1<<3,
+ kShakeScreen = 1<<4,
+ kAll = kVideoMode | kScreenAddress | kPalette | kAspectRatioCorrection | kShakeScreen,
+ };
+ int change = kNone;
};
- GraphicsState _pendingState{ (GraphicsMode)getDefaultGraphicsMode() };
- GraphicsState _currentState{ (GraphicsMode)getDefaultGraphicsMode() };
-
- enum PendingScreenChange {
- kPendingScreenChangeNone = 0,
- kPendingScreenChangeMode = 1<<0,
- kPendingScreenChangeScreen = 1<<1,
- kPendingScreenChangePalette = 1<<2
- };
- int _pendingScreenChange = kPendingScreenChangeNone;
+ GraphicsState _pendingState;
+ GraphicsState _currentState;
enum {
FRONT_BUFFER,
@@ -208,7 +210,9 @@ private:
Graphics::Surface _chunkySurface;
- bool _overlayVisible = false;
+ bool _overlayVisible = true;
+ bool _overlayPending = true;
+ bool _ignoreHideOverlay = true;
Graphics::Surface _overlaySurface;
Palette _palette;
diff --git a/backends/graphics/atari/atari-screen.h b/backends/graphics/atari/atari-screen.h
index 0355f649aee..abf1b156f7c 100644
--- a/backends/graphics/atari/atari-screen.h
+++ b/backends/graphics/atari/atari-screen.h
@@ -45,11 +45,14 @@ class Palette {
public:
void clear() {
memset(data, 0, sizeof(data));
+ entries = 0;
}
uint16 *const tt = reinterpret_cast<uint16*>(data);
_RGB *const falcon = reinterpret_cast<_RGB*>(data);
+ int entries = 0;
+
private:
byte data[256*4] = {};
};
@@ -80,12 +83,6 @@ struct Screen {
int mode = -1;
Graphics::Surface *const offsettedSurf = &_offsettedSurf;
- int oldScreenSurfaceWidth = -1;
- int oldScreenSurfaceHeight = -1;
- int oldScreenSurfacePitch = -1;
- int oldOffsettedSurfaceWidth = -1;
- int oldOffsettedSurfaceHeight = -1;
-
private:
static constexpr size_t ALIGN = 16; // 16 bytes
diff --git a/backends/mixer/atari/atari-mixer.cpp b/backends/mixer/atari/atari-mixer.cpp
index 7647e5acbb7..e7eae85fd91 100644
--- a/backends/mixer/atari/atari-mixer.cpp
+++ b/backends/mixer/atari/atari-mixer.cpp
@@ -25,13 +25,11 @@
#include <mint/falcon.h>
#include <mint/osbind.h>
#include <mint/ostruct.h>
+#include <usound.h> // https://github.com/mikrosk/usound
#include "common/config-manager.h"
#include "common/debug.h"
-// see https://github.com/mikrosk/atari_sound_setup
-#include "../../../../atari_sound_setup.git/atari_sound_setup.h"
-
#define DEFAULT_OUTPUT_RATE 24585
#define DEFAULT_OUTPUT_CHANNELS 2
#define DEFAULT_SAMPLES 2048 // 83ms
diff --git a/backends/platform/atari/osystem_atari.cpp b/backends/platform/atari/osystem_atari.cpp
index 5b3a9cd7ec0..59e3fa01506 100644
--- a/backends/platform/atari/osystem_atari.cpp
+++ b/backends/platform/atari/osystem_atari.cpp
@@ -59,6 +59,8 @@
#include "base/main.h"
#include "gui/debugger.h"
+#define INPUT_ACTIVE
+
/*
* Include header files needed for the getFilesystemFactory() method.
*/
@@ -77,7 +79,6 @@ extern "C" volatile uint32 counter_200hz;
extern void nf_init(void);
extern void nf_print(const char* msg);
-static bool s_tt = false;
static int s_app_id = -1;
static bool exit_already_called = false;
@@ -89,12 +90,9 @@ static void critical_restore() {
AtariAudioShutdown();
AtariGraphicsShutdown();
- if (s_tt)
- Supexec(asm_screen_tt_restore);
- else
- Supexec(asm_screen_falcon_restore);
Supexec(atari_200hz_shutdown);
+#ifdef INPUT_ACTIVE
if (atari_old_kbdvec && atari_old_mousevec) {
_KBDVECS *kbdvecs = Kbdvbase();
((uintptr *)kbdvecs)[-1] = (uintptr)atari_old_kbdvec;
@@ -110,6 +108,7 @@ static void critical_restore() {
// ok, restore mouse cursor at least
graf_mouse(M_ON, NULL);
}
+#endif
}
// called on normal program termination (via exit() or returning from main())
@@ -141,8 +140,6 @@ OSystem_Atari::OSystem_Atari() {
exit(EXIT_FAILURE);
}
- s_tt = (vdo == VDO_TT);
-
enum {
MCH_ST = 0,
MCH_STE,
@@ -161,23 +158,18 @@ OSystem_Atari::OSystem_Atari() {
exit(EXIT_FAILURE);
}
+#ifdef INPUT_ACTIVE
_KBDVECS *kbdvecs = Kbdvbase();
atari_old_kbdvec = (KBDVEC)(((uintptr *)kbdvecs)[-1]);
atari_old_mousevec = kbdvecs->mousevec;
((uintptr *)kbdvecs)[-1] = (uintptr)atari_kbdvec;
kbdvecs->mousevec = atari_mousevec;
+#endif
Supexec(atari_200hz_init);
_timerInitialized = true;
- if (s_tt)
- Supexec(asm_screen_tt_save);
- else
- Supexec(asm_screen_falcon_save);
-
- _videoInitialized = true;
-
// protect against sudden exit()
atexit(exit_restore);
// protect against sudden crash
@@ -210,16 +202,6 @@ OSystem_Atari::~OSystem_Atari() {
delete _fsFactory;
_fsFactory = nullptr;
- if (_videoInitialized) {
- if (s_tt)
- Supexec(asm_screen_tt_restore);
- else {
- Supexec(asm_screen_falcon_restore);
- }
-
- _videoInitialized = false;
- }
-
if (_timerInitialized) {
Supexec(atari_200hz_shutdown);
_timerInitialized = false;
@@ -273,9 +255,11 @@ void OSystem_Atari::initBackend() {
_vdi_width = work_out[0] + 1;
_vdi_height = work_out[1] + 1;
+#ifdef INPUT_ACTIVE
graf_mouse(M_OFF, NULL);
// see https://github.com/freemint/freemint/issues/312
//wind_update(BEG_UPDATE);
+#endif
}
_timerManager = new DefaultTimerManager();
diff --git a/backends/platform/atari/osystem_atari.h b/backends/platform/atari/osystem_atari.h
index 2afc60b97b2..6f428a64859 100644
--- a/backends/platform/atari/osystem_atari.h
+++ b/backends/platform/atari/osystem_atari.h
@@ -51,7 +51,6 @@ public:
private:
long _startTime;
- bool _videoInitialized = false;
bool _timerInitialized = false;
int16 _vdi_handle;
diff --git a/backends/platform/atari/readme.txt b/backends/platform/atari/readme.txt
index fbc49f7de70..4081e2128fc 100644
--- a/backends/platform/atari/readme.txt
+++ b/backends/platform/atari/readme.txt
@@ -305,11 +305,6 @@ Yes, it's a hack. :) Owners of a CRT monitor can achieve the same effect by the
analog knobs -- stretch and move the 320x200 picture unless black borders are no
longer visible. This hack provides a more elegant and per-game functionality.
-Realtime aspect ratio correction (CTRL+ALT+a) should be used with caution in
-Direct rendering mode because there's no way to refresh the screen. So if you
-change the setting and there isn't any game screen update coming, screen will
-stay black.
-
Audio mixing
------------
diff --git a/base/main.cpp b/base/main.cpp
index 65e9cf34a2b..04cc2a02d9c 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -347,7 +347,7 @@ static void setupGraphics(OSystem &system) {
system.setScaler(ConfMan.get("scaler").c_str(), ConfMan.getInt("scale_factor"));
system.setShader(ConfMan.getPath("shader"));
-#if defined(OPENDINGUX) || defined(MIYOO) || defined(MIYOOMINI)
+#if defined(OPENDINGUX) || defined(MIYOO) || defined(MIYOOMINI) || defined(ATARI)
// 0, 0 means "autodetect" but currently only SDL supports
// it and really useful only on Opendingux. When more platforms
// support it we will switch to it.
Commit: 4c98561eec488fe229542e70bd9968bda9eb3628
https://github.com/scummvm/scummvm/commit/4c98561eec488fe229542e70bd9968bda9eb3628
Author: Thorsten Otto (admin at tho-otto.de)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: Move timer interrupt to ossystem_atari.cpp
Changed paths:
R backends/platform/atari/atari_200hz.S
backends/platform/atari/module.mk
backends/platform/atari/osystem_atari.cpp
diff --git a/backends/platform/atari/atari_200hz.S b/backends/platform/atari/atari_200hz.S
deleted file mode 100644
index cec28f10c34..00000000000
--- a/backends/platform/atari/atari_200hz.S
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
-*
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
- #include "symbols.h"
-
- .globl SYM(atari_200hz_init)
- .globl SYM(atari_200hz_shutdown)
-
- .globl SYM(counter_200hz)
-
- .text
-
-SYM(atari_200hz_init):
- move sr,-(sp)
- or #0x700,sr
-
- move.l 0x114.w,old_200hz
- move.l #my_200hz,0x114.w
-
- move (sp)+,sr
- rts
-
-SYM(atari_200hz_shutdown):
- move sr,-(sp)
- or #0x700,sr
-
- move.l old_200hz,0x114.w
-
- move (sp)+,sr
- rts
-
- .ascii "XBRA"
- .ascii "SCUM"
-old_200hz:
- dc.l 0
-my_200hz:
- addq.l #1,SYM(counter_200hz)
-
- move.l old_200hz,-(sp)
- rts
-
-
- .bss
- .even
-
-SYM(counter_200hz):
- ds.l 1
diff --git a/backends/platform/atari/module.mk b/backends/platform/atari/module.mk
index ea1882a0480..015ae50f7eb 100644
--- a/backends/platform/atari/module.mk
+++ b/backends/platform/atari/module.mk
@@ -2,7 +2,6 @@ MODULE := backends/platform/atari
MODULE_OBJS := \
osystem_atari.o \
- atari_200hz.o \
atari_ikbd.o \
native_features.o \
dlmalloc.o
diff --git a/backends/platform/atari/osystem_atari.cpp b/backends/platform/atari/osystem_atari.cpp
index 59e3fa01506..3617b1b3f2f 100644
--- a/backends/platform/atari/osystem_atari.cpp
+++ b/backends/platform/atari/osystem_atari.cpp
@@ -72,17 +72,60 @@ typedef void (*KBDVEC)(void *);
extern "C" KBDVEC atari_old_kbdvec;
extern "C" KBDVEC atari_old_mousevec;
-extern "C" void atari_200hz_init();
-extern "C" void atari_200hz_shutdown();
-extern "C" volatile uint32 counter_200hz;
-
extern void nf_init(void);
extern void nf_print(const char* msg);
static int s_app_id = -1;
+static volatile uint32 counter_200hz;
+
static bool exit_already_called = false;
+static long atari_200hz_init(void)
+{
+ __asm__ __volatile__(
+ "\tmove %%sr,-(%%sp)\n"
+ "\tor.w #0x700,%%sr\n"
+
+ "\tmove.l 0x114.w,old_200hz\n"
+ "\tmove.l #my_200hz,0x114.w\n"
+
+ "\tmove (%%sp)+,%%sr\n"
+ "\tjbra 1f\n"
+
+ "\tdc.l 0x58425241\n" /* "XBRA" */
+ "\tdc.l 0x5343554d\n" /* "SCUM" */
+"old_200hz:\n"
+ "\tdc.l 0\n"
+"my_200hz:\n"
+ "\taddq.l #1,%0\n"
+
+ "\tmove.l old_200hz(%%pc),-(%%sp)\n"
+ "\trts\n"
+"1:\n"
+ : /* output */
+ : "m"(counter_200hz) /* inputs */
+ : "memory", "cc");
+
+ return 0;
+}
+
+static long atari_200hz_shutdown(void)
+{
+ __asm__ __volatile__(
+ "\tmove %%sr,-(%%sp)\n"
+ "\tor.w #0x700,%%sr\n"
+
+ "\tmove.l old_200hz,0x114.w\n"
+
+ "\tmove (%%sp)+,%%sr\n"
+ : /* output */
+ : /* inputs */
+ : "memory", "cc");
+
+ return 0;
+}
+
static void critical_restore() {
extern void AtariAudioShutdown();
extern void AtariGraphicsShutdown();
Commit: 7dabb755dd526269c2b75b3e1a4b4b16947ff642
https://github.com/scummvm/scummvm/commit/7dabb755dd526269c2b75b3e1a4b4b16947ff642
Author: Thorsten Otto (admin at tho-otto.de)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: Fixes to build scripts
Changed paths:
backends/platform/atari/build-release.sh
backends/platform/atari/build-release030.sh
diff --git a/backends/platform/atari/build-release.sh b/backends/platform/atari/build-release.sh
index dbbd47ea15c..72261e46278 100755
--- a/backends/platform/atari/build-release.sh
+++ b/backends/platform/atari/build-release.sh
@@ -10,7 +10,7 @@ PLATFORM=m68k-atari-mintelf
export ASFLAGS="-m68020-60"
export CXXFLAGS="-m68020-60 -DUSE_MOVE16 -DUSE_SUPERVIDEL -DUSE_SV_BLITTER"
-export LDFLAGS="-m68020-60"
+export LDFLAGS="-m68020-60 -Wl,--msuper-memory"
export PKG_CONFIG_LIBDIR="$(${PLATFORM}-gcc -print-sysroot)/usr/lib/m68020-60/pkgconfig"
if [ ! -f config.log ]
@@ -37,13 +37,10 @@ then
--disable-detection-full
fi
-make -j 16
+make -j$(getconf _NPROCESSORS_CONF)
rm -rf dist-generic
make dist-generic
-# make memory protection friendly
-${PLATFORM}-flags -S dist-generic/scummvm/scummvm.ttp
-
# create symbol file and strip
${PLATFORM}-nm -C dist-generic/scummvm/scummvm.ttp | grep -vF ' .L' | grep ' [TtWV] ' | ${PLATFORM}-c++filt | sort -u > dist-generic/scummvm/scummvm.sym
${PLATFORM}-strip -s dist-generic/scummvm/scummvm.ttp
diff --git a/backends/platform/atari/build-release030.sh b/backends/platform/atari/build-release030.sh
index a94d4254714..2502bc7e9f0 100755
--- a/backends/platform/atari/build-release030.sh
+++ b/backends/platform/atari/build-release030.sh
@@ -10,7 +10,7 @@ PLATFORM=m68k-atari-mintelf
export ASFLAGS="-m68030"
export CXXFLAGS="-m68030 -DDISABLE_FANCY_THEMES"
-export LDFLAGS="-m68030"
+export LDFLAGS="-m68030 -Wl,--msuper-memory"
export PKG_CONFIG_LIBDIR="$(${PLATFORM}-gcc -print-sysroot)/usr/lib/m68020-60/pkgconfig"
if [ ! -f config.log ]
@@ -39,13 +39,10 @@ then
--disable-detection-full
fi
-make -j 16
+make -j$(getconf _NPROCESSORS_CONF)
rm -rf dist-generic
make dist-generic
-# make memory protection friendly
-${PLATFORM}-flags -S dist-generic/scummvm/scummvm.ttp
-
# create symbol file and strip
${PLATFORM}-nm -C dist-generic/scummvm/scummvm.ttp | grep -vF ' .L' | grep ' [TtWV] ' | ${PLATFORM}-c++filt | sort -u > dist-generic/scummvm/scummvm.sym
${PLATFORM}-strip -s dist-generic/scummvm/scummvm.ttp
Commit: 30670e0a46b234808d8e44f4978f4afd0e2bea20
https://github.com/scummvm/scummvm/commit/30670e0a46b234808d8e44f4978f4afd0e2bea20
Author: Thorsten Otto (admin at tho-otto.de)
Date: 2024-07-15T19:42:51+02:00
Commit Message:
BACKENDS: ATARI: Add support for -mfastcall
Changed paths:
backends/graphics/atari/atari-c2p-asm.S
backends/graphics/atari/atari-graphics-asm.S
backends/platform/atari/build-release.sh
backends/platform/atari/build-release030.sh
diff --git a/backends/graphics/atari/atari-c2p-asm.S b/backends/graphics/atari/atari-c2p-asm.S
index 2da584648e8..14135025c7a 100644
--- a/backends/graphics/atari/atari-c2p-asm.S
+++ b/backends/graphics/atari/atari-c2p-asm.S
@@ -35,9 +35,15 @@
| void asm_c2p1x1_8(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
SYM(asm_c2p1x1_8):
+#ifdef __FASTCALL__
+ | a0: chunky
+ move.l a1,d0 | chunky end
+ move.l 4(sp),a1 | screen
+#else
move.l (4,sp),a0 | chunky
move.l (8,sp),d0 | chunky end
move.l (12,sp),a1 | screen
+#endif
movem.l d2-d7/a2-a6,-(sp)
move.l d0,a2
move.l #0x0f0f0f0f,d4
@@ -234,10 +240,17 @@ c2p1x1_8_start:
SYM(asm_c2p1x1_8_tt):
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
+#ifdef __FASTCALL__
+ | a0: chunky
+ move.l a1,a2 | a2: chunky end
+ move.l (11*4+4,sp),a1 | a1: screen
+ | d0.l: screen pitch (double width)
+#else
move.l (11*4+4,sp),a0 | a0: chunky
move.l (11*4+8,sp),a2 | a2: chunky end
move.l (11*4+12,sp),a1 | a1: screen
move.l (11*4+16,sp),d0 | d0.l: screen pitch (double width)
+#endif
move.l sp,old_sp
@@ -449,12 +462,21 @@ c2p1x1_8_tt_start:
SYM(asm_c2p1x1_8_rect):
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
+#ifdef __FASTCALL__
+ | a0: chunky
+ move.l a1,chunky_end
+ | d0.l: chunky width
+ move.l (11*4+4,sp),a1 | a1: screen
+ exg d1,d2 | d2.l: chunky pitch
+ | d1.l: screen pitch
+#else
move.l (11*4+4,sp),a0 | a0: chunky
move.l (11*4+8,sp),chunky_end
move.l (11*4+12,sp),d0 | d0.l: chunky width
move.l (11*4+16,sp),d2 | d2.l: chunky pitch
move.l (11*4+20,sp),a1 | a1: screen
move.l (11*4+24,sp),d1 | d1.l: screen pitch
+#endif
move.l sp,old_sp
@@ -679,9 +701,15 @@ c2p1x1_8_rect_done:
| void asm_c2p1x1_4(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
SYM(asm_c2p1x1_4):
+#ifdef __FASTCALL__
+ | a0: chunky
+ move.l a1,d0 | chunky end
+ move.l 4(sp),a1 | screen
+#else
move.l (4,sp),a0 | chunky
move.l (8,sp),d0 | chunky end
move.l (12,sp),a1 | screen
+#endif
movem.l d2-d7/a2-a6,-(sp)
move.l d0,a2
move.l #0x0f0f0f0f,d4
@@ -785,12 +813,21 @@ c2p1x1_4_start:
SYM(asm_c2p1x1_4_rect):
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
+#ifdef __FASTCALL__
+ | a0: chunky
+ move.l a1,chunky_end
+ | d0.l: chunky width
+ move.l (11*4+4,sp),a1 | a1: screen
+ exg d1,d2 | d2.l: chunky pitch
+ | d1.l: screen pitch
+#else
move.l (11*4+4,sp),a0 | a0: chunky
move.l (11*4+8,sp),chunky_end
move.l (11*4+12,sp),d0 | d0.l: chunky width
move.l (11*4+16,sp),d2 | d2.l: chunky pitch
move.l (11*4+20,sp),a1 | a1: screen
move.l (11*4+24,sp),d1 | d1.l: screen pitch
+#endif
move.l sp,old_sp
diff --git a/backends/graphics/atari/atari-graphics-asm.S b/backends/graphics/atari/atari-graphics-asm.S
index 90a811172db..8534876d7ae 100644
--- a/backends/graphics/atari/atari-graphics-asm.S
+++ b/backends/graphics/atari/atari-graphics-asm.S
@@ -32,6 +32,18 @@
SYM(asm_draw_4bpl_sprite):
movem.l d0-d7/a0-a2,-(sp) | 11 longs
+#ifdef __FASTCALL__
+ move.l a0,a2 | a2: dstBuffer
+ | a1: srcBuffer
+ move.l (4+11*4,sp),a0 | a0: srcMask
+ | d0.w: destX
+ | d1.w: destY
+ move.l d2,d3 | d3.w: dstPitch
+ ext.l d3 | d3.l: dstPitch
+ move.l (8+11*4,sp),d6 | d6.w: w
+ lsr.w #4,d6 | d6.w: w/16
+ move.l (12+11*4,sp),d7 | d7.w: h
+#else
move.l (4+11*4,sp),a2 | a2: dstBuffer
move.l (8+11*4,sp),a1 | a1: srcBuffer
move.l (12+11*4,sp),a0 | a0: srcMask
@@ -42,6 +54,7 @@ SYM(asm_draw_4bpl_sprite):
move.l (28+11*4,sp),d6 | d6.w: w
lsr.w #4,d6 | d6.w: w/16
move.l (32+11*4,sp),d7 | d7.w: h
+#endif
| Draws a 4 bitplane sprite at any position on screen.
| (c) 1999 Pieter van der Meer (EarX)
@@ -130,6 +143,18 @@ sprite4_xloop:
SYM(asm_draw_8bpl_sprite):
movem.l d0-d7/a0-a2,-(sp) | 11 longs
+#ifdef __FASTCALL__
+ move.l a0,a2 | a2: dstBuffer
+ | a1: srcBuffer
+ move.l (4+11*4,sp),a0 | a0: srcMask
+ | d0.w: destX
+ | d1.w: destY
+ move.l d2,d3 | d3.w: dstPitch
+ ext.l d3 | d3.l: dstPitch
+ move.l (8+11*4,sp),d6 | d6.w: w
+ lsr.w #4,d6 | d6.w: w/16
+ move.l (12+11*4,sp),d7 | d7.w: h
+#else
move.l (4+11*4,sp),a2 | a2: dstBuffer
move.l (8+11*4,sp),a1 | a1: srcBuffer
move.l (12+11*4,sp),a0 | a0: srcMask
@@ -140,6 +165,7 @@ SYM(asm_draw_8bpl_sprite):
move.l (28+11*4,sp),d6 | d6.w: w
lsr.w #4,d6 | d6.w: w/16
move.l (32+11*4,sp),d7 | d7.w: h
+#endif
move.w d0,d2 | / Calculate the
andi.w #0b111111110000,d0 | | number of bits
diff --git a/backends/platform/atari/build-release.sh b/backends/platform/atari/build-release.sh
index 72261e46278..4f6d14e075a 100755
--- a/backends/platform/atari/build-release.sh
+++ b/backends/platform/atari/build-release.sh
@@ -7,12 +7,20 @@ mkdir -p build-release
cd build-release
PLATFORM=m68k-atari-mintelf
+FASTCALL=false
export ASFLAGS="-m68020-60"
export CXXFLAGS="-m68020-60 -DUSE_MOVE16 -DUSE_SUPERVIDEL -DUSE_SV_BLITTER"
export LDFLAGS="-m68020-60 -Wl,--msuper-memory"
export PKG_CONFIG_LIBDIR="$(${PLATFORM}-gcc -print-sysroot)/usr/lib/m68020-60/pkgconfig"
+if $FASTCALL
+then
+ ASFLAGS="$ASFLAGS -mfastcall"
+ CXXFLAGS="$CXXFLAGS -mfastcall"
+ LDFLAGS="$LDFLAGS -mfastcall"
+fi
+
if [ ! -f config.log ]
then
../configure \
diff --git a/backends/platform/atari/build-release030.sh b/backends/platform/atari/build-release030.sh
index 2502bc7e9f0..d08b1b943fb 100755
--- a/backends/platform/atari/build-release030.sh
+++ b/backends/platform/atari/build-release030.sh
@@ -7,12 +7,20 @@ mkdir -p build-release030
cd build-release030
PLATFORM=m68k-atari-mintelf
+FASTCALL=false
export ASFLAGS="-m68030"
export CXXFLAGS="-m68030 -DDISABLE_FANCY_THEMES"
export LDFLAGS="-m68030 -Wl,--msuper-memory"
export PKG_CONFIG_LIBDIR="$(${PLATFORM}-gcc -print-sysroot)/usr/lib/m68020-60/pkgconfig"
+if $FASTCALL
+then
+ ASFLAGS="$ASFLAGS -mfastcall"
+ CXXFLAGS="$CXXFLAGS -mfastcall"
+ LDFLAGS="$LDFLAGS -mfastcall"
+fi
+
if [ ! -f config.log ]
then
../configure \
More information about the Scummvm-git-logs
mailing list