aboutsummaryrefslogtreecommitdiff
path: root/engines/agi/graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/agi/graphics.cpp')
-rw-r--r--engines/agi/graphics.cpp1701
1 files changed, 666 insertions, 1035 deletions
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index b46e6f726c..e9ae1295e9 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -23,773 +23,739 @@
#include "common/config-manager.h"
#include "common/file.h"
#include "common/textconsole.h"
+#include "engines/util.h"
#include "graphics/cursorman.h"
#include "graphics/palette.h"
#include "agi/agi.h"
#include "agi/graphics.h"
+#include "agi/mouse_cursor.h"
+#include "agi/palette.h"
+#include "agi/picture.h"
+#include "agi/text.h"
namespace Agi {
-#define DEV_X0(x) ((x) << 1)
-#define DEV_X1(x) (((x) << 1) + 1)
-#define DEV_Y(x) (x)
+#include "agi/font.h"
-#ifndef MAX_INT
-# define MAX_INT (int)((unsigned)~0 >> 1)
-#endif
+GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
+ _agipalFileNum = 0;
-#include "agi/font.h"
+ memset(&_paletteGfxMode, 0, sizeof(_paletteGfxMode));
+ memset(&_paletteTextMode, 0, sizeof(_paletteTextMode));
-/**
- * 16 color RGB palette.
- * This array contains the 6-bit RGB values of the EGA palette exported
- * to the console drivers.
- */
-static const uint8 egaPalette[16 * 3] = {
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x2a,
- 0x00, 0x2a, 0x00,
- 0x00, 0x2a, 0x2a,
- 0x2a, 0x00, 0x00,
- 0x2a, 0x00, 0x2a,
- 0x2a, 0x15, 0x00,
- 0x2a, 0x2a, 0x2a,
- 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x3f,
- 0x15, 0x3f, 0x15,
- 0x15, 0x3f, 0x3f,
- 0x3f, 0x15, 0x15,
- 0x3f, 0x15, 0x3f,
- 0x3f, 0x3f, 0x15,
- 0x3f, 0x3f, 0x3f
-};
+ memset(&_mouseCursor, 0, sizeof(_mouseCursor));
+ memset(&_mouseCursorBusy, 0, sizeof(_mouseCursorBusy));
-/**
- * Atari ST AGI palette.
- * Used by all of the tested Atari ST AGI games
- * from Donald Duck's Playground (1986) to Manhunter II (1989).
- * 16 RGB colors. 3 bits per color component.
- */
-#if 0
-static const uint8 atariStAgiPalette[16 * 3] = {
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x7,
- 0x0, 0x4, 0x0,
- 0x0, 0x5, 0x4,
- 0x5, 0x0, 0x0,
- 0x5, 0x3, 0x6,
- 0x4, 0x3, 0x0,
- 0x5, 0x5, 0x5,
- 0x3, 0x3, 0x2,
- 0x0, 0x5, 0x7,
- 0x0, 0x6, 0x0,
- 0x0, 0x7, 0x6,
- 0x7, 0x2, 0x3,
- 0x7, 0x4, 0x7,
- 0x7, 0x7, 0x4,
- 0x7, 0x7, 0x7
-};
-#endif
+ initPriorityTable();
-/**
- * Second generation Apple IIGS AGI palette.
- * A 16-color, 12-bit RGB palette.
- *
- * Used by at least the following Apple IIGS AGI versions:
- * 1.003 (Leisure Suit Larry I v1.0E, intro says 1987)
- * 1.005 (AGI Demo 2 1987-06-30?)
- * 1.006 (King's Quest I v1.0S 1988-02-23)
- * 1.007 (Police Quest I v2.0B 1988-04-21 8:00am)
- * 1.013 (King's Quest II v2.0A 1988-06-16 (CE))
- * 1.013 (Mixed-Up Mother Goose v2.0A 1988-05-31 10:00am)
- * 1.014 (King's Quest III v2.0A 1988-08-28 (CE))
- * 1.014 (Space Quest II v2.0A, LOGIC.141 says 1988)
- * 2.004 (Manhunter I v2.0E 1988-10-05 (CE))
- * 2.006 (King's Quest IV v1.0K 1988-11-22 (CE))
- * 3.001 (Black Cauldron v1.0O 1989-02-24 (CE))
- * 3.003 (Gold Rush! v1.0M 1989-02-28 (CE))
- */
-#if 0
-// FIXME: Identical to amigaAgiPaletteV2
-static const uint8 appleIIgsAgiPaletteV2[16 * 3] = {
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0xF,
- 0x0, 0x8, 0x0,
- 0x0, 0xD, 0xB,
- 0xC, 0x0, 0x0,
- 0xB, 0x7, 0xD,
- 0x8, 0x5, 0x0,
- 0xB, 0xB, 0xB,
- 0x7, 0x7, 0x7,
- 0x0, 0xB, 0xF,
- 0x0, 0xE, 0x0,
- 0x0, 0xF, 0xD,
- 0xF, 0x9, 0x8,
- 0xD, 0x9, 0xF, // Only this differs from the 1st generation palette
- 0xE, 0xE, 0x0,
- 0xF, 0xF, 0xF
-};
-#endif
+ _renderStartOffsetY = 0;
+}
/**
- * First generation Amiga & Apple IIGS AGI palette.
- * A 16-color, 12-bit RGB palette.
- *
- * Used by at least the following Amiga AGI versions:
- * 2.082 (King's Quest I v1.0U 1986)
- * 2.082 (Space Quest I v1.2 1986)
- * 2.090 (King's Quest III v1.01 1986-11-08)
- * 2.107 (King's Quest II v2.0J 1987-01-29)
- * x.yyy (Black Cauldron v2.00 1987-06-14)
- * x.yyy (Larry I v1.05 1987-06-26)
+ * Initialize graphics device.
*
- * Also used by at least the following Apple IIGS AGI versions:
- * 1.002 (Space Quest I, intro says v2.2 1987)
+ * @see deinit_video()
*/
-static const uint8 amigaAgiPaletteV1[16 * 3] = {
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0xF,
- 0x0, 0x8, 0x0,
- 0x0, 0xD, 0xB,
- 0xC, 0x0, 0x0,
- 0xB, 0x7, 0xD,
- 0x8, 0x5, 0x0,
- 0xB, 0xB, 0xB,
- 0x7, 0x7, 0x7,
- 0x0, 0xB, 0xF,
- 0x0, 0xE, 0x0,
- 0x0, 0xF, 0xD,
- 0xF, 0x9, 0x8,
- 0xF, 0x7, 0x0,
- 0xE, 0xE, 0x0,
- 0xF, 0xF, 0xF
-};
+int GfxMgr::initVideo() {
+ // Set up palettes
+ initPalette(_paletteTextMode, PALETTE_EGA);
+
+ switch (_vm->_renderMode) {
+ case RENDERMODE_EGA:
+ initPalette(_paletteGfxMode, PALETTE_EGA);
+ break;
+ case RENDERMODE_CGA:
+ initPalette(_paletteGfxMode, PALETTE_CGA, 4, 8);
+ break;
+ case RENDERMODE_VGA:
+ initPalette(_paletteGfxMode, PALETTE_VGA, 256, 8);
+ break;
+ case RENDERMODE_AMIGA:
+ if (!ConfMan.getBool("altamigapalette")) {
+ // Set the correct Amiga palette depending on AGI interpreter version
+ if (_vm->getVersion() < 0x2936)
+ initPalette(_paletteGfxMode, PALETTE_AMIGA_V1, 16, 4);
+ else if (_vm->getVersion() == 0x2936)
+ initPalette(_paletteGfxMode, PALETTE_AMIGA_V2, 16, 4);
+ else if (_vm->getVersion() > 0x2936)
+ initPalette(_paletteGfxMode, PALETTE_AMIGA_V3, 16, 4);
+ } else {
+ // Set the old common alternative Amiga palette
+ initPalette(_paletteGfxMode, PALETTE_AMIGA_ALT);
+ }
+ break;
+ case RENDERMODE_APPLE_II_GS:
+ initPalette(_paletteGfxMode, PALETTE_APPLE_II_GS, 16, 4);
+ break;
+ case RENDERMODE_ATARI_ST:
+ initPalette(_paletteGfxMode, PALETTE_ATARI_ST, 16, 3);
+ break;
+ default:
+ error("initVideo: unsupported render mode");
+ break;
+ }
-/**
- * Second generation Amiga AGI palette.
- * A 16-color, 12-bit RGB palette.
- *
- * Used by at least the following Amiga AGI versions:
- * 2.202 (Space Quest II v2.0F. Intro says 1988. ScummVM 0.10.0 detects as 1986-12-09)
- */
-static const uint8 amigaAgiPaletteV2[16 * 3] = {
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0xF,
- 0x0, 0x8, 0x0,
- 0x0, 0xD, 0xB,
- 0xC, 0x0, 0x0,
- 0xB, 0x7, 0xD,
- 0x8, 0x5, 0x0,
- 0xB, 0xB, 0xB,
- 0x7, 0x7, 0x7,
- 0x0, 0xB, 0xF,
- 0x0, 0xE, 0x0,
- 0x0, 0xF, 0xD,
- 0xF, 0x9, 0x8,
- 0xD, 0x0, 0xF,
- 0xE, 0xE, 0x0,
- 0xF, 0xF, 0xF
-};
+ // set up mouse cursors
+ switch (_vm->_renderMode) {
+ case RENDERMODE_EGA:
+ case RENDERMODE_CGA:
+ case RENDERMODE_VGA:
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_SCI, 11, 16, 1, 1);
+ initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
+ break;
+ case RENDERMODE_AMIGA:
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_AMIGA, 8, 11, 1, 1);
+ initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_AMIGA_BUSY, 13, 16, 7, 8);
+ break;
+ case RENDERMODE_APPLE_II_GS:
+ // had no special busy mouse cursor
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_APPLE_II_GS, 9, 11, 1, 1);
+ initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
+ break;
+ case RENDERMODE_ATARI_ST:
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 1, 1);
+ initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
+ break;
+ default:
+ error("initVideo: unsupported render mode");
+ break;
+ }
-/**
- * Third generation Amiga AGI palette.
- * A 16-color, 12-bit RGB palette.
- *
- * Used by at least the following Amiga AGI versions:
- * 2.310 (Police Quest I v2.0B 1989-02-22)
- * 2.316 (Gold Rush! v2.05 1989-03-09)
- * x.yyy (Manhunter I v1.06 1989-03-18)
- * 2.333 (Manhunter II v3.06 1989-08-17)
- * 2.333 (King's Quest III v2.15 1989-11-15)
- */
-static const uint8 amigaAgiPaletteV3[16 * 3] = {
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0xB,
- 0x0, 0xB, 0x0,
- 0x0, 0xB, 0xB,
- 0xB, 0x0, 0x0,
- 0xB, 0x0, 0xB,
- 0xC, 0x7, 0x0,
- 0xB, 0xB, 0xB,
- 0x7, 0x7, 0x7,
- 0x0, 0x0, 0xF,
- 0x0, 0xF, 0x0,
- 0x0, 0xF, 0xF,
- 0xF, 0x0, 0x0,
- 0xF, 0x0, 0xF,
- 0xF, 0xF, 0x0,
- 0xF, 0xF, 0xF
-};
+ _pixels = SCRIPT_WIDTH * SCRIPT_HEIGHT;
+ _visualScreen = (byte *)calloc(_pixels, 1);
+ _priorityScreen = (byte *)calloc(_pixels, 1);
+ _activeScreen = _visualScreen;
+ //_activeScreen = _priorityScreen;
-/**
- * 16 color amiga-ish palette.
- */
-static const uint8 altAmigaPalette[16 * 3] = {
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x3f,
- 0x00, 0x2A, 0x00,
- 0x00, 0x2A, 0x2A,
- 0x33, 0x00, 0x00,
- 0x2f, 0x1c, 0x37,
- 0x23, 0x14, 0x00,
- 0x2f, 0x2f, 0x2f,
- 0x15, 0x15, 0x15,
- 0x00, 0x2f, 0x3f,
- 0x00, 0x33, 0x15,
- 0x15, 0x3F, 0x3F,
- 0x3f, 0x27, 0x23,
- 0x3f, 0x15, 0x3f,
- 0x3b, 0x3b, 0x00,
- 0x3F, 0x3F, 0x3F
-};
+ _displayPixels = DISPLAY_WIDTH * DISPLAY_HEIGHT;
+ _displayScreen = (byte *)calloc(_displayPixels, 1);
+
+ initGraphics(DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_WIDTH > 320);
+
+ setPalette(true); // set gfx-mode palette
+
+ // set up mouse cursor palette
+ CursorMan.replaceCursorPalette(MOUSECURSOR_PALETTE, 1, ARRAYSIZE(MOUSECURSOR_PALETTE) / 3);
+ setMouseCursor();
+
+ return errOK;
+}
/**
- * 256 color palette used with AGI256 and AGI256-2 games.
- * Uses full 8 bits per color component.
+ * Deinitialize graphics device.
+ *
+ * @see init_video()
*/
-static const uint8 vgaPalette[256 * 3] = {
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xA8,
- 0x00, 0xA8, 0x00,
- 0x00, 0xA8, 0xA8,
- 0xA8, 0x00, 0x00,
- 0xA8, 0x00, 0xA8,
- 0xA8, 0x54, 0x00,
- 0xA8, 0xA8, 0xA8,
- 0x54, 0x54, 0x54,
- 0x54, 0x54, 0xFC,
- 0x54, 0xFC, 0x54,
- 0x54, 0xFC, 0xFC,
- 0xFC, 0x54, 0x54,
- 0xFC, 0x54, 0xFC,
- 0xFC, 0xFC, 0x54,
- 0xFC, 0xFC, 0xFC,
- 0x00, 0x00, 0x00,
- 0x14, 0x14, 0x14,
- 0x20, 0x20, 0x20,
- 0x2C, 0x2C, 0x2C,
- 0x38, 0x38, 0x38,
- 0x44, 0x44, 0x44,
- 0x50, 0x50, 0x50,
- 0x60, 0x60, 0x60,
- 0x70, 0x70, 0x70,
- 0x80, 0x80, 0x80,
- 0x90, 0x90, 0x90,
- 0xA0, 0xA0, 0xA0,
- 0xB4, 0xB4, 0xB4,
- 0xC8, 0xC8, 0xC8,
- 0xE0, 0xE0, 0xE0,
- 0xFC, 0xFC, 0xFC,
- 0x00, 0x00, 0xFC,
- 0x40, 0x00, 0xFC,
- 0x7C, 0x00, 0xFC,
- 0xBC, 0x00, 0xFC,
- 0xFC, 0x00, 0xFC,
- 0xFC, 0x00, 0xBC,
- 0xFC, 0x00, 0x7C,
- 0xFC, 0x00, 0x40,
- 0xFC, 0x00, 0x00,
- 0xFC, 0x40, 0x00,
- 0xFC, 0x7C, 0x00,
- 0xFC, 0xBC, 0x00,
- 0xFC, 0xFC, 0x00,
- 0xBC, 0xFC, 0x00,
- 0x7C, 0xFC, 0x00,
- 0x40, 0xFC, 0x00,
- 0x00, 0xFC, 0x00,
- 0x00, 0xFC, 0x40,
- 0x00, 0xFC, 0x7C,
- 0x00, 0xFC, 0xBC,
- 0x00, 0xFC, 0xFC,
- 0x00, 0xBC, 0xFC,
- 0x00, 0x7C, 0xFC,
- 0x00, 0x40, 0xFC,
- 0x7C, 0x7C, 0xFC,
- 0x9C, 0x7C, 0xFC,
- 0xBC, 0x7C, 0xFC,
- 0xDC, 0x7C, 0xFC,
- 0xFC, 0x7C, 0xFC,
- 0xFC, 0x7C, 0xDC,
- 0xFC, 0x7C, 0xBC,
- 0xFC, 0x7C, 0x9C,
- 0xFC, 0x7C, 0x7C,
- 0xFC, 0x9C, 0x7C,
- 0xFC, 0xBC, 0x7C,
- 0xFC, 0xDC, 0x7C,
- 0xFC, 0xFC, 0x7C,
- 0xDC, 0xFC, 0x7C,
- 0xBC, 0xFC, 0x7C,
- 0x9C, 0xFC, 0x7C,
- 0x7C, 0xFC, 0x7C,
- 0x7C, 0xFC, 0x9C,
- 0x7C, 0xFC, 0xBC,
- 0x7C, 0xFC, 0xDC,
- 0x7C, 0xFC, 0xFC,
- 0x7C, 0xDC, 0xFC,
- 0x7C, 0xBC, 0xFC,
- 0x7C, 0x9C, 0xFC,
- 0xB4, 0xB4, 0xFC,
- 0xC4, 0xB4, 0xFC,
- 0xD8, 0xB4, 0xFC,
- 0xE8, 0xB4, 0xFC,
- 0xFC, 0xB4, 0xFC,
- 0xFC, 0xB4, 0xE8,
- 0xFC, 0xB4, 0xD8,
- 0xFC, 0xB4, 0xC4,
- 0xFC, 0xB4, 0xB4,
- 0xFC, 0xC4, 0xB4,
- 0xFC, 0xD8, 0xB4,
- 0xFC, 0xE8, 0xB4,
- 0xFC, 0xFC, 0xB4,
- 0xE8, 0xFC, 0xB4,
- 0xD8, 0xFC, 0xB4,
- 0xC4, 0xFC, 0xB4,
- 0xB4, 0xFC, 0xB4,
- 0xB4, 0xFC, 0xC4,
- 0xB4, 0xFC, 0xD8,
- 0xB4, 0xFC, 0xE8,
- 0xB4, 0xFC, 0xFC,
- 0xB4, 0xE8, 0xFC,
- 0xB4, 0xD8, 0xFC,
- 0xB4, 0xC4, 0xFC,
- 0x00, 0x00, 0x70,
- 0x1C, 0x00, 0x70,
- 0x38, 0x00, 0x70,
- 0x54, 0x00, 0x70,
- 0x70, 0x00, 0x70,
- 0x70, 0x00, 0x54,
- 0x70, 0x00, 0x38,
- 0x70, 0x00, 0x1C,
- 0x70, 0x00, 0x00,
- 0x70, 0x1C, 0x00,
- 0x70, 0x38, 0x00,
- 0x70, 0x54, 0x00,
- 0x70, 0x70, 0x00,
- 0x54, 0x70, 0x00,
- 0x38, 0x70, 0x00,
- 0x1C, 0x70, 0x00,
- 0x00, 0x70, 0x00,
- 0x00, 0x70, 0x1C,
- 0x00, 0x70, 0x38,
- 0x00, 0x70, 0x54,
- 0x00, 0x70, 0x70,
- 0x00, 0x54, 0x70,
- 0x00, 0x38, 0x70,
- 0x00, 0x1C, 0x70,
- 0x38, 0x38, 0x70,
- 0x44, 0x38, 0x70,
- 0x54, 0x38, 0x70,
- 0x60, 0x38, 0x70,
- 0x70, 0x38, 0x70,
- 0x70, 0x38, 0x60,
- 0x70, 0x38, 0x54,
- 0x70, 0x38, 0x44,
- 0x70, 0x38, 0x38,
- 0x70, 0x44, 0x38,
- 0x70, 0x54, 0x38,
- 0x70, 0x60, 0x38,
- 0x70, 0x70, 0x38,
- 0x60, 0x70, 0x38,
- 0x54, 0x70, 0x38,
- 0x44, 0x70, 0x38,
- 0x38, 0x70, 0x38,
- 0x38, 0x70, 0x44,
- 0x38, 0x70, 0x54,
- 0x38, 0x70, 0x60,
- 0x38, 0x70, 0x70,
- 0x38, 0x60, 0x70,
- 0x38, 0x54, 0x70,
- 0x38, 0x44, 0x70,
- 0x50, 0x50, 0x70,
- 0x58, 0x50, 0x70,
- 0x60, 0x50, 0x70,
- 0x68, 0x50, 0x70,
- 0x70, 0x50, 0x70,
- 0x70, 0x50, 0x68,
- 0x70, 0x50, 0x60,
- 0x70, 0x50, 0x58,
- 0x70, 0x50, 0x50,
- 0x70, 0x58, 0x50,
- 0x70, 0x60, 0x50,
- 0x70, 0x68, 0x50,
- 0x70, 0x70, 0x50,
- 0x68, 0x70, 0x50,
- 0x60, 0x70, 0x50,
- 0x58, 0x70, 0x50,
- 0x50, 0x70, 0x50,
- 0x50, 0x70, 0x58,
- 0x50, 0x70, 0x60,
- 0x50, 0x70, 0x68,
- 0x50, 0x70, 0x70,
- 0x50, 0x68, 0x70,
- 0x50, 0x60, 0x70,
- 0x50, 0x58, 0x70,
- 0x00, 0x00, 0x40,
- 0x10, 0x00, 0x40,
- 0x20, 0x00, 0x40,
- 0x30, 0x00, 0x40,
- 0x40, 0x00, 0x40,
- 0x40, 0x00, 0x30,
- 0x40, 0x00, 0x20,
- 0x40, 0x00, 0x10,
- 0x40, 0x00, 0x00,
- 0x40, 0x10, 0x00,
- 0x40, 0x20, 0x00,
- 0x40, 0x30, 0x00,
- 0x40, 0x40, 0x00,
- 0x30, 0x40, 0x00,
- 0x20, 0x40, 0x00,
- 0x10, 0x40, 0x00,
- 0x00, 0x40, 0x00,
- 0x00, 0x40, 0x10,
- 0x00, 0x40, 0x20,
- 0x00, 0x40, 0x30,
- 0x00, 0x40, 0x40,
- 0x00, 0x30, 0x40,
- 0x00, 0x20, 0x40,
- 0x00, 0x10, 0x40,
- 0x20, 0x20, 0x40,
- 0x28, 0x20, 0x40,
- 0x30, 0x20, 0x40,
- 0x38, 0x20, 0x40,
- 0x40, 0x20, 0x40,
- 0x40, 0x20, 0x38,
- 0x40, 0x20, 0x30,
- 0x40, 0x20, 0x28,
- 0x40, 0x20, 0x20,
- 0x40, 0x28, 0x20,
- 0x40, 0x30, 0x20,
- 0x40, 0x38, 0x20,
- 0x40, 0x40, 0x20,
- 0x38, 0x40, 0x20,
- 0x30, 0x40, 0x20,
- 0x28, 0x40, 0x20,
- 0x20, 0x40, 0x20,
- 0x20, 0x40, 0x28,
- 0x20, 0x40, 0x30,
- 0x20, 0x40, 0x38,
- 0x20, 0x40, 0x40,
- 0x20, 0x38, 0x40,
- 0x20, 0x30, 0x40,
- 0x20, 0x28, 0x40,
- 0x2C, 0x2C, 0x40,
- 0x30, 0x2C, 0x40,
- 0x34, 0x2C, 0x40,
- 0x3C, 0x2C, 0x40,
- 0x40, 0x2C, 0x40,
- 0x40, 0x2C, 0x3C,
- 0x40, 0x2C, 0x34,
- 0x40, 0x2C, 0x30,
- 0x40, 0x2C, 0x2C,
- 0x40, 0x30, 0x2C,
- 0x40, 0x34, 0x2C,
- 0x40, 0x3C, 0x2C,
- 0x40, 0x40, 0x2C,
- 0x3C, 0x40, 0x2C,
- 0x34, 0x40, 0x2C,
- 0x30, 0x40, 0x2C,
- 0x2C, 0x40, 0x2C,
- 0x2C, 0x40, 0x30,
- 0x2C, 0x40, 0x34,
- 0x2C, 0x40, 0x3C,
- 0x2C, 0x40, 0x40,
- 0x2C, 0x3C, 0x40,
- 0x2C, 0x34, 0x40,
- 0x2C, 0x30, 0x40,
- 0x40, 0x40, 0x40,
- 0x38, 0x38, 0x38,
- 0x30, 0x30, 0x30,
- 0x28, 0x28, 0x28,
- 0x24, 0x24, 0x24,
- 0x1C, 0x1C, 0x1C,
- 0x14, 0x14, 0x14,
- 0x0C, 0x0C, 0x0C
-};
+int GfxMgr::deinitVideo() {
+ free(_displayScreen);
+ free(_visualScreen);
+ free(_priorityScreen);
-static const uint16 cgaMap[16] = {
- 0x0000, // 0 - black
- 0x0d00, // 1 - blue
- 0x0b00, // 2 - green
- 0x0f00, // 3 - cyan
- 0x000b, // 4 - red
- 0x0b0d, // 5 - magenta
- 0x000d, // 6 - brown
- 0x0b0b, // 7 - gray
- 0x0d0d, // 8 - dark gray
- 0x0b0f, // 9 - light blue
- 0x0b0d, // 10 - light green
- 0x0f0d, // 11 - light cyan
- 0x0f0d, // 12 - light red
- 0x0f00, // 13 - light magenta
- 0x0f0b, // 14 - yellow
- 0x0f0f // 15 - white
-};
+ return errOK;
+}
-struct UpdateBlock {
- int x1, y1;
- int x2, y2;
-};
+int GfxMgr::initMachine() {
+ _vm->_clockCount = 0;
-static struct UpdateBlock update = {
- MAX_INT, MAX_INT, 0, 0
-};
+ return errOK;
+}
-GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
- _shakeH = NULL;
- _shakeV = NULL;
- _agipalFileNum = 0;
- _currentCursorPalette = 0; // cursor palette not set
+int GfxMgr::deinitMachine() {
+ return errOK;
}
+void GfxMgr::setRenderStartOffset(uint16 offsetY) {
+ if (offsetY >= (DISPLAY_HEIGHT - SCRIPT_HEIGHT))
+ error("invalid render start offset");
-//
-// Layer 4: 640x480? ================== User display
-// ^
-// | do_update(), put_block()
-// |
-// Layer 3: 640x480? ================== Framebuffer
-// ^
-// | flush_block(), put_pixels()
-// |
-// Layer 2: 320x200 ================== AGI engine screen (console), put_pixel()
-// |
-// Layer 1: 160x336 ================== AGI screen
-//
-// Upper half (160x168) of Layer 1 is for the normal 16 color & control line/priority info.
-// Lower half (160x168) of Layer 1 is for the 256 color information (Used with AGI256 & AGI256-2).
-//
-
-#define SHAKE_MAG 3
-
-void GfxMgr::shakeStart() {
- int i;
-
- if ((_shakeH = (uint8 *)malloc(GFX_WIDTH * SHAKE_MAG)) == NULL)
- return;
+ _renderStartOffsetY = offsetY;
+}
- if ((_shakeV = (uint8 *)malloc(SHAKE_MAG * (GFX_HEIGHT - SHAKE_MAG))) == NULL) {
- free(_shakeH);
- return;
+void GfxMgr::debugShowMap(int mapNr) {
+ switch (mapNr) {
+ case 0:
+ _activeScreen = _visualScreen;
+ break;
+ case 1:
+ _activeScreen = _priorityScreen;
+ break;
+ default:
+ break;
}
- for (i = 0; i < GFX_HEIGHT - SHAKE_MAG; i++) {
- memcpy(_shakeV + i * SHAKE_MAG, _agiScreen + i * GFX_WIDTH, SHAKE_MAG);
+ render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
+}
+
+void GfxMgr::clear(byte color, byte priority) {
+ memset(_visualScreen, color, _pixels);
+ memset(_priorityScreen, priority, _pixels);
+}
+
+void GfxMgr::clearDisplay(byte color, bool copyToScreen) {
+ memset(_displayScreen, color, _displayPixels);
+
+ if (copyToScreen) {
+ g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
}
+}
+
+void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority) {
+ int offset = y * SCRIPT_WIDTH + x;
- for (i = 0; i < SHAKE_MAG; i++) {
- memcpy(_shakeH + i * GFX_WIDTH, _agiScreen + i * GFX_WIDTH, GFX_WIDTH);
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ _visualScreen[offset] = color;
+ }
+ if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
+ _priorityScreen[offset] = priority;
}
}
-void GfxMgr::shakeScreen(int n) {
- int i;
+void GfxMgr::putPixelOnDisplay(int16 x, int16 y, byte color) {
+ int offset = y * DISPLAY_WIDTH + x;
- if (n == 0) {
- for (i = 0; i < (GFX_HEIGHT - SHAKE_MAG); i++) {
- memmove(&_agiScreen[GFX_WIDTH * i],
- &_agiScreen[GFX_WIDTH * (i + SHAKE_MAG) + SHAKE_MAG],
- GFX_WIDTH - SHAKE_MAG);
- }
- } else {
- for (i = GFX_HEIGHT - SHAKE_MAG - 1; i >= 0; i--) {
- memmove(&_agiScreen[GFX_WIDTH * (i + SHAKE_MAG) + SHAKE_MAG],
- &_agiScreen[GFX_WIDTH * i], GFX_WIDTH - SHAKE_MAG);
+ _displayScreen[offset] = color;
+}
+
+byte GfxMgr::getColor(int16 x, int16 y) {
+ int offset = y * SCRIPT_WIDTH + x;
+
+ return _visualScreen[offset];
+}
+
+byte GfxMgr::getPriority(int16 x, int16 y) {
+ int offset = y * SCRIPT_WIDTH + x;
+
+ return _priorityScreen[offset];
+}
+
+// used, when a control pixel is found
+// will search downwards and compare priority in case any is found
+bool GfxMgr::checkControlPixel(int16 x, int16 y, byte viewPriority) {
+ int offset = y * SCRIPT_WIDTH + x;
+ byte curPriority;
+
+ while (1) {
+ y++;
+ offset += SCRIPT_WIDTH;
+ if (y >= SCRIPT_HEIGHT) {
+ // end of screen, nothing but control pixels found
+ return true; // draw view pixel
}
+ curPriority = _priorityScreen[offset];
+ if (curPriority > 2) // valid priority found?
+ break;
+ }
+ if (curPriority <= viewPriority)
+ return true; // view priority is higher, draw
+ return false; // view priority is lower, don't draw
+}
+
+static byte CGA_MixtureColorTable[] = {
+ 0x00, 0x08, 0x04, 0x0C, 0x01, 0x09, 0x02, 0x05,
+ 0x0A, 0x0D, 0x06, 0x0E, 0x0B, 0x03, 0x07, 0x0F
+};
+
+byte GfxMgr::getCGAMixtureColor(byte color) {
+ return CGA_MixtureColorTable[color & 0x0F];
+}
+
+// Attention: y-coordinate points to the LOWER left!
+void GfxMgr::render_Block(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
+ if (!render_Clip(x, y, width, height))
+ return;
+
+ switch (_vm->_renderMode) {
+ case RENDERMODE_CGA:
+ render_BlockCGA(x, y, width, height, copyToScreen);
+ break;
+ case RENDERMODE_EGA:
+ default:
+ render_BlockEGA(x, y, width, height, copyToScreen);
+ break;
+ }
+
+ if (copyToScreen) {
+ int16 upperY = y - height + 1 + _renderStartOffsetY;
+ g_system->copyRectToScreen(_displayScreen + upperY * DISPLAY_WIDTH + x * 2, DISPLAY_WIDTH, x * 2, upperY, width * 2, height);
}
}
-void GfxMgr::shakeEnd() {
- int i;
+bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16 clipAgainstWidth, int16 clipAgainstHeight) {
+ if ((x >= clipAgainstWidth) || ((x + width - 1) < 0) ||
+ (y < 0) || ((y - (height - 1)) >= clipAgainstHeight)) {
+ return false;
+ }
+
+ if ((y - height + 1) < 0)
+ height = y + 1;
- for (i = 0; i < GFX_HEIGHT - SHAKE_MAG; i++) {
- memcpy(_agiScreen + i * GFX_WIDTH, _shakeV + i * SHAKE_MAG, SHAKE_MAG);
+ if (y >= clipAgainstHeight) {
+ height -= y - (clipAgainstHeight - 1);
+ y = clipAgainstHeight - 1;
}
- for (i = 0; i < SHAKE_MAG; i++) {
- memcpy(_agiScreen + i * GFX_WIDTH, _shakeH + i * GFX_WIDTH, GFX_WIDTH);
+ if (x < 0) {
+ width += x;
+ x = 0;
}
- flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
+ if ((x + width - 1) >= clipAgainstWidth) {
+ width = clipAgainstWidth - x;
+ }
+ return true;
+}
+
+void GfxMgr::render_BlockEGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
+ int offsetVisual = SCRIPT_WIDTH * y + x;
+ int offsetDisplay = (DISPLAY_WIDTH * (y + _renderStartOffsetY)) + x * 2;
+ int16 remainingWidth = width;
+ int16 remainingHeight = height;
+ byte curColor = 0;
+
+ while (remainingHeight) {
+ remainingWidth = width;
+ while (remainingWidth) {
+ curColor = _activeScreen[offsetVisual++];
+ _displayScreen[offsetDisplay++] = curColor;
+ _displayScreen[offsetDisplay++] = curColor;
+ remainingWidth--;
+ }
+ offsetVisual -= SCRIPT_WIDTH + width;
+ offsetDisplay -= DISPLAY_WIDTH + width * 2;
- free(_shakeV);
- free(_shakeH);
+ remainingHeight--;
+ }
}
-void GfxMgr::putTextCharacter(int l, int x, int y, unsigned char c, int fg, int bg, bool checkerboard, const uint8 *font) {
- int x1, y1, xx, yy, cc;
- const uint8 *p;
+void GfxMgr::render_BlockCGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
+ int offsetVisual = SCRIPT_WIDTH * y + x;
+ int offsetDisplay = (DISPLAY_WIDTH * (y + _renderStartOffsetY)) + x * 2;
+ int16 remainingWidth = width;
+ int16 remainingHeight = height;
+ byte curColor = 0;
+
+ while (remainingHeight) {
+ remainingWidth = width;
+ while (remainingWidth) {
+ curColor = _activeScreen[offsetVisual++];
+ _displayScreen[offsetDisplay++] = curColor & 0x03; // we process CGA mixture
+ _displayScreen[offsetDisplay++] = curColor >> 2;
+ remainingWidth--;
+ }
+ offsetVisual -= SCRIPT_WIDTH + width;
+ offsetDisplay -= DISPLAY_WIDTH + width * 2;
+
+ remainingHeight--;
+ }
+}
- assert(font);
+void GfxMgr::transition_Amiga() {
+ uint16 screenPos = 1;
+ uint16 screenStepPos = 1;
+ int16 posY = 0, posX = 0;
+ int16 stepCount = 0;
+
+ // disable mouse while transition is taking place
+ if (_vm->_game.mouseEnabled) {
+ CursorMan.showMouse(false);
+ }
+
+ do {
+ if (screenPos & 1) {
+ screenPos = screenPos >> 1;
+ screenPos = screenPos ^ 0x3500; // 13568d
+ } else {
+ screenPos = screenPos >> 1;
+ }
- p = font + ((unsigned int)c * CHAR_LINES);
- for (y1 = 0; y1 < CHAR_LINES; y1++) {
- for (x1 = 0; x1 < CHAR_COLS; x1++) {
- xx = x + x1;
- yy = y + y1;
- cc = (*p & (1 << (7 - x1))) ? fg : bg;
- _agiScreen[xx + yy * GFX_WIDTH] = cc;
+ if ((screenPos < 13440) && (screenPos & 1)) {
+ screenStepPos = screenPos >> 1;
+ posY = screenStepPos / SCRIPT_WIDTH;
+ posX = screenStepPos - (posY * SCRIPT_WIDTH);
+
+ posY += _renderStartOffsetY; // adjust to only update the main area, not the status bar
+ posX *= 2; // adjust for display screen
+
+ screenStepPos = (screenStepPos * 2) + (_renderStartOffsetY * DISPLAY_WIDTH); // adjust here too for display screen
+ for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
+ g_system->copyRectToScreen(_displayScreen + screenStepPos, DISPLAY_WIDTH, posX, posY, 2, 1);
+ screenStepPos += (0x1A40 * 2); // 6720d
+ posY += 42;
+ }
+ stepCount++;
+ if (stepCount == 220) {
+ // 30 times for the whole transition, so should take around 0.5 seconds
+ g_system->updateScreen();
+ g_system->delayMillis(16);
+ stepCount = 0;
+ }
}
+ } while (screenPos != 1);
- p++;
+ // Enable mouse again
+ if (_vm->_game.mouseEnabled) {
+ CursorMan.showMouse(true);
}
- // Simple checkerboard effect to simulate "greyed out" text.
- // This is what Sierra's interpreter does for things like menu items
- // that aren't selectable (such as separators). -- dsymonds
- if (checkerboard) {
- for (yy = y; yy < y + CHAR_LINES; yy++)
- for (xx = x + (~yy & 1); xx < x + CHAR_COLS; xx += 2)
- _agiScreen[xx + yy * GFX_WIDTH] = 15;
+ g_system->updateScreen();
+}
+
+// This transition code was not reverse engineered, but created based on the Amiga transition code
+// Atari ST definitely had a hi-res transition using the full resolution unlike the Amiga transition.
+void GfxMgr::transition_AtariSt() {
+ uint16 screenPos = 1;
+ uint16 screenStepPos = 1;
+ int16 posY = 0, posX = 0;
+ int16 stepCount = 0;
+
+ // disable mouse while transition is taking place
+ if (_vm->_game.mouseEnabled) {
+ CursorMan.showMouse(false);
+ }
+
+ do {
+ if (screenPos & 1) {
+ screenPos = screenPos >> 1;
+ screenPos = screenPos ^ 0x3500; // 13568d
+ } else {
+ screenPos = screenPos >> 1;
+ }
+
+ if ((screenPos < 13440) && (screenPos & 1)) {
+ screenStepPos = screenPos >> 1;
+ posY = screenStepPos / DISPLAY_WIDTH;
+ posX = screenStepPos - (posY * DISPLAY_WIDTH);
+
+ posY += _renderStartOffsetY; // adjust to only update the main area, not the status bar
+
+ screenStepPos = screenStepPos + (_renderStartOffsetY * DISPLAY_WIDTH); // adjust here too for display screen
+ for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
+ g_system->copyRectToScreen(_displayScreen + screenStepPos, DISPLAY_WIDTH, posX, posY, 1, 1);
+ screenStepPos += 0x1a40; // 6720d
+ posY += 21;
+ }
+ stepCount++;
+ if (stepCount == 168) {
+ // 40 times for the whole transition, so should take around 0.7 seconds
+ // When using an Atari ST emulator, the transition seems to be even slower than this
+ // TODO: should get checked on real hardware
+ g_system->updateScreen();
+ g_system->delayMillis(16);
+ stepCount = 0;
+ }
+ }
+ } while (screenPos != 1);
+
+ // Enable mouse again
+ if (_vm->_game.mouseEnabled) {
+ CursorMan.showMouse(true);
}
- // FIXME: we don't want this when we're writing on the
- // console!
- flushBlock(x, y, x + CHAR_COLS - 1, y + CHAR_LINES - 1);
+ g_system->updateScreen();
}
-void GfxMgr::drawRectangle(int x1, int y1, int x2, int y2, int c) {
- int y, w, h;
- uint8 *p0;
-
- if (x1 >= GFX_WIDTH)
- x1 = GFX_WIDTH - 1;
- if (y1 >= GFX_HEIGHT)
- y1 = GFX_HEIGHT - 1;
- if (x2 >= GFX_WIDTH)
- x2 = GFX_WIDTH - 1;
- if (y2 >= GFX_HEIGHT)
- y2 = GFX_HEIGHT - 1;
-
- w = x2 - x1 + 1;
- h = y2 - y1 + 1;
- p0 = &_agiScreen[x1 + y1 * GFX_WIDTH];
- for (y = 0; y < h; y++) {
- memset(p0, c, w);
- p0 += GFX_WIDTH;
+// Attention: y coordinate is here supposed to be the upper one!
+void GfxMgr::block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr) {
+ int16 startOffset = y * SCRIPT_WIDTH + x;
+ int16 offset = startOffset;
+ int16 remainingHeight = height;
+ byte *curBufferPtr = bufferPtr;
+
+ //warning("block_save: %d, %d -> %d, %d", x, y, width, height);
+
+ while (remainingHeight) {
+ memcpy(curBufferPtr, _visualScreen + offset, width);
+ offset += SCRIPT_WIDTH;
+ curBufferPtr += width;
+ remainingHeight--;
+ }
+
+ remainingHeight = height;
+ offset = startOffset;
+ while (remainingHeight) {
+ memcpy(curBufferPtr, _priorityScreen + offset, width);
+ offset += SCRIPT_WIDTH;
+ curBufferPtr += width;
+ remainingHeight--;
}
}
-void GfxMgr::drawFrame(int x1, int y1, int x2, int y2, int c1, int c2) {
- int y, w;
- uint8 *p0;
+// Attention: y coordinate is here supposed to be the upper one!
+void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr) {
+ int16 startOffset = y * SCRIPT_WIDTH + x;
+ int16 offset = startOffset;
+ int16 remainingHeight = height;
+ byte *curBufferPtr = bufferPtr;
- // top line
- w = x2 - x1 + 1;
- p0 = &_agiScreen[x1 + y1 * GFX_WIDTH];
- memset(p0, c1, w);
+ //warning("block_restore: %d, %d -> %d, %d", x, y, width, height);
- // bottom line
- p0 = &_agiScreen[x1 + y2 * GFX_WIDTH];
- memset(p0, c2, w);
+ while (remainingHeight) {
+ memcpy(_visualScreen + offset, curBufferPtr, width);
+ offset += SCRIPT_WIDTH;
+ curBufferPtr += width;
+ remainingHeight--;
+ }
- // side lines
- for (y = y1; y <= y2; y++) {
- _agiScreen[x1 + y * GFX_WIDTH] = c1;
- _agiScreen[x2 + y * GFX_WIDTH] = c2;
+ remainingHeight = height;
+ offset = startOffset;
+ while (remainingHeight) {
+ memcpy(_priorityScreen + offset, curBufferPtr, width);
+ offset += SCRIPT_WIDTH;
+ curBufferPtr += width;
+ remainingHeight--;
}
}
-void GfxMgr::drawBox(int x1, int y1, int x2, int y2, int color1, int color2, int m) {
- x1 += m;
- y1 += m;
- x2 -= m;
- y2 -= m;
+// Attention: uses visual screen coordinates!
+void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height) {
+ g_system->copyRectToScreen(_displayScreen + y * DISPLAY_WIDTH + x, DISPLAY_WIDTH, x, y, width, height);
+}
+
+// coordinates are for visual screen, but are supposed to point somewhere inside the playscreen
+void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor) {
+ drawRect(x, y, width, height, backgroundColor);
+ drawRect(x + 1, y - 1, width - 2, 1, lineColor);
+ drawRect(x + width - 2, y - 2, 1, height - 4, lineColor);
+ drawRect(x + 1, y - height + 2, width - 2, 1, lineColor);
+ drawRect(x + 1, y - 2, 1, height - 4, lineColor);
+}
+
+// coordinates for visual screen
+// attention: Clipping is done here against 160x200 instead of 160x168
+// Original interpreter didn't do any clipping, we do it for security.
+// Clipping against the regular script width/height must not be done,
+// because at least during the intro one message box goes beyond playscreen
+// Going beyond 160x168 will result in messageboxes not getting fully removed
+// In KQ4's case, the scripts clear the screen that's why it works.
+void GfxMgr::drawRect(int16 x, int16 y, int16 width, int16 height, byte color) {
+ if (!render_Clip(x, y, width, height, SCRIPT_WIDTH, DISPLAY_HEIGHT - _renderStartOffsetY))
+ return;
- drawRectangle(x1, y1, x2, y2, color1);
- drawFrame(x1 + 2, y1 + 2, x2 - 2, y2 - 2, color2, color2);
- flushBlock(x1, y1, x2, y2);
+ // coordinate translation: visual-screen -> display-screen
+ x = x * 2;
+ y = y + _renderStartOffsetY; // drawDisplayRect paints anywhere on the whole screen, our coordinate is within playscreen
+ width = width * 2; // width was given as visual width, we need display width
+ drawDisplayRect(x, y, width, height, color);
+}
+
+// coordinates are directly for display screen
+void GfxMgr::drawDisplayRect(int16 x, int16 y, int16 width, int16 height, byte color) {
+ switch (_vm->_renderMode) {
+ case RENDERMODE_CGA:
+ drawDisplayRectCGA(x, y, width, height, color);
+ break;
+ case RENDERMODE_EGA:
+ default:
+ drawDisplayRectEGA(x, y, width, height, color);
+ break;
+ }
+ int16 upperY = y - height + 1;
+ g_system->copyRectToScreen(_displayScreen + upperY * DISPLAY_WIDTH + x, DISPLAY_WIDTH, x, upperY, width, height);
}
-void GfxMgr::printCharacter(int x, int y, char c, int fg, int bg) {
- x *= CHAR_COLS;
- y *= CHAR_LINES;
+void GfxMgr::drawDisplayRectEGA(int16 x, int16 y, int16 width, int16 height, byte color) {
+ int offsetDisplay = (DISPLAY_WIDTH * y) + x;
+ int16 remainingHeight = height;
- putTextCharacter(0, x, y, c, fg, bg, false, _vm->getFontData());
- // redundant! already inside put_text_character!
- // flush_block (x, y, x + CHAR_COLS - 1, y + CHAR_LINES - 1);
+ while (remainingHeight) {
+ memset(_displayScreen + offsetDisplay, color, width);
+
+ offsetDisplay -= DISPLAY_WIDTH;
+ remainingHeight--;
+ }
}
-/**
- * Draw a default style button.
- * Swaps background and foreground color if button is in focus or being pressed.
- * @param x x coordinate of the button
- * @param y y coordinate of the button
- * @param a set if the button has focus
- * @param p set if the button is pressed
- * @param fgcolor foreground color of the button when it is neither in focus nor being pressed
- * @param bgcolor background color of the button when it is neither in focus nor being pressed
- */
-void GfxMgr::drawDefaultStyleButton(int x, int y, const char *s, int a, int p, int fgcolor, int bgcolor) {
- int textOffset = _vm->_defaultButtonStyle.getTextOffset(a > 0, p > 0);
- AgiTextColor color = _vm->_defaultButtonStyle.getColor (a > 0, p > 0, fgcolor, bgcolor);
- bool border = _vm->_defaultButtonStyle.getBorder (a > 0, p > 0);
+void GfxMgr::drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byte color) {
+ int offsetDisplay = (DISPLAY_WIDTH * y) + x;
+ int16 remainingHeight = height;
+ int16 remainingWidth = width;
+ byte CGAMixtureColor = getCGAMixtureColor(color);
+ byte *displayScreen = nullptr;
+
+ // we should never get an uneven width
+ assert((width & 1) == 0);
+
+ while (remainingHeight) {
+ remainingWidth = width;
+
+ // set up pointer
+ displayScreen = _displayScreen + offsetDisplay;
- rawDrawButton(x, y, s, color.fg, color.bg, border, textOffset);
+ while (remainingWidth) {
+ *displayScreen++ = CGAMixtureColor & 0x03;
+ *displayScreen++ = CGAMixtureColor >> 2;
+ remainingWidth -= 2;
+ }
+
+ offsetDisplay -= DISPLAY_WIDTH;
+ remainingHeight--;
+ }
}
-/**
- * Draw a button using the currently chosen style.
- * Amiga-style is used for the Amiga-rendering mode, PC-style is used otherwise.
- * @param x x coordinate of the button
- * @param y y coordinate of the button
- * @param hasFocus set if the button has focus
- * @param pressed set if the button is pressed
- * @param positive set if button is positive, otherwise button is negative (Only matters with Amiga-style buttons)
- * TODO: Make Amiga-style buttons a bit wider as they were in Amiga AGI games.
- */
-void GfxMgr::drawCurrentStyleButton(int x, int y, const char *label, bool hasFocus, bool pressed, bool positive) {
- int textOffset = _vm->_buttonStyle.getTextOffset(hasFocus, pressed);
- AgiTextColor color = _vm->_buttonStyle.getColor(hasFocus, pressed, positive);
- bool border = _vm->_buttonStyle.getBorder(hasFocus, pressed);
+// row + column are text-coordinates
+void GfxMgr::drawCharacter(int16 row, int16 column, byte character, byte foreground, byte background, bool disabledLook) {
+ int16 startX, startY;
+ int16 curX, curY;
+ const byte *fontData;
+ byte curByte = 0;
+ uint16 curBit;
+ byte curTransformXOR = 0;
+ byte curTransformOR = 0;
+
+ startX = column * FONT_DISPLAY_HEIGHT;
+ startY = row * FONT_DISPLAY_WIDTH;
+
+ // get font data of specified character
+ fontData = _vm->getFontData() + character * FONT_BYTES_PER_CHARACTER;
+
+ // Now figure out, if special handling needs to be done (for graphical mode only)
+ if (_vm->_game.gfxMode) {
+ if (background & 0x08) {
+ // invert enabled
+ background &= 0x07; // remove invert bit
+ curTransformXOR = 0xFF; // inverse all bits of the font
+ }
+ if (disabledLook) {
+ curTransformOR = 0xAA;
+ }
+ }
+
+ curBit = 0;
+ for (curY = 0; curY < FONT_DISPLAY_HEIGHT; curY++) {
+ for (curX = 0; curX < FONT_DISPLAY_WIDTH; curX++) {
+ if (!curBit) {
+ curByte = *fontData;
+ // do transformations in case they are needed (invert/disabled look)
+ curByte ^= curTransformXOR;
+ curByte |= curTransformOR;
+ fontData++;
+ curBit = 0x80;
+ }
+ if (curByte & curBit) {
+ putPixelOnDisplay(startX + curX, startY + curY, foreground);
+ } else {
+ putPixelOnDisplay(startX + curX, startY + curY, background);
+ }
+ curBit = curBit >> 1;
+ }
+ }
- rawDrawButton(x, y, label, color.fg, color.bg, border, textOffset);
+ copyDisplayRectToScreen(startX, startY, FONT_DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
}
-void GfxMgr::rawDrawButton(int x, int y, const char *s, int fgcolor, int bgcolor, bool border, int textOffset) {
- int len = strlen(s);
- int x1, y1, x2, y2;
+#define SHAKE_VERTICAL_PIXELS 4
+#define SHAKE_HORIZONTAL_PIXELS 8
- x1 = x - 3;
- y1 = y - 3;
- x2 = x + CHAR_COLS * len + 2;
- y2 = y + CHAR_LINES + 2;
+// Sierra used some EGA port trickery to do it, we have to do it by copying pixels around
+void GfxMgr::shakeScreen(int16 repeatCount) {
+ int shakeNr, shakeCount;
+ uint8 *blackSpace;
- // Draw a filled rectangle that's larger than the button. Used for drawing
- // a border around the button as the button itself is drawn after this.
- drawRectangle(x1, y1, x2, y2, border ? BUTTON_BORDER : MSG_BOX_COLOR);
+ if ((blackSpace = (uint8 *)calloc(SHAKE_HORIZONTAL_PIXELS * DISPLAY_WIDTH, 1)) == NULL)
+ return;
- while (*s) {
- putTextCharacter(0, x + textOffset, y + textOffset, *s++, fgcolor, bgcolor, false, _vm->getFontData());
- x += CHAR_COLS;
+ shakeCount = repeatCount * 8; // effectively 4 shakes per repeat
+
+ // it's 4 pixels down and 8 pixels to the right
+ // and it's also filling the remaining space with black
+ for (shakeNr = 0; shakeNr < shakeCount; shakeNr++) {
+ if (shakeNr & 1) {
+ // move back
+ copyDisplayRectToScreen(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ } else {
+ g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, SHAKE_HORIZONTAL_PIXELS, SHAKE_VERTICAL_PIXELS, DISPLAY_WIDTH - SHAKE_HORIZONTAL_PIXELS, DISPLAY_HEIGHT - SHAKE_VERTICAL_PIXELS);
+ // additionally fill the remaining space with black
+ g_system->copyRectToScreen(blackSpace, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, SHAKE_VERTICAL_PIXELS);
+ g_system->copyRectToScreen(blackSpace, SHAKE_HORIZONTAL_PIXELS, 0, 0, SHAKE_HORIZONTAL_PIXELS, DISPLAY_HEIGHT);
+ }
+ g_system->updateScreen();
+ g_system->delayMillis(66); // Sierra waited for 4 V'Syncs, which is around 66 milliseconds
}
- x1 -= 2;
- y1 -= 2;
- x2 += 2;
- y2 += 2;
+ free(blackSpace);
+}
- flushBlock(x1, y1, x2, y2);
+void GfxMgr::updateScreen() {
+ g_system->updateScreen();
}
-int GfxMgr::testButton(int x, int y, const char *s) {
- int len = strlen(s);
- Common::Rect rect(x - 3, y - 3, x + CHAR_COLS * len + 3, y + CHAR_LINES + 3);
- return rect.contains(_vm->_mouse.x, _vm->_mouse.y);
+void GfxMgr::initPriorityTable() {
+ int16 priority, step;
+ int16 yPos = 0;
+
+ _priorityTableSet = false;
+ for (priority = 1; priority < 15; priority++) {
+ for (step = 0; step < 12; step++) {
+ _priorityTable[yPos++] = priority < 4 ? 4 : priority;
+ }
+ }
}
-void GfxMgr::putBlock(int x1, int y1, int x2, int y2) {
- gfxPutBlock(x1, y1, x2, y2);
+void GfxMgr::setPriorityTable(int16 priorityBase) {
+ int16 x, priorityY, priority;
+
+ _priorityTableSet = true;
+ x = (SCRIPT_HEIGHT - priorityBase) * SCRIPT_HEIGHT / 10;
+
+ for (priorityY = 0; priorityY < SCRIPT_HEIGHT; priorityY++) {
+ priority = (priorityY - priorityBase) < 0 ? 4 : (priorityY - priorityBase) * SCRIPT_HEIGHT / x + 5;
+ if (priority > 15)
+ priority = 15;
+ _priorityTable[priorityY] = priority;
+ }
}
-void GfxMgr::putScreen() {
- putBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
+// used for restoring
+void GfxMgr::setPriority(int16 yPos, int16 priority) {
+ assert(yPos < SCRIPT_HEIGHT);
+ _priorityTable[yPos] = priority;
}
-/*
- * Public functions
+/**
+ * Convert sprite priority to y value.
*/
+int16 GfxMgr::priorityToY(int16 priority) {
+ int16 currentY;
+
+ if (!_priorityTableSet) {
+ // priority table wasn't set by scripts? calculate directly
+ return (priority - 5) * 12 + 48;
+ }
+
+ // dynamic priority bands were introduced in 3.002.086 (effectively AGI3)
+ // It seems there was a glitch, that caused priority bands to not get calculated properly.
+ // It was caused by this function starting with Y = 168 instead of 167, which meant it always
+ // returned with 168 as result.
+ // This glitch is required in King's Quest 4 2.0, otherwise in room 54 ego will get drawn over
+ // the last dwarf, that enters the house.
+ // Dwarf is screen object 13 (view 152), gets fixed priority of 8, which would normally
+ // result in a Y of 101. Ego is priority (non-fixed) 8, which would mean that dwarf is
+ // drawn first, followed by ego, which would then draw ego over the dwarf.
+ // For more information see bug #1712585 (dwarf sprite priority)
+ //
+ // Priority bands were working properly in: 3.001.098 (Black Cauldron)
+ uint16 agiVersion = _vm->getVersion();
+
+ if (agiVersion <= 0x3086) {
+ return 168; // Buggy behavior, see above
+ }
+
+ currentY = 167;
+ while (_priorityTable[currentY] >= priority) {
+ currentY--;
+ if (currentY < 0) // Original AGI didn't do this, we abort in that case and return -1
+ break;
+ }
+ return currentY;
+}
+
+int16 GfxMgr::priorityFromY(int16 yPos) {
+ assert(yPos < SCRIPT_HEIGHT);
+ return _priorityTable[yPos];
+}
+
/**
* Initialize the color palette
@@ -800,18 +766,22 @@ void GfxMgr::putScreen() {
* @param fromBits Bits per source color component.
* @param toBits Bits per destination color component.
*/
-void GfxMgr::initPalette(const uint8 *p, uint colorCount, uint fromBits, uint toBits) {
+void GfxMgr::initPalette(uint8 *destPalette, const uint8 *paletteData, uint colorCount, uint fromBits, uint toBits) {
const uint srcMax = (1 << fromBits) - 1;
const uint destMax = (1 << toBits) - 1;
for (uint col = 0; col < colorCount; col++) {
for (uint comp = 0; comp < 3; comp++) { // Convert RGB components
- _palette[col * 3 + comp] = (p[col * 3 + comp] * destMax) / srcMax;
+ destPalette[col * 3 + comp] = (paletteData[col * 3 + comp] * destMax) / srcMax;
}
}
}
-void GfxMgr::gfxSetPalette() {
- g_system->getPaletteManager()->setPalette(_palette, 0, 256);
+void GfxMgr::setPalette(bool gfxModePalette) {
+ if (gfxModePalette) {
+ g_system->getPaletteManager()->setPalette(_paletteGfxMode, 0, 256);
+ } else {
+ g_system->getPaletteManager()->setPalette(_paletteTextMode, 0, 256);
+ }
}
//Gets AGIPAL Data
@@ -863,8 +833,8 @@ void GfxMgr::setAGIPal(int p0) {
_agipalFileNum = p0;
- initPalette(_agipalPalette);
- gfxSetPalette();
+ initPalette(_paletteGfxMode, _agipalPalette);
+ setPalette(true); // set gfx-mode palette
debug(1, "Using AGIPAL palette from '%s'", filename);
}
@@ -873,137 +843,33 @@ int GfxMgr::getAGIPalFileNum() {
return _agipalFileNum;
}
-// put a block onto the screen
-void GfxMgr::gfxPutBlock(int x1, int y1, int x2, int y2) {
- if (x1 >= GFX_WIDTH)
- x1 = GFX_WIDTH - 1;
- if (y1 >= GFX_HEIGHT)
- y1 = GFX_HEIGHT - 1;
- if (x2 >= GFX_WIDTH)
- x2 = GFX_WIDTH - 1;
- if (y2 >= GFX_HEIGHT)
- y2 = GFX_HEIGHT - 1;
-
- g_system->copyRectToScreen(_screen + y1 * 320 + x1, 320, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+void GfxMgr::initMouseCursor(MouseCursorData *mouseCursor, const byte *bitmapData, uint16 width, uint16 height, int hotspotX, int hotspotY) {
+ mouseCursor->bitmapData = bitmapData;
+ mouseCursor->width = width;
+ mouseCursor->height = height;
+ mouseCursor->hotspotX = hotspotX;
+ mouseCursor->hotspotY = hotspotY;
}
-/**
- * A black and white SCI-style arrow cursor (11x16).
- * 0 = Transparent.
- * 1 = Black (#000000 in 24-bit RGB).
- * 2 = White (#FFFFFF in 24-bit RGB).
- */
-static const byte sciMouseCursor[] = {
- 1,1,0,0,0,0,0,0,0,0,0,
- 1,2,1,0,0,0,0,0,0,0,0,
- 1,2,2,1,0,0,0,0,0,0,0,
- 1,2,2,2,1,0,0,0,0,0,0,
- 1,2,2,2,2,1,0,0,0,0,0,
- 1,2,2,2,2,2,1,0,0,0,0,
- 1,2,2,2,2,2,2,1,0,0,0,
- 1,2,2,2,2,2,2,2,1,0,0,
- 1,2,2,2,2,2,2,2,2,1,0,
- 1,2,2,2,2,2,2,2,2,2,1,
- 1,2,2,2,2,2,1,0,0,0,0,
- 1,2,1,0,1,2,2,1,0,0,0,
- 1,1,0,0,1,2,2,1,0,0,0,
- 0,0,0,0,0,1,2,2,1,0,0,
- 0,0,0,0,0,1,2,2,1,0,0,
- 0,0,0,0,0,0,1,2,2,1,0
-};
-
-#if 0
-/**
- * A black and white Apple IIGS style arrow cursor (9x11).
- * 0 = Transparent.
- * 1 = Black (#000000 in 24-bit RGB).
- * 2 = White (#FFFFFF in 24-bit RGB).
- */
-static const byte appleIIgsMouseCursor[] = {
- 2,2,0,0,0,0,0,0,0,
- 2,1,2,0,0,0,0,0,0,
- 2,1,1,2,0,0,0,0,0,
- 2,1,1,1,2,0,0,0,0,
- 2,1,1,1,1,2,0,0,0,
- 2,1,1,1,1,1,2,0,0,
- 2,1,1,1,1,1,1,2,0,
- 2,1,1,1,1,1,1,1,2,
- 2,1,1,2,1,1,2,2,0,
- 2,2,2,0,2,1,1,2,0,
- 0,0,0,0,0,2,2,2,0
-};
-#endif
-
-/**
- * RGB-palette for the black and white SCI and Apple IIGS arrow cursors.
- */
-static const byte sciMouseCursorPalette[] = {
- 0x00, 0x00, 0x00, // Black
- 0xFF, 0xFF, 0xFF // White
-};
-
-/**
- * An Amiga-style arrow cursor (8x11).
- * 0 = Transparent.
- * 1 = Black (#000000 in 24-bit RGB).
- * 2 = Red (#DE2021 in 24-bit RGB).
- * 3 = Light red (#FFCFAD in 24-bit RGB).
- */
-static const byte amigaMouseCursor[] = {
- 2,3,1,0,0,0,0,0,
- 2,2,3,1,0,0,0,0,
- 2,2,2,3,1,0,0,0,
- 2,2,2,2,3,1,0,0,
- 2,2,2,2,2,3,1,0,
- 2,2,2,2,2,2,3,1,
- 2,0,2,2,3,1,0,0,
- 0,0,0,2,3,1,0,0,
- 0,0,0,2,2,3,1,0,
- 0,0,0,0,2,3,1,0,
- 0,0,0,0,2,2,3,1
-};
+void GfxMgr::setMouseCursor(bool busy) {
+ MouseCursorData *mouseCursor = nullptr;
-/**
- * RGB-palette for the Amiga-style arrow cursor
- * and the Amiga-style busy cursor.
- */
-static const byte amigaMouseCursorPalette[] = {
- 0x00, 0x00, 0x00, // Black
- 0xDE, 0x20, 0x21, // Red
- 0xFF, 0xCF, 0xAD // Light red
-};
+ if (!busy) {
+ mouseCursor = &_mouseCursor;
+ } else {
+ mouseCursor = &_mouseCursorBusy;
+ }
-/**
- * An Amiga-style busy cursor showing an hourglass (13x16).
- * 0 = Transparent.
- * 1 = Black (#000000 in 24-bit RGB).
- * 2 = Red (#DE2021 in 24-bit RGB).
- * 3 = Light red (#FFCFAD in 24-bit RGB).
- */
-static const byte busyAmigaMouseCursor[] = {
- 1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,2,2,2,2,2,2,2,2,2,2,2,1,
- 1,2,2,2,2,2,2,2,2,2,2,2,1,
- 0,1,3,3,3,3,3,3,3,3,3,1,0,
- 0,0,1,3,3,3,3,3,3,3,1,0,0,
- 0,0,0,1,3,3,3,3,3,1,0,0,0,
- 0,0,0,0,1,3,3,3,1,0,0,0,0,
- 0,0,0,0,0,1,3,1,0,0,0,0,0,
- 0,0,0,0,0,1,3,1,0,0,0,0,0,
- 0,0,0,0,1,2,3,2,1,0,0,0,0,
- 0,0,0,1,2,2,3,2,2,1,0,0,0,
- 0,0,1,2,2,2,3,2,2,2,1,0,0,
- 0,1,2,2,2,3,3,3,2,2,2,1,0,
- 1,3,3,3,3,3,3,3,3,3,3,3,1,
- 1,3,3,3,3,3,3,3,3,3,3,3,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1
-};
+ if (mouseCursor) {
+ CursorMan.replaceCursor(mouseCursor->bitmapData, mouseCursor->width, mouseCursor->height, mouseCursor->hotspotX, mouseCursor->hotspotY, 0);
+ }
+}
+#if 0
void GfxMgr::setCursor(bool amigaStyleCursor, bool busy) {
if (busy) {
- CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 3);
- CursorMan.replaceCursor(busyAmigaMouseCursor, 13, 16, 7, 8, 0);
-
+ CursorMan.replaceCursorPalette(MOUSECURSOR_AMIGA_PALETTE, 1, ARRAYSIZE(MOUSECURSOR_AMIGA_PALETTE) / 3);
+ CursorMan.replaceCursor(MOUSECURSOR_AMIGA_BUSY, 13, 16, 7, 8, 0);
return;
}
@@ -1029,241 +895,6 @@ void GfxMgr::setCursorPalette(bool amigaStyleCursor) {
}
}
}
-
-/**
- * Initialize graphics device.
- *
- * @see deinit_video()
- */
-int GfxMgr::initVideo() {
- if (_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2))
- initPalette(vgaPalette, 256, 8);
- else if (_vm->_renderMode == Common::kRenderEGA)
- initPalette(egaPalette);
- else if (_vm->_renderMode == Common::kRenderAmiga) {
- if (!ConfMan.getBool("altamigapalette")) {
- // Set the correct Amiga palette
- if (_vm->getVersion() < 0x2936)
- // TODO: This palette isn't used for Apple IIGS games yet, as
- // we don't set a separate render mode for them yet
- initPalette(amigaAgiPaletteV1, 16, 4);
- else if (_vm->getVersion() == 0x2936)
- initPalette(amigaAgiPaletteV2, 16, 4);
- else if (_vm->getVersion() > 0x2936)
- initPalette(amigaAgiPaletteV3, 16, 4);
- } else
- // Set the old common alternative Amiga palette
- initPalette(altAmigaPalette);
- } else
- error("initVideo: Unhandled render mode \"%s\"", Common::getRenderModeDescription(_vm->_renderMode));
-
- if ((_agiScreen = (uint8 *)calloc(GFX_WIDTH, GFX_HEIGHT)) == NULL)
- return errNotEnoughMemory;
-
- gfxSetPalette();
-
- setCursor(_vm->_renderMode == Common::kRenderAmiga);
-
- return errOK;
-}
-
-/**
- * Deinitialize graphics device.
- *
- * @see init_video()
- */
-int GfxMgr::deinitVideo() {
- free(_agiScreen);
-
- return errOK;
-}
-
-int GfxMgr::initMachine() {
- _screen = (unsigned char *)malloc(320 * 200);
- _vm->_clockCount = 0;
-
- return errOK;
-}
-
-int GfxMgr::deinitMachine() {
- free(_screen);
-
- return errOK;
-}
-
-/**
- * Write pixels on the output device.
- * This function writes a row of pixels on the output device. Only the
- * lower 4 bits of each pixel in the row will be used, making this
- * function suitable for use with rows from the AGI screen.
- * @param x x coordinate of the row start (AGI coord.)
- * @param y y coordinate of the row start (AGI coord.)
- * @param n number of pixels in the row
- * @param p pointer to the row start in the AGI screen (Always use sbuf16c as base, not sbuf256c)
- * FIXME: CGA rendering doesn't work correctly with AGI256 or AGI256-2.
- */
-void GfxMgr::putPixelsA(int x, int y, int n, uint8 *p) {
- const uint rShift = _vm->_debug.priority ? 4 : 0; // Priority information is in the top 4 bits of a byte taken from sbuf16c.
-
- // Choose the correct screen to read from. If AGI256 or AGI256-2 is used and we're not trying to show the priority information,
- // then choose the 256 color screen, otherwise choose the 16 color screen (Which also has the priority information).
- p += ((_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2)) && !_vm->_debug.priority) ? FROM_SBUF16_TO_SBUF256_OFFSET : 0;
-
- if (_vm->_renderMode == Common::kRenderCGA) {
- for (x *= 2; n--; p++, x += 2) {
- register uint16 q = (cgaMap[(*p & 0xf0) >> 4] << 4) | cgaMap[*p & 0x0f];
- *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & 0x0f0f;
- }
- } else {
- const uint16 mask = ((_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2)) && !_vm->_debug.priority) ? 0xffff : 0x0f0f;
- for (x *= 2; n--; p++, x += 2) {
- register uint16 q = ((uint16)*p << 8) | *p;
- *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & mask;
- }
- }
-}
-
-/**
- * Schedule blocks for blitting on the output device.
- * This function gets the coordinates of a block in the AGI screen and
- * schedule it to be updated in the output device.
- * @param x1 x coordinate of the upper left corner of the block (AGI coord.)
- * @param y1 y coordinate of the upper left corner of the block (AGI coord.)
- * @param x2 x coordinate of the lower right corner of the block (AGI coord.)
- * @param y2 y coordinate of the lower right corner of the block (AGI coord.)
- *
- * @see do_update()
- */
-void GfxMgr::scheduleUpdate(int x1, int y1, int x2, int y2) {
- if (x1 < update.x1)
- update.x1 = x1;
- if (y1 < update.y1)
- update.y1 = y1;
- if (x2 > update.x2)
- update.x2 = x2;
- if (y2 > update.y2)
- update.y2 = y2;
-}
-
-/**
- * Update scheduled blocks on the output device.
- * This function exposes the blocks scheduled for updating to the output
- * device. Blocks can be scheduled at any point of the AGI cycle.
- *
- * @see schedule_update()
- */
-void GfxMgr::doUpdate() {
- if (update.x1 <= update.x2 && update.y1 <= update.y2) {
- gfxPutBlock(update.x1, update.y1, update.x2, update.y2);
- }
-
- // reset update block variables
- update.x1 = MAX_INT;
- update.y1 = MAX_INT;
- update.x2 = 0;
- update.y2 = 0;
-
- g_system->updateScreen();
-}
-
-/**
- * Updates a block of the framebuffer with contents of the AGI engine screen.
- * This function updates a block in the output device with the contents of
- * the AGI engine screen, handling console transparency.
- * @param x1 x coordinate of the upper left corner of the block
- * @param y1 y coordinate of the upper left corner of the block
- * @param x2 x coordinate of the lower right corner of the block
- * @param y2 y coordinate of the lower right corner of the block
- *
- * @see flush_block_a()
- */
-void GfxMgr::flushBlock(int x1, int y1, int x2, int y2) {
- int y, w;
- uint8 *p0;
-
- scheduleUpdate(x1, y1, x2, y2);
-
- p0 = &_agiScreen[x1 + y1 * GFX_WIDTH];
- w = x2 - x1 + 1;
-
- for (y = y1; y <= y2; y++) {
- memcpy(_screen + 320 * y + x1, p0, w);
- p0 += GFX_WIDTH;
- }
-}
-
-/**
- * Updates a block of the framebuffer receiving AGI picture coordinates.
- * @param x1 x AGI picture coordinate of the upper left corner of the block
- * @param y1 y AGI picture coordinate of the upper left corner of the block
- * @param x2 x AGI picture coordinate of the lower right corner of the block
- * @param y2 y AGI picture coordinate of the lower right corner of the block
- *
- * @see flush_block()
- */
-void GfxMgr::flushBlockA(int x1, int y1, int x2, int y2) {
- //y1 += 8;
- //y2 += 8;
- flushBlock(DEV_X0(x1), DEV_Y(y1), DEV_X1(x2), DEV_Y(y2));
-}
-
-/**
- * Updates the framebuffer with contents of the AGI engine screen (console-aware).
- * This function updates the output device with the contents of the AGI
- * screen, handling console transparency.
- */
-void GfxMgr::flushScreen() {
- flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
-
- doUpdate();
-}
-
-/**
- * Clear the output device screen (console-aware).
- * This function clears the output device screen and updates the
- * output device. Contents of the AGI screen are left untouched. This
- * function can be used to simulate a switch to a text mode screen in
- * a graphic-only device.
- * @param c color to clear the screen
- */
-void GfxMgr::clearScreen(int c) {
- memset(_agiScreen, c, GFX_WIDTH * GFX_HEIGHT);
- flushScreen();
-}
-
-/**
- * Save a block of the AGI engine screen
- */
-void GfxMgr::saveBlock(int x1, int y1, int x2, int y2, uint8 *b) {
- uint8 *p0;
- int w, h;
-
- p0 = &_agiScreen[x1 + GFX_WIDTH * y1];
- w = x2 - x1 + 1;
- h = y2 - y1 + 1;
- while (h--) {
- memcpy(b, p0, w);
- b += w;
- p0 += GFX_WIDTH;
- }
-}
-
-/**
- * Restore a block of the AGI engine screen
- */
-void GfxMgr::restoreBlock(int x1, int y1, int x2, int y2, uint8 *b) {
- uint8 *p0;
- int w, h;
-
- p0 = &_agiScreen[x1 + GFX_WIDTH * y1];
- w = x2 - x1 + 1;
- h = y2 - y1 + 1;
- while (h--) {
- memcpy(p0, b, w);
- b += w;
- p0 += GFX_WIDTH;
- }
- flushBlock(x1, y1, x2, y2);
-}
+#endif
} // End of namespace Agi