[Scummvm-git-logs] scummvm master -> 0f27cdba16e7b429dbc3c54eb19267b8ca087683
sev-
noreply at scummvm.org
Sat Apr 25 22:55:02 UTC 2026
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
64ae817ccb CHAMBER: Add EGA core rendering infrastructure
4b51672503 CHAMBER: Add EGA engine initialization and resource loading
a509e6c307 CHAMBER: Wire CGA dispatch layer to EGA for basic rendering
9d5a91b29c CHAMBER: Extend EGA rendering to animation, portrait, room, and script
cb6c1a1754 CHAMBER: Refactor rendering into Renderer class hierarchy
897d9a7b3f CHAMBER: Remove renderer mode checks by moving format dispatch into EGARenderer
0f27cdba16 CHAMBER: Address review comments
Commit: 64ae817ccb085419ecc55dd171ca247d1a4eea2d
https://github.com/scummvm/scummvm/commit/64ae817ccb085419ecc55dd171ca247d1a4eea2d
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Add EGA core rendering infrastructure
Add ega.cpp/ega.h implementing the linear 320x200 CLUT8 framebuffers, the standard 16-color EGA palette, block and sprite blitters, draw primitives, a planar-to-chunky background loader, and offset helpers.
Add ega_resource.cpp/ega_resource.h with EgaSpriteResource, which loads
.EGA sprite banks (packed 4bpp, 2 pixels per byte) and decodes each
sprite into a CLUT8 Graphics::Surface.
Changed paths:
A engines/chamber/ega.cpp
A engines/chamber/ega.h
A engines/chamber/ega_resource.cpp
A engines/chamber/ega_resource.h
engines/chamber/module.mk
diff --git a/engines/chamber/ega.cpp b/engines/chamber/ega.cpp
new file mode 100644
index 00000000000..da6d7b43db6
--- /dev/null
+++ b/engines/chamber/ega.cpp
@@ -0,0 +1,456 @@
+/* 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 "common/file.h"
+#include "common/system.h"
+#include "graphics/paletteman.h"
+#include "graphics/surface.h"
+
+#include "chamber/chamber.h"
+#include "chamber/common.h"
+#include "chamber/cga.h"
+#include "chamber/ega.h"
+#include "chamber/input.h"
+#include "chamber/resdata.h"
+#include "chamber/room.h"
+
+namespace Chamber {
+
+// ---------------------------------------------------------------------------
+// EGA 16-color palette (standard EGA RGB values)
+// Source: kult/kult.cpp â this is the correct version (NOT BGR-swapped)
+// ---------------------------------------------------------------------------
+const byte EGA_PALETTE[16 * 3] = {
+ 0x00, 0x00, 0x00, // 0 black
+ 0x00, 0x00, 0xaa, // 1 dark blue
+ 0x00, 0xaa, 0x00, // 2 dark green
+ 0x00, 0xaa, 0xaa, // 3 dark cyan
+ 0xaa, 0x00, 0x00, // 4 dark red
+ 0xaa, 0x00, 0xaa, // 5 dark magenta
+ 0xaa, 0x55, 0x00, // 6 brown
+ 0xaa, 0xaa, 0xaa, // 7 light grey
+ 0x00, 0x00, 0x00, // 8 dark grey (same as black in standard EGA)
+ 0x55, 0x55, 0xff, // 9 bright blue
+ 0x55, 0xff, 0x55, // 10 bright green
+ 0x55, 0xff, 0xff, // 11 bright cyan
+ 0xff, 0x55, 0x55, // 12 bright red
+ 0xff, 0x55, 0xff, // 13 bright magenta
+ 0xff, 0xff, 0x55, // 14 yellow
+ 0xff, 0xff, 0xff, // 15 white
+};
+
+// ---------------------------------------------------------------------------
+// EGA framebuffers â aliases to the shared CGA/EGA buffers (both 64000 bytes)
+// ega_screen -> CGA_SCREENBUFFER (frontbuffer in room.cpp)
+// ega_backbuffer -> backbuffer (backbuffer in room.cpp)
+// ---------------------------------------------------------------------------
+byte *ega_screen = CGA_SCREENBUFFER;
+byte *ega_backbuffer = backbuffer;
+
+// ---------------------------------------------------------------------------
+// Screen management
+// ---------------------------------------------------------------------------
+
+void ega_switchToGraphicsMode() {
+ g_system->getPaletteManager()->setPalette(EGA_PALETTE, 0, 16);
+}
+
+void ega_blitToScreen(int16 x, int16 y, int16 w, int16 h) {
+ if (x < 0) { w += x; x = 0; }
+ if (y < 0) { h += y; y = 0; }
+ if (x + w > EGA_WIDTH) w = EGA_WIDTH - x;
+ if (y + h > EGA_HEIGHT) h = EGA_HEIGHT - y;
+ if (w <= 0 || h <= 0)
+ return;
+
+ g_system->copyRectToScreen(
+ ega_screen + y * EGA_BYTES_PER_LINE + x,
+ EGA_BYTES_PER_LINE,
+ x, y, w, h);
+ g_system->updateScreen();
+}
+
+void ega_BackBufferToRealFull() {
+ memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+}
+
+void ega_RealBufferToBackFull() {
+ memcpy(ega_backbuffer, ega_screen, EGA_SCREEN_SIZE);
+}
+
+void ega_SwapRealBackBuffer() {
+ static byte tmp[EGA_SCREEN_SIZE];
+ memcpy(tmp, ega_screen, EGA_SCREEN_SIZE);
+ memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
+ memcpy(ega_backbuffer, tmp, EGA_SCREEN_SIZE);
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+}
+
+// ---------------------------------------------------------------------------
+// Offset helpers
+// EGA: linear layout, no interlacing â offset = y * 320 + x
+// ---------------------------------------------------------------------------
+
+uint16 ega_CalcXY(uint16 x, uint16 y) {
+ return y * EGA_BYTES_PER_LINE + x;
+}
+
+// "packed" variant: x is in 4-pixel units (matching CGA convention)
+uint16 ega_CalcXY_p(uint16 x, uint16 y) {
+ return y * EGA_BYTES_PER_LINE + x * 4;
+}
+
+// ---------------------------------------------------------------------------
+// Memory / block blit helpers
+// w is in *bytes* == *pixels* in EGA mode (1 byte per pixel)
+// ---------------------------------------------------------------------------
+
+void ega_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ memcpy(target + ofs, source + ofs, w);
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (target == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ byte *old = scratch_mem2;
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 i = 0; i < w; i++) {
+ *old++ = screen[ofs + i];
+ screen[ofs + i] = *pixels++;
+ }
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+// EGA backup image header (6 bytes):
+// [0] h (byte)
+// [1] w_cga = w_pixels / 4 (byte, CGA byte-units; avoids overflow for w <= 1020 px)
+// [2:3] ofs (uint16, linear EGA offset)
+// Pixel data follows at buffer+4, w_pixels bytes per row à h rows.
+// w is passed as pixel width (w_cga * 4). Callers from cga_BackupImage
+// already multiply by 4; callers from backupAndShowSprite pass surf->w directly.
+byte *ega_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
+ *(byte *)(buffer + 0) = (byte)h;
+ *(byte *)(buffer + 1) = (byte)(w >> 2); // store CGA byte-units to keep in one byte
+ *(uint16 *)(buffer + 2) = ofs;
+ buffer += 4;
+ for (uint16 y = 0; y < h; y++) {
+ memcpy(buffer, source + ofs, w);
+ buffer += w;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+ return buffer;
+}
+
+void ega_RestoreImage(byte *buffer, byte *target) {
+ if (!buffer)
+ return;
+ uint16 h = *(byte *)(buffer + 0);
+ uint16 w = (uint16)*(byte *)(buffer + 1) * 4; // restore pixel width
+ uint16 ofs = *(uint16 *)(buffer + 2);
+ buffer += 4;
+ ega_Blit(buffer, w, w, h, target, ofs);
+}
+
+void ega_RefreshImageData(byte *buffer) {
+ if (!buffer)
+ return;
+ uint16 h = *(byte *)(buffer + 0);
+ uint16 w = (uint16)*(byte *)(buffer + 1) * 4; // restore pixel width
+ uint16 ofs = *(uint16 *)(buffer + 2);
+ ega_CopyScreenBlock(ega_screen, w, h, ega_backbuffer, ofs);
+}
+
+void ega_RestoreBackupImage(byte *target) {
+ ega_RestoreImage(scratch_mem2, target);
+}
+
+void ega_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ memcpy(screen + ofs, pixels, w);
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ ega_Blit(pixels, pw, w, h, screen, ofs);
+ // waitVBlank is defined in cga.cpp and calls pollInput + delayMillis
+ pollInput();
+ g_system->delayMillis(10);
+}
+
+void ega_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 oofs = ofs;
+ debug(1, "ega_Fill: color=%d w=%d h=%d ofs=%d (x=%d y=%d)", pixel, w, h, ofs, ofs % EGA_BYTES_PER_LINE, ofs / EGA_BYTES_PER_LINE);
+ for (uint16 y = 0; y < h; y++) {
+ memset(screen + ofs, pixel, w);
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ ega_Fill(pixel, w, h, screen, ofs);
+ pollInput();
+ g_system->delayMillis(10);
+}
+
+void ega_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
+ ega_CopyScreenBlock(ega_backbuffer, w, h, screen, ofs);
+}
+
+// ---------------------------------------------------------------------------
+// Sprite blitters
+// EGA sprites are stored as decoded CLUT8: 1 byte per pixel, index 0 = transparent
+// ---------------------------------------------------------------------------
+
+void ega_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < w; x++) {
+ if (pixels[x] != 0)
+ screen[ofs + x] = pixels[x];
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < w; x++) {
+ if (pixels[w - 1 - x] != 0)
+ screen[ofs + x] = pixels[w - 1 - x];
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < w; x++) {
+ *backup++ = screen[ofs + x];
+ if (pixels[x] != 0)
+ screen[ofs + x] = pixels[x] & mask;
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ byte *pixels = scratch_mem2 + 2 + sprofs;
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < w; x++) {
+ // In CGA the scratch sprite has (mask, pixel) pairs per pixel-byte.
+ // In EGA mode the scratch sprite is plain CLUT8; use ega_backbuffer for transparency.
+ byte p = pixels[x];
+ screen[ofs + x] = (p != 0) ? p : ega_backbuffer[ofs + x];
+ }
+ pixels += w;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+// ---------------------------------------------------------------------------
+// Draw primitives
+// ---------------------------------------------------------------------------
+
+void ega_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+ uint16 ofs = ega_CalcXY(x, y);
+ for (uint16 i = 0; i < l; i++) {
+ target[ofs] = color;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (target == ega_screen)
+ ega_blitToScreen(x, y, 1, l);
+}
+
+void ega_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+ uint16 ofs = ega_CalcXY(x, y);
+ memset(target + ofs, color, l);
+
+ if (target == ega_screen)
+ ega_blitToScreen(x, y, l, 1);
+}
+
+uint16 ega_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
+ // bmask / bpix encode end-cap bytes in CGA 2bpp packed format (high byte = left, low byte = right).
+ // color is a CGA 2bpp packed fill byte. l is inner segment length in CGA bytes.
+ // Expand everything to CLUT8 EGA pixels: each CGA byte â 4 pixels.
+ uint16 oofs = ofs;
+
+ // Left end-cap: expand bpix high byte (4 pixels), applying bmask
+ byte leftPix = (bpix >> 8) & 0xFF;
+ byte leftMask = (bmask >> 8) & 0xFF;
+ for (int p = 3; p >= 0; p--) {
+ byte m = (leftMask >> (p * 2)) & 0x03;
+ byte px = (leftPix >> (p * 2)) & 0x03;
+ if (m == 0)
+ target[ofs] = cga_to_ega_color[px];
+ // else: leave existing pixel (masked out)
+ ofs++;
+ }
+
+ // Inner segment: l CGA bytes â l*4 pixels of solid color
+ byte egaColor = cga_to_ega_color[(color >> 6) & 0x03];
+ memset(target + ofs, egaColor, l * 4);
+ ofs += l * 4;
+
+ // Right end-cap: expand bpix low byte (4 pixels), applying bmask
+ byte rightPix = bpix & 0xFF;
+ byte rightMask = bmask & 0xFF;
+ for (int p = 3; p >= 0; p--) {
+ byte m = (rightMask >> (p * 2)) & 0x03;
+ byte px = (rightPix >> (p * 2)) & 0x03;
+ if (m == 0)
+ target[ofs] = cga_to_ega_color[px];
+ ofs++;
+ }
+
+ uint16 totalW = (l + 2) * 4;
+ if (target == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, totalW, 1);
+
+ return oofs + EGA_BYTES_PER_LINE;
+}
+
+// CGA palette 1 high-intensity â EGA color index mapping
+// CGA 0 (background) â EGA 0 (black)
+// CGA 1 (bright cyan) â EGA 11 (bright cyan)
+// CGA 2 (bright magenta) â EGA 13 (bright magenta)
+// CGA 3 (white) â EGA 15 (white)
+const byte cga_to_ega_color[] = { 0, 11, 13, 15 };
+
+void ega_PrintChar(byte c, byte *target) {
+ // carpc_data: 64 characters à fontHeight bytes, each byte encodes a 4-pixel row.
+ // char_xlat_table maps each font byte to a CGA 2bpp packed byte.
+ // We extract the 4 CGA 2-bit color values and map to EGA indices.
+ byte *font = carpc_data + c * g_vm->_fontHeight;
+ uint16 ofs = ega_CalcXY_p(char_draw_coords_x, char_draw_coords_y);
+
+ for (uint16 row = 0; row < (uint16)g_vm->_fontHeight; row++) {
+ byte bits = char_xlat_table[*font++];
+ for (int p = 3; p >= 0; p--) {
+ byte col = (bits >> (p * 2)) & 0x03;
+ target[ofs + (3 - p)] = cga_to_ega_color[col];
+ }
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ char_draw_coords_x++;
+
+ if (target == ega_screen)
+ ega_blitToScreen((char_draw_coords_x - 1) * g_vm->_fontWidth,
+ char_draw_coords_y,
+ g_vm->_fontWidth, g_vm->_fontHeight);
+}
+
+// ---------------------------------------------------------------------------
+// Background loader (Phase 1 milestone)
+// Reads a 32000-byte 4-plane EGA file and unpacks it into ega_backbuffer.
+// Format: 4 planes à 8000 bytes.
+// plane[0] = bits 0 of each pixel (8 pixels per byte, MSB first)
+// plane[1] = bits 1
+// plane[2] = bits 2
+// plane[3] = bits 3
+// Resulting pixel index = bit3<<3 | bit2<<2 | bit1<<1 | bit0
+// Reference: kult/kult.cpp:268-285
+// ---------------------------------------------------------------------------
+Graphics::Surface *ega_loadFond(const char *filename) {
+ Common::File fd;
+ if (!fd.open(filename)) {
+ warning("ega_loadFond: cannot open %s", filename);
+ return nullptr;
+ }
+
+ static byte planarData[EGA_PLANAR_SIZE * 4];
+ fd.read(planarData, sizeof(planarData));
+
+ byte *dst = ega_backbuffer;
+ for (uint i = 0; i < EGA_PLANAR_SIZE; i++) {
+ for (int bit = 7; bit >= 0; bit--) {
+ byte px =
+ (((planarData[i] >> bit) & 1) ) |
+ (((planarData[i + EGA_PLANAR_SIZE] >> bit) & 1) << 1) |
+ (((planarData[i + EGA_PLANAR_SIZE*2]>> bit) & 1) << 2) |
+ (((planarData[i + EGA_PLANAR_SIZE*3]>> bit) & 1) << 3);
+ *dst++ = px;
+ }
+ }
+
+ // Save a clean copy for background restoration
+ memcpy(ega_fond_clean, ega_backbuffer, EGA_SCREEN_SIZE);
+
+ // Return a Graphics::Surface that wraps ega_backbuffer so the existing
+ // loadFond() caller chain (which expects a Surface*) stays happy.
+ Graphics::Surface *surface = new Graphics::Surface();
+ surface->init(EGA_WIDTH, EGA_HEIGHT,
+ EGA_BYTES_PER_LINE,
+ ega_backbuffer,
+ Graphics::PixelFormat::createFormatCLUT8());
+ return surface;
+}
+
+// Clean copy of decoded FOND.EGA for room background restoration
+byte ega_fond_clean[EGA_SCREEN_SIZE];
+
+void ega_drawBackground(byte *target) {
+ // In EGA mode, the FOND.EGA contains the pre-rendered background.
+ // Restore the entire frame from the saved clean copy.
+ memcpy(target, ega_fond_clean, EGA_SCREEN_SIZE);
+}
+
+} // End of namespace Chamber
diff --git a/engines/chamber/ega.h b/engines/chamber/ega.h
new file mode 100644
index 00000000000..37aaf351e5e
--- /dev/null
+++ b/engines/chamber/ega.h
@@ -0,0 +1,101 @@
+/* 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 CHAMBER_EGA_H
+#define CHAMBER_EGA_H
+
+#include "graphics/surface.h"
+
+namespace Chamber {
+
+// EGA screen dimensions (same as CGA)
+#define EGA_WIDTH 320
+#define EGA_HEIGHT 200
+
+// EGA uses 1 byte per pixel (CLUT8 linear, no interlacing)
+#define EGA_BYTES_PER_LINE EGA_WIDTH
+#define EGA_SCREEN_SIZE (EGA_WIDTH * EGA_HEIGHT)
+
+// Planar background: 4 planes à 8000 bytes
+#define EGA_PLANAR_SIZE (EGA_WIDTH / 8 * EGA_HEIGHT) // 8000 bytes per plane
+
+extern byte *ega_screen; // aliases CGA_SCREENBUFFER (frontbuffer)
+extern byte *ega_backbuffer; // aliases backbuffer
+
+// Standard EGA 16-color palette (RGB, used for screen and cursor)
+extern const byte EGA_PALETTE[16 * 3];
+
+// CGA palette 1 high-intensity â EGA color index mapping
+extern const byte cga_to_ega_color[4];
+
+// --- screen management ---
+void ega_switchToGraphicsMode();
+void ega_blitToScreen(int16 x, int16 y, int16 w, int16 h);
+void ega_BackBufferToRealFull();
+void ega_RealBufferToBackFull();
+void ega_SwapRealBackBuffer();
+
+// --- offset helpers ---
+uint16 ega_CalcXY(uint16 x, uint16 y);
+uint16 ega_CalcXY_p(uint16 x, uint16 y);
+
+// --- memory / blit ---
+void ega_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
+void ega_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs);
+
+byte *ega_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer);
+void ega_RestoreImage(byte *buffer, byte *target);
+void ega_RefreshImageData(byte *buffer);
+void ega_RestoreBackupImage(byte *target);
+
+void ega_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
+void ega_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
+void ega_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs);
+void ega_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs);
+
+void ega_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs);
+
+// --- sprite blitters ---
+// EGA sprites are decoded to CLUT8 (1 byte/pixel); pixel 0 = transparent
+void ega_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
+void ega_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
+void ega_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask);
+
+void ega_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs);
+
+// --- draw primitives ---
+void ega_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
+void ega_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
+uint16 ega_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs);
+
+void ega_PrintChar(byte c, byte *target);
+
+// --- resource loader ---
+Graphics::Surface *ega_loadFond(const char *filename);
+
+// --- background restore ---
+// Saved clean copy of decoded FOND.EGA for room background restoration
+extern byte ega_fond_clean[EGA_SCREEN_SIZE];
+void ega_drawBackground(byte *target);
+
+} // End of namespace Chamber
+
+#endif // CHAMBER_EGA_H
diff --git a/engines/chamber/ega_resource.cpp b/engines/chamber/ega_resource.cpp
new file mode 100644
index 00000000000..59a95266e76
--- /dev/null
+++ b/engines/chamber/ega_resource.cpp
@@ -0,0 +1,90 @@
+/* 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 "common/debug.h"
+#include "common/error.h"
+#include "graphics/surface.h"
+
+#include "chamber/ega_resource.h"
+
+namespace Chamber {
+
+// Global instances (defined here, declared extern in ega_resource.h)
+EgaSpriteResource *ega_sprit_res = nullptr;
+EgaSpriteResource *ega_puzzl_res = nullptr;
+EgaSpriteResource *ega_perso_res = nullptr;
+
+// ---------------------------------------------------------------------------
+// EgaSpriteResource
+// ---------------------------------------------------------------------------
+
+EgaSpriteResource::EgaSpriteResource() {
+}
+
+EgaSpriteResource::~EgaSpriteResource() {
+ for (uint i = 0; i < _sprites.size(); i++) {
+ _sprites[i]->free();
+ delete _sprites[i];
+ }
+}
+
+void EgaSpriteResource::appendFromFile(const char *filename) {
+ Common::File fd;
+ if (!fd.open(filename))
+ error("EgaSpriteResource::appendFromFile: cannot open %s", filename);
+ appendFromStream(fd);
+}
+
+void EgaSpriteResource::appendFromStream(Common::SeekableReadStream &stream) {
+ stream.skip(4); // skip 4-byte junk header
+
+ while (!stream.eos()) {
+ uint16 size = stream.readUint16LE();
+ if (stream.eos())
+ break;
+
+ byte w = stream.readByte(); // width in 4-pixel units
+ byte h = stream.readByte(); // height in pixels
+
+ if (size < 4)
+ break;
+
+ uint16 dataSize = size - 4; // bytes of packed 4-bpp pixel data
+
+ // Allocate CLUT8 surface: actual pixel width = w * 4
+ Graphics::Surface *sprite = new Graphics::Surface();
+ sprite->create(w * 4, h, Graphics::PixelFormat::createFormatCLUT8());
+
+ byte *dst = (byte *)sprite->getPixels();
+
+ // Unpack packed 4-bpp: 2 pixels per byte
+ // Reference: kult/resource.cpp:100-103
+ for (uint16 i = 0; i < dataSize; i++) {
+ byte packed = stream.readByte();
+ *dst++ = (packed >> 4) & 0x0F; // high nibble = first pixel
+ *dst++ = packed & 0x0F; // low nibble = second pixel
+ }
+
+ _sprites.push_back(sprite);
+ }
+}
+
+} // End of namespace Chamber
diff --git a/engines/chamber/ega_resource.h b/engines/chamber/ega_resource.h
new file mode 100644
index 00000000000..3beee3b7938
--- /dev/null
+++ b/engines/chamber/ega_resource.h
@@ -0,0 +1,70 @@
+/* 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 CHAMBER_EGA_RESOURCE_H
+#define CHAMBER_EGA_RESOURCE_H
+
+#include "common/array.h"
+#include "common/file.h"
+#include "common/stream.h"
+#include "graphics/surface.h"
+
+namespace Chamber {
+
+// ---------------------------------------------------------------------------
+// EgaSpriteResource
+//
+// Loads a .EGA sprite bank file and decodes each sprite into a CLUT8
+// Graphics::Surface (w*4 wide à h pixels tall, 1 byte per pixel).
+//
+// On-disk format (reference: kult/resource.cpp, DumpEga_main.cpp):
+// 4 bytes â junk header (skip)
+// per sprite:
+// uint16 size â total byte count for this record (including the 4-byte header)
+// byte w â width in 4-pixel units â actual pixel width = w * 4
+// byte h â height in pixels
+// (size-4) bytes â packed 4-bpp pixel data, 2 pixels per byte:
+// pixel_hi = (byte >> 4) & 0x0F
+// pixel_lo = byte & 0x0F
+// ---------------------------------------------------------------------------
+class EgaSpriteResource {
+public:
+ EgaSpriteResource();
+ ~EgaSpriteResource();
+
+ void appendFromFile(const char *filename);
+ void appendFromStream(Common::SeekableReadStream &stream);
+
+ Graphics::Surface *getSprite(uint index) const { return _sprites[index]; }
+ uint getSpriteCount() const { return _sprites.size(); }
+
+private:
+ Common::Array<Graphics::Surface *> _sprites;
+};
+
+// Global EGA sprite banks (allocated in kult.cpp EGA init branch)
+extern EgaSpriteResource *ega_sprit_res; // SPRIT.EGA
+extern EgaSpriteResource *ega_puzzl_res; // PUZZL.EGA + PUZZ1.EGA
+extern EgaSpriteResource *ega_perso_res; // PERSO.EGA
+
+} // End of namespace Chamber
+
+#endif // CHAMBER_EGA_RESOURCE_H
diff --git a/engines/chamber/module.mk b/engines/chamber/module.mk
index 7aa82d1fd21..b319bbdf63e 100644
--- a/engines/chamber/module.mk
+++ b/engines/chamber/module.mk
@@ -5,6 +5,8 @@ MODULE_OBJS := \
bkbuff.o \
cga.o \
chamber.o \
+ ega.o \
+ ega_resource.o \
cursor.o \
decompr.o \
dialog.o \
Commit: 4b51672503deeacc62be7391ce25cf17bb24d9e0
https://github.com/scummvm/scummvm/commit/4b51672503deeacc62be7391ce25cf17bb24d9e0
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Add EGA engine initialization and resource loading
Wire EGA mode into ChamberEngine::init(): configure the 320x200 CLUT8 screen, load the EGA title screen (PRESEGA.EGA), and load sprite banks (SPRIT.EGA, PUZZL.EGA, PUZZ1.EGA, PERSO.EGA) via EgaSpriteResource.
Changed paths:
engines/chamber/chamber.cpp
engines/chamber/kult.cpp
engines/chamber/resdata.cpp
engines/chamber/resdata.h
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index a111fa8ac64..65eef6c6f5a 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -27,6 +27,7 @@
#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
+#include "common/rendermode.h"
#include "common/system.h"
#include "engines/util.h"
@@ -52,7 +53,15 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
_prioritycommand_1 = false;
_prioritycommand_2 = false;
_pxiData = NULL;
- _videoMode = Common::kRenderCGA;
+
+ // Read render mode from ScummVM settings (--render-mode command line flag).
+ // Supported: cga (default), herc, ega.
+ Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
+ if (renderMode == Common::kRenderEGA || renderMode == Common::kRenderHercG)
+ _videoMode = renderMode;
+ else
+ _videoMode = Common::kRenderCGA;
+
_screenH = _screenW = _screenBits = _screenBPL = _screenPPB = 0;
_line_offset = _line_offset2 = _fontHeight = _fontWidth = 0;
}
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index d97a05bb019..63187dd9262 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -27,6 +27,8 @@
#include "chamber/common.h"
#include "chamber/decompr.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
+#include "chamber/ega_resource.h"
#include "chamber/anim.h"
#include "chamber/cursor.h"
#include "chamber/input.h"
@@ -233,23 +235,37 @@ Common::Error ChamberEngine::init() {
// Initialize graphics using following:
bool isCustomHerc = false;
- if (_videoMode == Common::RenderMode::kRenderHercG) {
- isCustomHerc = true;
- _videoMode = Common::RenderMode::kRenderCGA;
- }
- _screenW = 320;
- _screenH = 200;
- _screenBits = 2;
- _screenPPB = 8 / _screenBits;
- _screenBPL = _screenW / _screenPPB;
- _line_offset = 0x2000;
- _line_offset2 = 0x2000;
- _fontHeight = 6;
- _fontWidth = 4;
- if (isCustomHerc) {
- initGraphics(720, 348);
- } else {
+ if (_videoMode == Common::RenderMode::kRenderEGA) {
+ // EGA: 320x200 CLUT8 linear framebuffer, 1 byte per pixel, no interlacing
+ _screenW = 320;
+ _screenH = 200;
+ _screenBits = 8;
+ _screenPPB = 1;
+ _screenBPL = _screenW;
+ _line_offset = 0;
+ _line_offset2 = 0;
+ _fontHeight = 6;
+ _fontWidth = 4;
initGraphics(_screenW, _screenH);
+ } else {
+ if (_videoMode == Common::RenderMode::kRenderHercG) {
+ isCustomHerc = true;
+ _videoMode = Common::RenderMode::kRenderCGA;
+ }
+ _screenW = 320;
+ _screenH = 200;
+ _screenBits = 2;
+ _screenPPB = 8 / _screenBits;
+ _screenBPL = _screenW / _screenPPB;
+ _line_offset = 0x2000;
+ _line_offset2 = 0x2000;
+ _fontHeight = 6;
+ _fontWidth = 4;
+ if (isCustomHerc) {
+ initGraphics(720, 348);
+ } else {
+ initGraphics(_screenW, _screenH);
+ }
}
initSound();
@@ -265,35 +281,52 @@ Common::Error ChamberEngine::init() {
Graphics::Surface *splash = nullptr;
- if (g_vm->getLanguage() == Common::EN_USA) {
- /* Load title screen */
- splash = loadSplash("PRESCGA.BIN");
- if (!splash)
- exitGame();
+ if (g_vm->_videoMode == Common::RenderMode::kRenderEGA) {
+ /* EGA title screen â load planar EGA splash (same format as FOND.EGA) */
+ splash = ega_loadFond("PRESEGA.EGA");
+ cga_ColorSelect(0x30); // sets EGA palette
+ if (splash)
+ cga_BackBufferToRealFull();
+ } else {
+ if (g_vm->getLanguage() == Common::EN_USA) {
+ /* Load title screen */
+ splash = loadSplash("PRESCGA.BIN");
+ if (!splash)
+ exitGame();
+
+ if (ifgm_loaded) {
+ /*TODO*/
+ }
+ } else {
+ /* Load title screen */
+ splash = loadSplash("PRES.BIN");
+ if (!splash)
+ exitGame();
+ }
- if (ifgm_loaded) {
- /*TODO*/
+ if (!isCustomHerc) {
+ /* Select intense cyan-mageta palette */
+ cga_ColorSelect(0x30);
+ cga_BackBufferToRealFull();
+ } else {
+ /* Set authentic Hercules Green phosphor palette */
+ g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
+ cga_BackBufferToRealFull();
}
- } else {
- /* Load title screen */
- splash = loadSplash("PRES.BIN");
- if (!splash)
- exitGame();
}
- if (!isCustomHerc) {
- /* Select intense cyan-mageta palette */
- cga_ColorSelect(0x30);
- cga_BackBufferToRealFull();
- } else {
- /* Set authentic Hercules Green phosphor palette */
- g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
- cga_BackBufferToRealFull();
+ if (splash) {
+ if (g_vm->_videoMode != Common::RenderMode::kRenderEGA)
+ splash->free();
+ delete splash;
}
+<<<<<<< HEAD
splash->free();
delete splash;
+=======
+>>>>>>> 6182990634e (chamber: Implement EGA rendering path)
/* Wait for a keypress */
clearKeyboard();
readKeyboardChar();
@@ -346,7 +379,7 @@ Common::Error ChamberEngine::init() {
if (!loadStaticData())
exitGame();
- /* Load text resources */
+/* Load text resources */
if (!loadVepciData() || !loadDesciData() || !loadDialiData())
exitGame();
@@ -354,8 +387,27 @@ Common::Error ChamberEngine::init() {
initInput();
/* Load graphics resources */
- while (!loadFond() || !loadSpritesData() || !loadPersData())
- askDisk2();
+ if (g_vm->_videoMode == Common::RenderMode::kRenderEGA) {
+ /* EGA: load decoded sprite banks from external .EGA files */
+ ega_sprit_res = new EgaSpriteResource();
+ ega_sprit_res->appendFromFile("SPRIT.EGA");
+
+ ega_puzzl_res = new EgaSpriteResource();
+ ega_puzzl_res->appendFromFile("PUZZL.EGA");
+ ega_puzzl_res->appendFromFile("PUZZ1.EGA");
+
+ ega_perso_res = new EgaSpriteResource();
+ ega_perso_res->appendFromFile("PERSO.EGA");
+
+ Graphics::Surface *fond = loadFond();
+ if (!fond)
+ exitGame();
+ /* fond wraps ega_backbuffer via init() â surface does not own pixel data, safe to delete directly */
+ delete fond;
+ } else {
+ while (!loadFond() || !loadSpritesData() || !loadPersData())
+ askDisk2();
+ }
/*TODO: is this necessary?*/
cga_BackBufferToRealFull();
diff --git a/engines/chamber/resdata.cpp b/engines/chamber/resdata.cpp
index 4fa7300a746..5836ff94100 100644
--- a/engines/chamber/resdata.cpp
+++ b/engines/chamber/resdata.cpp
@@ -26,6 +26,7 @@
#include "chamber/common.h"
#include "chamber/resdata.h"
#include "chamber/decompr.h"
+#include "chamber/ega.h"
namespace Chamber {
@@ -131,6 +132,25 @@ ResEntry_tp res_static[] = {
{"$", NULL}
};
+// EGA Kult2.pxi uses SOURI.EGA / GAUSS.EGA and stores the script template
+// data under "kultega.bin" instead of TEMPL.BIN
+ResEntry_tp res_static_ega[] = {
+ {"ARPLA.BIN", &arpla_data},
+ {"ALEAT.BIN", &aleat_data},
+ {"ICONE.BIN", &icone_data},
+ {"SOUCO.BIN", &souco_data},
+ {"CARPC.BIN", &carpc_data},
+ {"SOURI.EGA", &souri_data},
+ {"kultega.bin", &templ_data},
+ {"MURSM.BIN", &mursm_data},
+ {"GAUSS.EGA", &gauss_data},
+ {"LUTIN.BIN", &lutin_data},
+ {"ANIMA.BIN", &anima_data},
+ {"ANICO.BIN", &anico_data},
+ {"ZONES.BIN", &zones_data},
+ {"$", NULL}
+};
+
/*
Load resident data files. Original game has all these data files embedded in the executable.
NB! Static data includes the font file, don't use any text print routines before it's loaded.
@@ -138,7 +158,9 @@ NB! Static data includes the font file, don't use any text print routines before
int16 loadStaticData() {
Common::File pxi;
- if (g_vm->getLanguage() == Common::EN_USA)
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ pxi.open("Kult2.pxi");
+ else if (g_vm->getLanguage() == Common::EN_USA)
pxi.open("kult1.pxi");
else
pxi.open("ere.pxi");
@@ -206,23 +228,25 @@ int16 loadStaticData() {
warning("%s : %X", resName.c_str(), ress * 16 + reso);
+ ResEntry_tp *table = (g_vm->_videoMode == Common::kRenderEGA) ? res_static_ega : res_static;
int i;
- for (i = 0; res_static[i].name[0] != '$'; i++) { // Yeah, linear search
- if (!strcmp(res_static[i].name, resName.c_str())) {
- *res_static[i].buffer = rawData + off + ress * 16 + reso;
+ for (i = 0; table[i].name[0] != '$'; i++) { // Yeah, linear search
+ if (!strcmp(table[i].name, resName.c_str())) {
+ *table[i].buffer = rawData + off + ress * 16 + reso;
break;
}
}
- if (res_static[i].name[0] == '$')
+ if (table[i].name[0] == '$')
warning("loadStaticData(): Extra resource %s", resName.c_str());
}
// And now check that everything was loaded
+ ResEntry_tp *table = (g_vm->_videoMode == Common::kRenderEGA) ? res_static_ega : res_static;
bool missing = false;
- for (int i = 0; res_static[i].name[0] != '$'; i++) {
- if (*res_static[i].buffer == NULL) {
- warning("loadStaticData(): Resource %s is not present", res_static[i].name);
+ for (int i = 0; table[i].name[0] != '$'; i++) {
+ if (*table[i].buffer == NULL) {
+ warning("loadStaticData(): Resource %s is not present", table[i].name);
missing = true;
}
}
@@ -246,6 +270,8 @@ int16 loadVepciData() {
}
Graphics::Surface *loadFond(void) {
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return ega_loadFond("FOND.EGA");
return loadSplash("FOND.BIN");
}
diff --git a/engines/chamber/resdata.h b/engines/chamber/resdata.h
index df56e4bb05b..bd3992fd26c 100644
--- a/engines/chamber/resdata.h
+++ b/engines/chamber/resdata.h
@@ -27,12 +27,12 @@
namespace Chamber {
typedef struct ResEntry_t {
- char name[5 + 1 + 3 + 1];
+ char name[16];
void *buffer;
} ResEntry_t;
typedef struct ResEntry_tp {
- char name[5 + 1 + 3 + 1];
+ char name[16];
byte **buffer;
} ResEntry_tp;
Commit: a509e6c30711459bc03a840e4d69a81c16d0ee76
https://github.com/scummvm/scummvm/commit/a509e6c30711459bc03a840e4d69a81c16d0ee76
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Wire CGA dispatch layer to EGA for basic rendering
Add early-return EGA branches to all cga_* functions that touch the
screen (blitters, fill, backup/restore, line drawing, offset calc,
color select), redirecting to their ega_* counterparts without
changing any call sites.
Implement EGA cursor decoding for the SOURI.EGA format (two LE 16-bit planes per row: planeA = outline, planeB = fill; MSB = leftmost pixel). Skip the gauss animation in EGA mode (pre-rendered in FOND.EGA).
Changed paths:
engines/chamber/bkbuff.cpp
engines/chamber/cga.cpp
engines/chamber/cga.h
engines/chamber/cursor.cpp
engines/chamber/dialog.cpp
engines/chamber/timer.cpp
diff --git a/engines/chamber/bkbuff.cpp b/engines/chamber/bkbuff.cpp
index 2b44edbf0c3..99c416f0f59 100644
--- a/engines/chamber/bkbuff.cpp
+++ b/engines/chamber/bkbuff.cpp
@@ -24,7 +24,7 @@
namespace Chamber {
-byte backbuffer[0xB800]; ///< CGA: 0x4000, HGS: 0xB800
+byte backbuffer[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
} // End of namespace Chamber
diff --git a/engines/chamber/cga.cpp b/engines/chamber/cga.cpp
index 74e503d5357..a378a75d065 100644
--- a/engines/chamber/cga.cpp
+++ b/engines/chamber/cga.cpp
@@ -28,6 +28,8 @@
#include "chamber/input.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
+#include "chamber/ega_resource.h"
#include "common/debug.h"
@@ -63,8 +65,8 @@ uint16 HGA_CalcXY(uint16 x, uint16 y) {
return HGA_CalcXY_p(x / 4, y);
}
-extern byte backbuffer[0xB800]; ///< CGA: 0x4000, HGS: 0xB800
-byte CGA_SCREENBUFFER[0xB800];
+extern byte backbuffer[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
+byte CGA_SCREENBUFFER[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
Graphics::Surface *mainSurface = nullptr;
extern byte *scratch_mem2;
@@ -120,6 +122,10 @@ static const uint8 PALETTE_CGA2[4 * 3] = {
Switch to CGA 320x200x2bpp mode
*/
void switchToGraphicsMode(void) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_switchToGraphicsMode();
+ return;
+ }
if (g_system->getWidth() == 720) {
g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
} else {
@@ -136,10 +142,17 @@ void switchToTextMode(void) {
void waitVBlank(void) {
pollInput();
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ ega_blitToScreen(0, 0, 320, 200);
g_system->delayMillis(10);
+ g_system->updateScreen();
}
void cga_ColorSelect(byte csel) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_switchToGraphicsMode();
+ return;
+ }
if (g_system->getWidth() == 720) {
g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
g_system->setCursorPalette(Graphics::HGC_G_PALETTE, 0, 2);
@@ -156,6 +169,10 @@ void cga_ColorSelect(byte csel) {
}
void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_blitToScreen(dx, dy, w, h);
+ return;
+ }
if (!mainSurface) {
mainSurface = new Graphics::Surface();
}
@@ -253,6 +270,12 @@ void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
}
void cga_blitToScreen(int16 ofs, int16 w, int16 h) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ int16 dy = ofs / EGA_BYTES_PER_LINE;
+ int16 dx = ofs % EGA_BYTES_PER_LINE;
+ ega_blitToScreen(dx, dy, w, h);
+ return;
+ }
uint16 byte_per_line = w / (0x8 / g_vm->_screenBits);
int16 dy = ofs / byte_per_line;
int16 dx = (ofs % byte_per_line) * (0x8 / g_vm->_screenBits);
@@ -261,6 +284,10 @@ void cga_blitToScreen(int16 ofs, int16 w, int16 h) {
}
void cga_BackBufferToRealFull(void) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_BackBufferToRealFull();
+ return;
+ }
if (g_vm->_videoMode == Common::RenderMode::kRenderCGA) {
memcpy(CGA_SCREENBUFFER, backbuffer, sizeof(backbuffer));
@@ -296,12 +323,20 @@ void cga_BackBufferToRealFull(void) {
}
void cga_RealBufferToBackFull(void) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_RealBufferToBackFull();
+ return;
+ }
memcpy(backbuffer, CGA_SCREENBUFFER, sizeof(backbuffer));
}
/*Copy interlaced screen data to another screen*/
/*NB! w is in bytes*/
void cga_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, w * 4, h, target, ofs);
+ return;
+ }
uint16 oh = h;
uint16 oofs = ofs;
while (h--) {
@@ -319,6 +354,10 @@ void cga_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16
Flip screen and backbuffer
*/
void cga_SwapRealBackBuffer(void) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_SwapRealBackBuffer();
+ return;
+ }
uint16 i;
uint16 *s, *d;
waitVBlank();
@@ -338,6 +377,10 @@ void cga_SwapRealBackBuffer(void) {
Copy current screen's pixels to scratch mem, put new pixels to screen
*/
void cga_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_SwapScreenRect(pixels, w * 4, h, screen, ofs);
+ return;
+ }
byte *old = scratch_mem2;
uint16 oh = h;
uint16 oofs = ofs;
@@ -366,7 +409,9 @@ uint16 cga_CalcXY(uint16 x, uint16 y) {
}
uint16 CalcXY(uint16 x, uint16 y) {
- if (g_vm->_videoMode == Common::RenderMode::kRenderCGA)
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return ega_CalcXY(x, y);
+ else if (g_vm->_videoMode == Common::RenderMode::kRenderCGA)
return cga_CalcXY(x, y);
else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG)
return HGA_CalcXY(x, y);
@@ -375,7 +420,9 @@ uint16 CalcXY(uint16 x, uint16 y) {
}
uint16 CalcXY_p(uint16 x, uint16 y) {
- if (g_vm->_videoMode == Common::RenderMode::kRenderCGA)
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return ega_CalcXY_p(x, y);
+ else if (g_vm->_videoMode == Common::RenderMode::kRenderCGA)
return cga_CalcXY_p(x, y);
else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG)
return HGA_CalcXY_p(x, y);
@@ -403,6 +450,8 @@ Out:
next buffer ptr
*/
byte *cga_BackupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return ega_BackupImage(screen, ofs, w * 4, h, buffer);
*(byte *)(buffer + 0) = h;
*(byte *)(buffer + 1) = w;
*(uint16 *)(buffer + 2) = ofs;
@@ -426,6 +475,10 @@ Blit progressive image to interlaced screen buffer
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
void cga_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_Blit(pixels, pw * 4, w * 4, h, screen, ofs);
+ return;
+ }
byte *src = pixels;
uint16 oofs = ofs;
for (int16 y = 0; y < h; y++) {
@@ -450,6 +503,10 @@ void cga_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen,
}
void cga_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_Fill(cga_to_ega_color[(pixel >> 6) & 0x03], w * 4, h, screen, ofs);
+ return;
+ }
uint16 oofs = ofs;
for (int16 y = 0; y < h; y++) {
memset(screen + ofs, pixel, w);
@@ -471,6 +528,10 @@ void cga_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
Restore saved image to target screen buffer
*/
void cga_RestoreImage(byte *buffer, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_RestoreImage(buffer, target);
+ return;
+ }
uint16 w, h;
uint16 ofs;
@@ -496,6 +557,10 @@ void cga_RestoreBackupImage(byte *target) {
Copy image's real screen data to backbuffer
*/
void cga_RefreshImageData(byte *buffer) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_RefreshImageData(buffer);
+ return;
+ }
uint16 w, h;
uint16 ofs;
@@ -514,6 +579,10 @@ Draw a vertical line with origin x:y and length l, using color
NB! Line must not wrap around the edge
*/
void cga_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_DrawVLine(x, y, l, cga_to_ega_color[color & 0x03], target);
+ return;
+ }
uint16 ofs;
uint16 mask = 0;
/*pixels are starting from top bits of byte*/
@@ -546,6 +615,10 @@ Draw a horizontal line with origin x:y and length l, using color
NB! Line must not wrap around the edge
*/
void cga_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_DrawHLine(x, y, l, cga_to_ega_color[color & 0x03], target);
+ return;
+ }
uint16 ofs;
uint16 mask = 0;
/*pixels are starting from top bits of byte*/
@@ -587,6 +660,8 @@ Return next line screen offset
NB! Length specifies byte length of inner segment, not amount of pixels
*/
uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return ega_DrawHLineWithEnds(bmask, bpix, color, l, target, ofs);
target[ofs] = (target[ofs] & (bmask >> 8)) | (bpix >> 8);
memset(target + ofs + 1, color, l);
target[ofs + 1 + l] = (target[ofs + 1 + l] & (bmask & 255)) | (bpix & 255);
@@ -605,6 +680,10 @@ uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, by
Print a character at current cursor pos, then advance
*/
void cga_PrintChar(byte c, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_PrintChar(c, target);
+ return;
+ }
uint16 i;
byte *font = carpc_data + c * g_vm->_fontHeight;
@@ -644,6 +723,11 @@ NB! width specify a number of bytes, not count of pixels
TODO: generalize/merge me with BlitSprite
*/
void cga_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ // sprofs is in CGA mask+pixel bytes (2 per CGA unit); EGA needs 4 bytes per CGA unit, so *2
+ ega_BlitScratchBackSprite(sprofs * 2, w * 4, h, screen, ofs);
+ return;
+ }
byte x;
byte *pixels = scratch_mem2 + 2 + sprofs;
uint16 oh = h;
@@ -662,6 +746,10 @@ void cga_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen,
}
void cga_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_BlitFromBackBuffer(w * 4, h, screen, ofs);
+ return;
+ }
cga_CopyScreenBlock(backbuffer, w, h, screen, ofs);
}
@@ -670,6 +758,29 @@ Blit progressive sprite (mask+pixel) to interlaced screen buffer
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
void cga_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ // pixels are CGA mask+pixel pairs: pixels[x*2]=mask, pixels[x*2+1]=color (2bpp packed)
+ // Decode each CGA byte (4 pixels) into 4 CLUT8 EGA pixels.
+ // mask bit pair 0x00 = draw pixel, non-zero = keep background.
+ uint16 oofs = ofs;
+ for (uint16 row = 0; row < h; row++) {
+ for (uint16 bx = 0; bx < w; bx++) {
+ byte mb = pixels[bx * 2];
+ byte cb = pixels[bx * 2 + 1];
+ for (int p = 3; p >= 0; p--) {
+ byte m = (mb >> (p * 2)) & 0x03;
+ byte c = (cb >> (p * 2)) & 0x03;
+ if (m == 0)
+ screen[ofs + bx * 4 + (3 - p)] = cga_to_ega_color[c];
+ }
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w * 4, h);
+ return;
+ }
byte x;
uint16 oh = h;
uint16 oofs = ofs;
@@ -691,6 +802,31 @@ Blit progressive sprite (mask+pixel) to interlaced screen buffer. Flip the sprit
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
void cga_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ // Same as cga_BlitSprite but pixels are drawn right-to-left (horizontal flip).
+ // CGA ofs points to the rightmost byte of the sprite row on screen.
+ uint16 oofs = ofs;
+ for (uint16 row = 0; row < h; row++) {
+ for (uint16 bx = 0; bx < w; bx++) {
+ byte mb = pixels[bx * 2];
+ byte cb = pixels[bx * 2 + 1];
+ // bx=0 is rightmost group of 4 pixels, bx=w-1 is leftmost
+ for (int p = 3; p >= 0; p--) {
+ byte m = (mb >> (p * 2)) & 0x03;
+ byte c = (cb >> (p * 2)) & 0x03;
+ // pixel bx*4+(3-p) in sprite goes to screen position -(bx*4+(3-p))
+ if (m == 0)
+ screen[ofs - (bx * 4 + (3 - p))] = cga_to_ega_color[c];
+ }
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+ uint16 startX = (oofs % EGA_BYTES_PER_LINE) - (w * 4 - 1);
+ if (screen == ega_screen)
+ ega_blitToScreen(startX, oofs / EGA_BYTES_PER_LINE, w * 4, h);
+ return;
+ }
byte x;
uint16 oh = h;
uint16 oofs = ofs;
@@ -716,6 +852,10 @@ NB! width and pixelswidth specify a number of bytes, not count of pixels
NB! pixel+mask comes in reversed order, compared to regular BlitSprite
*/
void cga_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_BlitSpriteBak(pixels, pw * 4, w * 4, h, screen, ofs, backup, mask);
+ return;
+ }
byte x;
uint16 oh = h;
uint16 oofs = ofs;
@@ -736,9 +876,15 @@ void cga_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen,
/*
-Blit progressive sprite (w+h+mask+pixel) to interlaced screen buffer
+Blit progressive sprite (w+h+mask+pixel) to interlaced screen buffer.
+In EGA mode sprite is a decoded CLUT8 Graphics::Surface; w and h come from it.
*/
void drawSprite(byte *sprite, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
+ ega_BlitSprite((byte *)surf->getPixels(), surf->pitch, surf->w, surf->h, screen, ofs);
+ return;
+ }
byte w, h;
w = *sprite++;
h = *sprite++;
@@ -746,9 +892,15 @@ void drawSprite(byte *sprite, byte *screen, uint16 ofs) {
}
/*
-Blit progressive sprite (w+h+mask+pixel) to interlaced screen buffer, horizontally flipped
+Blit progressive sprite (w+h+mask+pixel) to interlaced screen buffer, horizontally flipped.
+In EGA mode sprite is a decoded CLUT8 Graphics::Surface.
*/
void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
+ ega_BlitSpriteFlip((byte *)surf->getPixels(), surf->pitch, surf->w, surf->h, screen, ofs);
+ return;
+ }
byte w, h;
w = *sprite++;
h = *sprite++;
@@ -838,14 +990,18 @@ byte *loadSprite(byte index, byte *bank, byte *buffer, byte header_only) {
extern byte sprit_data[RES_SPRIT_MAX];
-byte sprit_load_buffer[1290];
+byte sprit_load_buffer[8192];
byte *loadSprit(byte index) {
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return reinterpret_cast<byte *>(ega_sprit_res->getSprite(index));
loadSprite(index, sprit_data + 4, sprit_load_buffer, 0);
return sprit_load_buffer;
}
byte *loadPersSprit(byte index) {
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return reinterpret_cast<byte *>(ega_perso_res->getSprite(index));
#if 1
/*Use separate memory for pers1/pers2*/
if (index < 61)
@@ -878,14 +1034,20 @@ void drawSpriteNFlip(byte index, uint16 x, uint16 y, byte *target) {
}
void backupAndShowSprite(byte index, byte x, byte y) {
- byte w, h;
- uint16 ofs;
byte *sprite = loadSprit(index);
- ofs = CalcXY_p(x, y);
- w = sprite[0];
- h = sprite[1];
+ uint16 ofs = CalcXY_p(x, y);
+
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
+ ega_BackupImage(ega_screen, ofs, surf->w, surf->h, scratch_mem2);
+ drawSprite(sprite, ega_screen, ofs);
+ return;
+ }
+
+ byte w = sprite[0];
+ byte h = sprite[1];
cga_BackupImageReal(ofs, w, h);
- drawSprite(sprite, CGA_SCREENBUFFER, ofs); /*DrawSpriteN(index, x, y, CGA_SCREENBUFFER);*/
+ drawSprite(sprite, CGA_SCREENBUFFER, ofs);
}
/*
@@ -895,6 +1057,15 @@ NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
void cga_AnimLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 i;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ uint16 epw = pw * 4;
+ pixels += epw * (h - 1);
+ for (i = 1; i <= h; i++) {
+ ega_BlitAndWait(pixels, epw, w * 4, i, screen, ofs);
+ pixels -= epw;
+ }
+ return;
+ }
pixels += pw * (h - 1);
for (i = 1; i <= h; i++) {
cga_BlitAndWait(pixels, pw, w, i, screen, ofs);
@@ -910,6 +1081,13 @@ NB! ofs specifies top-right corner of the image
*/
void cga_AnimLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 i;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ for (i = 0; i < n; i++) {
+ ega_BlitAndWait(pixels, pw * 4, (w + i) * 4, h, screen, ofs);
+ ofs -= 4;
+ }
+ return;
+ }
for (i = 0; i < n; i++) {
cga_BlitAndWait(pixels, pw, w + i, h, screen, ofs);
ofs -= 1;
@@ -923,6 +1101,13 @@ NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
void cga_AnimLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 i;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ for (i = 0; i < n; i++) {
+ ega_BlitAndWait(pixels, pw * 4, (w + i) * 4, h, screen, ofs);
+ pixels -= 4;
+ }
+ return;
+ }
for (i = 0; i < n; i++) {
cga_BlitAndWait(pixels, pw, w + i, h, screen, ofs);
pixels -= 1;
@@ -937,6 +1122,14 @@ NB! x:y specifies left-bottom coords
*/
void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) {
uint16 i;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ uint16 epw = pw * 4;
+ for (i = 1; i <= h; i++) {
+ ega_BlitAndWait(pixels, epw, w * 4, i, screen, ega_CalcXY_p(x, y));
+ y -= 1;
+ }
+ return;
+ }
for (i = 1; i <= h; i++) {
cga_BlitAndWait(pixels, pw, w, i, screen, cga_CalcXY_p(x, y));
y -= 1;
@@ -948,6 +1141,10 @@ void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen,
/*offs points to block's bottom most line, data will be shifted to next line*/
/*NB! w is in bytes*/
void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, w * 4, h + n, target, ofs);
+ return;
+ }
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -993,6 +1190,10 @@ void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16
/*offs points to block's top most line, data will be shifted to previous line*/
/*NB! w is in bytes*/
void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, w * 4, h + n, target, ofs);
+ return;
+ }
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1038,6 +1239,10 @@ void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w,
/*offs points to block's left most column, data will be shifted to previous column*/
/*NB! w is in bytes*/
void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, (w + n) * 4, h, target, ofs - n * 4);
+ return;
+ }
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1075,6 +1280,10 @@ void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16
/*offs points to block's right most column, data will be shifted to next column*/
/*NB! w is in bytes*/
void cga_HideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, (w + n) * 4, h, target, ofs - w * 4);
+ return;
+ }
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1250,12 +1459,36 @@ static void fallPieces(scrpiece_t *pieces, byte *source, byte *target) {
}
void cga_HideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, w * 4, h, target, ofs);
+ return;
+ }
scrpiece_t *pieces = (scrpiece_t *)scratch_mem2;
screenToPieces(w, h, screen, ofs, pieces);
fallPieces(pieces, source, target);
}
void cga_TraceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* EGA: Bresenham pixel-by-pixel copy from source to target */
+ int16 x0 = sx, y0 = sy, x1 = ex, y1 = ey;
+ int16 ddx = (x1 >= x0) ? 1 : -1;
+ int16 ddy = (y1 >= y0) ? 1 : -1;
+ int16 abw = (x1 >= x0) ? (x1 - x0) : (x0 - x1);
+ int16 abh = (y1 >= y0) ? (y1 - y0) : (y0 - y1);
+ int16 err = abw - abh;
+ for (;;) {
+ uint16 o = y0 * EGA_BYTES_PER_LINE + x0;
+ if (o < EGA_SCREEN_SIZE)
+ target[o] = source[o];
+ if (x0 == x1 && y0 == y1) break;
+ int16 e2 = err * 2;
+ if (e2 > -abh) { err -= abh; x0 += ddx; }
+ if (e2 < abw) { err += abw; y0 += ddy; }
+ }
+ /* Screen blit is done by the caller at the appropriate cadence */
+ return;
+ }
byte b0 = 0;
byte b1 = 0;
byte mask;
@@ -1520,6 +1753,11 @@ Use backbuffer pixels to fill sides
NB! w/nw are the number of bytes, not pixels
*/
void cga_ZoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* EGA: instant blit at original size, skip zoom */
+ ega_BlitAndWait(pixels, w * 4, w * 4, h, target, ofs);
+ return;
+ }
zoom_t zoom;
zoom.pixels = pixels;
@@ -1586,6 +1824,10 @@ NB! w is the number of bytes, not pixels
NB! ofs is the final image top left corner, not the zoom origin
*/
void cga_AnimZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_BlitAndWait(pixels, w * 4, w * 4, h, target, ofs);
+ return;
+ }
uint16 finofs = ofs;
byte x, y, maxside;
@@ -1689,6 +1931,10 @@ void cga_ZoomInplace(zoom_t *params, byte tw, byte th, byte *source, byte *targe
}
void cga_ZoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_Blit(pixels, w * 4, w * 4, h, target, CalcXY_p(x, y));
+ return;
+ }
zoom_t zoom;
zoom.pixels = pixels;
diff --git a/engines/chamber/cga.h b/engines/chamber/cga.h
index 911180674b5..ab6c2acabae 100644
--- a/engines/chamber/cga.h
+++ b/engines/chamber/cga.h
@@ -59,7 +59,7 @@ namespace Chamber {
#define CGA_PIXELS_PER_BYTE (8 / CGA_BITS_PER_PIXEL)
#define CGA_BYTES_PER_LINE (CGA_WIDTH / CGA_PIXELS_PER_BYTE)
-extern byte CGA_SCREENBUFFER[0xB800];
+extern byte CGA_SCREENBUFFER[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
#define CGA_FONT_HEIGHT 6
@@ -67,9 +67,9 @@ extern byte CGA_SCREENBUFFER[0xB800];
#define CGA_PREV_LINE(offs) ((CGA_ODD_LINES_OFS ^ (offs)) - (((offs) & CGA_ODD_LINES_OFS) ? CGA_BYTES_PER_LINE : 0))
#define frontbuffer CGA_SCREENBUFFER
-extern byte backbuffer[0xB800]; ///< CGA: 0x4000, HGS: 0xB800
+extern byte backbuffer[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
-extern byte sprit_load_buffer[1290];
+extern byte sprit_load_buffer[8192];
extern byte cga_pixel_flip[256];
diff --git a/engines/chamber/cursor.cpp b/engines/chamber/cursor.cpp
index 5ee65824b28..022097dbf00 100644
--- a/engines/chamber/cursor.cpp
+++ b/engines/chamber/cursor.cpp
@@ -26,6 +26,7 @@
#include "chamber/cursor.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
namespace Chamber {
@@ -66,31 +67,60 @@ Select cursor shape and its hotspot
void selectCursor(uint16 num) {
cursor_x_shift = cursor_shifts[num][0];
cursor_y_shift = cursor_shifts[num][1];
- cursor_shape = souri_data + num * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / g_vm->_screenPPB;
- byte *src = cursor_shape;
byte *dst = cursorImage;
- for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
- for (int16 x = 0; x < CURSOR_HEIGHT / 4; x++) {
- byte colors = *src;
- byte masks = *(src++ + CURSOR_HEIGHT * CURSOR_WIDTH / 4);
-
- for (int16 c = 0; c < 4; c++) {
- byte color = (colors & 0xC0) >> 6;
- byte mask = (masks & 0xC0) >> 6;
- colors <<= 2;
- masks <<= 2;
-
- if (!mask)
- *dst++ = color;
- else {
- *dst++ = 255;
+
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ // EGA SOURI.EGA: 64 bytes/cursor, 4 bytes per row.
+ // Each row = two little-endian 16-bit planes:
+ // planeA (bytes 0,1): outline/black mask (bit set = black pixel)
+ // planeB (bytes 2,3): fill/white mask (bit set = white pixel)
+ // MSB of each word = leftmost pixel (pixel 0).
+ // A=0,B=0 â transparent; A=1,B=0 â black (EGA 0); A=0/1,B=1 â white (EGA 15).
+ cursor_shape = souri_data + num * (CURSOR_WIDTH * CURSOR_HEIGHT / 4);
+ byte *src = cursor_shape;
+ for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
+ uint16 planeA = (uint16)src[0] | ((uint16)src[1] << 8);
+ uint16 planeB = (uint16)src[2] | ((uint16)src[3] << 8);
+ src += 4;
+ for (int16 x = 0; x < CURSOR_WIDTH; x++) {
+ byte bitA = (planeA >> (CURSOR_WIDTH - 1 - x)) & 1;
+ byte bitB = (planeB >> (CURSOR_WIDTH - 1 - x)) & 1;
+ if (!bitA && !bitB)
+ *dst++ = 255; // transparent
+ else if (bitB)
+ *dst++ = 15; // white
+ else
+ *dst++ = 0; // black
+ }
+ }
+ } else {
+ cursor_shape = souri_data + num * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / 4;
+ byte *src = cursor_shape;
+ for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
+ for (int16 x = 0; x < CURSOR_HEIGHT / 4; x++) {
+ byte colors = *src;
+ byte masks = *(src++ + CURSOR_HEIGHT * CURSOR_WIDTH / 4);
+
+ for (int16 c = 0; c < 4; c++) {
+ byte color = (colors & 0xC0) >> 6;
+ byte mask = (masks & 0xC0) >> 6;
+ colors <<= 2;
+ masks <<= 2;
+
+ if (!mask)
+ *dst++ = color;
+ else {
+ *dst++ = 255;
+ }
}
}
}
}
g_system->setMouseCursor(cursorImage, CURSOR_WIDTH, CURSOR_HEIGHT, cursor_x_shift, cursor_y_shift, 255);
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ g_system->setCursorPalette(EGA_PALETTE, 0, 16);
g_system->showMouse(true);
}
diff --git a/engines/chamber/dialog.cpp b/engines/chamber/dialog.cpp
index 97677e6c89c..c9444dbbdcb 100644
--- a/engines/chamber/dialog.cpp
+++ b/engines/chamber/dialog.cpp
@@ -26,6 +26,7 @@
#include "chamber/dialog.h"
#include "chamber/print.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
#include "chamber/script.h"
#include "chamber/cursor.h"
#include "chamber/input.h"
@@ -187,6 +188,8 @@ void showPromptAnim(void) {
}
void promptWait(void) {
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ ega_blitToScreen(0, 0, 320, 200);
cursor_anim_phase = 0;
do {
diff --git a/engines/chamber/timer.cpp b/engines/chamber/timer.cpp
index a37472ca93f..2a2bb17bee1 100644
--- a/engines/chamber/timer.cpp
+++ b/engines/chamber/timer.cpp
@@ -32,6 +32,10 @@ namespace Chamber {
void animateGauss(byte *target) {
+ // In EGA mode, the gauss animation tiles are CGA format data.
+ // The EGA background (FOND.EGA) already includes the gauss area pre-rendered.
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ return;
byte *sprite;
byte phase = getRand() % 4;
if (phase == script_byte_vars.gauss_phase)
Commit: 9d5a91b29c5de667408a64426098eae94d6559c3
https://github.com/scummvm/scummvm/commit/9d5a91b29c5de667408a64426098eae94d6559c3
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Extend EGA rendering to animation, portrait, room, and script
Add ega_makePortraitFrame() and ega_loadPortrait() to composite CLUT8 person sprites onto portrait frames. Fix SCR_1B/SCR_1C (portrait hide animations) to use the dirty-rect offset directly instead of the CGA
bottom-up recalculation, which would leave most of the portrait unrestored.
Add EGA screen flush after each step of trace-line intro animations and
the starfield. Handle room background restore from the clean FOND.EGA copy. Disable zoom in SCR_ZoomPortrait (EGA sprites are not in scalable CGA format).
Changed paths:
engines/chamber/anim.cpp
engines/chamber/portrait.cpp
engines/chamber/room.cpp
engines/chamber/script.cpp
diff --git a/engines/chamber/anim.cpp b/engines/chamber/anim.cpp
index 5c249123656..cbf1f762e26 100644
--- a/engines/chamber/anim.cpp
+++ b/engines/chamber/anim.cpp
@@ -26,6 +26,7 @@
#include "chamber/common.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
#include "chamber/room.h"
#include "chamber/sound.h"
@@ -73,6 +74,9 @@ void animLoadSprite(byte **panim) {
void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx, int8 dy) {
if (anim_flags == 7)
return;
+ // In EGA mode, lutin_mem CLUT8 buffer has 4 bytes per column (1 byte/pixel à 4 pixels).
+ // In CGA mode, mask+pixel pairs give 2 bytes per column.
+ uint16 bytes_per_col = (g_vm->_videoMode == Common::kRenderEGA) ? 4 : 2;
if (anim_flags & 4) {
if (anim_cycle == 0)
return;
@@ -87,7 +91,7 @@ void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx
anim_cycle--;
} else {
*x -= dx;
- *sprite += (*sprw - anim_cycle) * 2;
+ *sprite += (*sprw - anim_cycle) * bytes_per_col;
*sprw = anim_cycle;
anim_cycle--;
}
@@ -99,7 +103,7 @@ void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx
anim_cycle++;
} else {
*x -= dx;
- *sprite += (*sprw - anim_cycle) * 2;
+ *sprite += (*sprw - anim_cycle) * bytes_per_col;
*sprw = anim_cycle;
anim_cycle++;
}
@@ -107,6 +111,10 @@ void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx
}
void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte height, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_CopyScreenBlock(source, width * 4, height, target, ega_CalcXY_p(x, y));
+ return;
+ }
uint16 offs;
uint16 xx = x * 4;
uint16 ww = width * 4;
@@ -134,7 +142,13 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
byte ex, ey, updx, updy, updw, updh;
uint16 ofs = CalcXY_p(x, y);
cga_BackupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
- cga_BlitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ // In EGA mode, loadLutinSprite builds a CLUT8 flat buffer in lutin_mem+2.
+ // pitch here is sprw*4 (set in playAnimCore for EGA).
+ ega_BlitSprite(pixels, pitch, (uint16)sprw * 4, sprh, backbuffer, ofs);
+ } else {
+ cga_BlitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
+ }
ex = x + sprw;
ey = y + sprh;
if (last_anim_height != 0) {
@@ -216,7 +230,10 @@ void playAnimCore(byte **panim) {
sprw = *sprite++;
sprh = *sprite++;
- pitch = sprw * 2;
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ pitch = sprw * 4;
+ else
+ pitch = sprw * 2;
clipSprite(&x, &y, &sprw, &sprh, &sprite, dx, dy);
animDrawSprite(x, y, sprw, sprh, sprite, pitch);
diff --git a/engines/chamber/portrait.cpp b/engines/chamber/portrait.cpp
index a01676b02fd..d96c512312a 100644
--- a/engines/chamber/portrait.cpp
+++ b/engines/chamber/portrait.cpp
@@ -19,12 +19,17 @@
*
*/
+#include "common/system.h"
+#include "common/rendermode.h"
+#include "graphics/surface.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/portrait.h"
#include "chamber/resdata.h"
#include "chamber/room.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
+#include "chamber/ega_resource.h"
#include "chamber/script.h"
#include "chamber/dialog.h"
#include "chamber/input.h"
@@ -154,9 +159,111 @@ byte *loadPortrait(byte **pinfo, byte *end) {
return sprit_load_buffer + 2;
}
+/* Expand a CGA 2bpp packed byte into 4 CLUT8 EGA pixels */
+static void ega_expandCgaByte(byte cgaByte, byte *dst) {
+ for (int p = 3; p >= 0; p--)
+ *dst++ = cga_to_ega_color[(cgaByte >> (p * 2)) & 0x03];
+}
+
+/*
+Build portrait frame in CLUT8 format for EGA mode.
+Pixel width = pframe->width * 4, stored row by row.
+Header bytes: [height][width_cga] to stay compatible with existing callers.
+*/
+static void ega_makePortraitFrame(byte index, byte *target) {
+ persframe_t *pf = &pers_frames[index];
+ uint16 pw = pf->width * 4; // pixel width
+ byte fillCol = cga_to_ega_color[(pf->fill >> 6) & 0x03];
+ debug(1, "ega_makePortraitFrame: frame=%d h=%d w=%d fillEGA=%d", index, pf->height, pf->width, fillCol);
+
+ *target++ = pf->height;
+ *target++ = pf->width; // CGA-unit width for compatibility
+ cur_frame_width = pf->width;
+
+ // Top border row
+ for (uint16 x = 0; x < pf->width; x++)
+ ega_expandCgaByte(pf->topbot, target + x * 4);
+ target += pw;
+
+ // Middle rows
+ for (uint16 i = 0; i < pf->height - 2; i++) {
+ ega_expandCgaByte(pf->left, target);
+ // Fill middle with solid color from fill byte
+ byte fillCol2 = cga_to_ega_color[(pf->fill >> 6) & 0x03];
+ memset(target + 4, fillCol2, (pf->width - 2) * 4);
+ ega_expandCgaByte(pf->right, target + (pf->width - 1) * 4);
+ target += pw;
+ }
+
+ // Bottom border row
+ for (uint16 x = 0; x < pf->width; x++)
+ ega_expandCgaByte(pf->topbot, target + x * 4);
+}
+
+/*
+Composite CLUT8 pers sprites onto EGA portrait frame.
+Sprites from ega_perso_res are already decoded CLUT8 Graphics::Surface.
+*/
+static byte *ega_loadPortrait(byte **pinfo, byte *end) {
+ uint16 frame_pw = cur_frame_width * 4; // pixel width of frame
+
+ while (*pinfo != end) {
+ byte index;
+ uint16 flags;
+
+ index = *((*pinfo)++);
+ flags = *((*pinfo)++);
+ flags |= (*((*pinfo)++)) << 8;
+
+ Graphics::Surface *surf = ega_perso_res->getSprite(index);
+ byte *src = (byte *)surf->getPixels();
+ uint16 sw = surf->w;
+ uint16 sh = surf->h;
+ int16 spitch = surf->pitch;
+
+ // Decode CGA byte offset to row/col in the frame
+ uint16 cga_ofs = flags & 0x3FFF;
+ uint16 row = cga_ofs / cur_frame_width;
+ uint16 col_cga = cga_ofs % cur_frame_width;
+ byte *dst = sprit_load_buffer + 2 + 2 + row * frame_pw + col_cga * 4;
+
+ if (flags & 0x8000) { // vertical flip
+ src += spitch * (sh - 1);
+ spitch = -spitch;
+ }
+
+ if (flags & 0x4000) { // horizontal flip
+ for (uint16 y = 0; y < sh; y++) {
+ for (uint16 x = 0; x < sw; x++) {
+ byte p = src[sw - 1 - x];
+ if (p != 0)
+ dst[x] = p;
+ }
+ src += spitch;
+ dst += frame_pw;
+ }
+ } else {
+ for (uint16 y = 0; y < sh; y++) {
+ for (uint16 x = 0; x < sw; x++) {
+ byte p = src[x];
+ if (p != 0)
+ dst[x] = p;
+ }
+ src += spitch;
+ dst += frame_pw;
+ }
+ }
+ }
+ return sprit_load_buffer + 2;
+}
+
byte *loadPortraitWithFrame(byte index) {
byte *pinfo, *end;
pinfo = seekToEntry(icone_data, index, &end);
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_makePortraitFrame(*pinfo++, sprit_load_buffer + 2);
+ return ega_loadPortrait(&pinfo, end);
+ }
makePortraitFrame(*pinfo++, sprit_load_buffer + 2);
return loadPortrait(&pinfo, end);
}
@@ -233,12 +340,18 @@ void drawBoxAroundSpot(void) {
ofs = *(uint16 *)(buffer + 2);
/*decode ofs back to x:y*/
- /*TODO: this is CGA-only!*/
- y = (ofs & g_vm->_line_offset) ? 1 : 0;
- ofs &= ~g_vm->_line_offset;
- x = (ofs % g_vm->_screenBPL) * g_vm->_screenPPB;
- y += (ofs / g_vm->_screenBPL) * 2;
- w *= g_vm->_screenPPB; /*TODO: this will overflow on large sprite*/
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* EGA: linear layout, offset = y * 320 + x */
+ y = ofs / EGA_BYTES_PER_LINE;
+ x = ofs % EGA_BYTES_PER_LINE;
+ w *= 4; /* w was stored in CGA byte units */
+ } else {
+ y = (ofs & g_vm->_line_offset) ? 1 : 0;
+ ofs &= ~g_vm->_line_offset;
+ x = (ofs % g_vm->_screenBPL) * g_vm->_screenPPB;
+ y += (ofs / g_vm->_screenBPL) * 2;
+ w *= g_vm->_screenPPB;
+ }
cga_DrawVLine(x, y, h - 1, 0, CGA_SCREENBUFFER);
cga_DrawHLine(x, y, w - 1, 0, CGA_SCREENBUFFER);
@@ -258,8 +371,9 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
index = *((*desc)++);
if (index == 0xFF) {
- if (script_byte_vars.dirty_rect_kind != 0)
+ if (script_byte_vars.dirty_rect_kind != 0) {
return 0;
+ }
drawBoxAroundSpot();
if (!selectCurrentAnim(&xx, &yy, &index))
return 0;
@@ -270,6 +384,7 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
cur_image_coords_x = xx;
cur_image_coords_y = yy;
cur_image_idx = index;
+ debug(1, "drawPortrait: index=%d x=%d y=%d (pixel x=%d y=%d)", index, xx, yy, xx * 4, yy);
image = loadPortraitWithFrame(index - 1);
cur_image_size_h = *image++;
@@ -320,9 +435,8 @@ volatile byte vblank_ticks;
void waitVBlankTimer(void) {
if (g_vm->getLanguage() == Common::EN_USA) {
- /*A crude attempt to fix the animation speed...*/
- while (vblank_ticks < 3) ;
- vblank_ticks = 0;
+ /*Simulate 3 vblank ticks (~50ms) since vblank_ticks is never incremented by the timer*/
+ g_system->delayMillis(50);
}
waitVBlank();
}
@@ -353,7 +467,10 @@ void animPortrait(byte layer, byte index, byte delay) {
loadPortraitWithFrame(portrait - 1);
if (*ani == 0xFF) {
ani++;
- loadPortrait(&ani, ani + 3);
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ ega_loadPortrait(&ani, ani + 3);
+ else
+ loadPortrait(&ani, ani + 3);
}
getDirtyRectAndSetSprite(layer, &kind, &x, &y, &width, &height, &offs);
waitVBlank();
diff --git a/engines/chamber/room.cpp b/engines/chamber/room.cpp
index 2d1e965b12e..55ce1663a57 100644
--- a/engines/chamber/room.cpp
+++ b/engines/chamber/room.cpp
@@ -25,6 +25,8 @@
#include "chamber/enums.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
+#include "chamber/ega_resource.h"
#include "chamber/print.h"
#include "chamber/anim.h"
#include "chamber/cursor.h"
@@ -188,7 +190,7 @@ int16 isInRect(byte x, byte y, rect_t *rect) {
Check if cursor is in rect
*/
int16 isCursorInRect(rect_t *rect) {
- return isInRect(cursor_x / g_vm->_screenPPB, cursor_y, rect);
+ return isInRect(cursor_x / 4, cursor_y, rect);
}
/*
@@ -245,7 +247,10 @@ void selectSpotCursor(void) {
curs = CURSOR_CROSSHAIR;
}
}
- cursor_shape = souri_data + curs * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / g_vm->_screenPPB;
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ cursor_shape = souri_data + curs * (CURSOR_WIDTH * CURSOR_HEIGHT / 4);
+ else
+ cursor_shape = souri_data + curs * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / 4;
}
#define kBgW 8
@@ -287,6 +292,10 @@ static const int16 background_draw_steps_hga[] = {
Draw main backgound pattern, in spiral-like order
*/
void drawBackground(byte *target, byte vblank) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ ega_drawBackground(target);
+ return;
+ }
int16 i;
uint16 offs = (2 / 2) * CGA_BYTES_PER_LINE + 8; /*TODO: calcxy?*/
byte *pixels = gauss_data + 0x3C8; /*TODO: better const*/
@@ -436,48 +445,82 @@ Fill in sliding door animation information
void initRoomDoorInfo(byte index) {
int16 i;
byte *aptr;
- byte *sprbuf;
doorinfo_t *info = (doorinfo_t *)scratch_mem2;
rect_t bounds = {0xFF, 0, 0xFF, 0};
aptr = doors_list[index - 1];
info->flipped = (aptr[1] & 0x80) ? ~0 : 0;
- sprbuf = info->sprites;
- for (i = 0; i < kNumDoorSprites; i++) {
- byte x, y, w, h, ox;
- byte *sprite = sprbuf;
- sprbuf = loadPuzzl(aptr[0], sprbuf);
-
- x = aptr[1];
- y = aptr[2];
- w = sprite[0];
- h = sprite[1];
-
- ox = x;
- if (x & 0x80) {
- /*horizontal flip*/
- x = (x + w - 1) & 0x7F;
- ox &= 0x7F;
+
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ for (i = 0; i < kNumDoorSprites; i++) {
+ byte x, y, w, h, ox;
+ Graphics::Surface *surf = ega_puzzl_res->getSprite(aptr[0]);
+
+ x = aptr[1];
+ y = aptr[2];
+ w = surf->w / 4; /* CGA byte width */
+ h = surf->h;
+
+ ox = x & 0x7F;
+ // EGA: ega_BlitSpriteFlip writes left-to-right, so use original ox for offset.
+ // (CGA convention shifts x to rightmost byte; EGA does not need that.)
+
+ y = (y * 2) & 0xFF;
+
+ if (ox < bounds.sx)
+ bounds.sx = ox;
+ if (ox + w >= bounds.ex)
+ bounds.ex = ox + w;
+
+ if (y < bounds.sy)
+ bounds.sy = y;
+ if (y + h >= bounds.ey)
+ bounds.ey = y + h;
+
+ info->layer[i].width = w;
+ info->layer[i].height = h;
+ info->layer[i].pixels = (byte *)surf->getPixels();
+ info->layer[i].offs = CalcXY_p(ox, y);
+
+ aptr += 3;
}
+ } else {
+ byte *sprbuf = info->sprites;
+ for (i = 0; i < kNumDoorSprites; i++) {
+ byte x, y, w, h, ox;
+ byte *sprite = sprbuf;
+ sprbuf = loadPuzzl(aptr[0], sprbuf);
+
+ x = aptr[1];
+ y = aptr[2];
+ w = sprite[0];
+ h = sprite[1];
+
+ ox = x;
+ if (x & 0x80) {
+ x = (x + w - 1) & 0x7F;
+ ox &= 0x7F;
+ }
- y = (y * 2) & 0xFF; /*TODO: disregard vertical flip?*/
+ y = (y * 2) & 0xFF;
- if (ox < bounds.sx)
- bounds.sx = ox;
- if (ox + w >= bounds.ex)
- bounds.ex = ox + w;
+ if (ox < bounds.sx)
+ bounds.sx = ox;
+ if (ox + w >= bounds.ex)
+ bounds.ex = ox + w;
- if (y < bounds.sy)
- bounds.sy = y;
- if (y + h >= bounds.ey)
- bounds.ey = y + h;
+ if (y < bounds.sy)
+ bounds.sy = y;
+ if (y + h >= bounds.ey)
+ bounds.ey = y + h;
- info->layer[i].width = w;
- info->layer[i].height = h;
- info->layer[i].pixels = sprite + 2;
- info->layer[i].offs = CalcXY_p(x, y);
+ info->layer[i].width = w;
+ info->layer[i].height = h;
+ info->layer[i].pixels = sprite + 2;
+ info->layer[i].offs = CalcXY_p(x, y);
- aptr += 3;
+ aptr += 3;
+ }
}
info->width = bounds.ex - bounds.sx;
@@ -491,6 +534,23 @@ Draw sliding door
void drawRoomDoor(void) {
int16 i;
doorinfo_t *info = (doorinfo_t *)scratch_mem2;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ for (i = 0; i < kNumDoorSprites; i++) {
+ uint16 w = info->layer[i].width * 4;
+ byte h = info->layer[i].height;
+ byte *pixels = info->layer[i].pixels;
+ uint16 offs = info->layer[i].offs;
+
+ if (!info->flipped)
+ ega_BlitSprite(pixels, w, w, h, backbuffer, offs);
+ else
+ ega_BlitSpriteFlip(pixels, w, w, h, backbuffer, offs);
+ }
+ waitVBlank();
+ waitVBlank();
+ ega_BlitFromBackBuffer(info->width * 4, info->height, frontbuffer, info->offs);
+ return;
+ }
for (i = 0; i < kNumDoorSprites; i++) {
byte w = info->layer[i].width;
byte h = info->layer[i].height;
@@ -528,7 +588,10 @@ void animRoomDoorOpen(byte index) {
drawRoomDoor();
#endif
info->layer[1].height -= 2;
- info->layer[1].pixels += info->layer[1].width * 2 * 2;
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ info->layer[1].pixels += info->layer[1].width * 4 * 2;
+ else
+ info->layer[1].pixels += info->layer[1].width * 2 * 2;
}
playSound(31);
@@ -551,7 +614,11 @@ void animRoomDoorClose(byte index) {
oldheight = info->layer[1].height;
oldpixels = info->layer[1].pixels;
- info->layer[1].pixels += info->layer[1].width * 2 * (info->layer[1].height - 1);
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ info->layer[1].pixels += info->layer[1].width * 4 * (info->layer[1].height - 1);
+ } else {
+ info->layer[1].pixels += info->layer[1].width * 2 * (info->layer[1].height - 1);
+ }
info->layer[1].height = 1;
for (i = 0; i < oldheight / 2; i++) {
@@ -559,7 +626,10 @@ void animRoomDoorClose(byte index) {
drawRoomDoor();
#endif
info->layer[1].height += 2;
- info->layer[1].pixels -= info->layer[1].width * 2 * 2;
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ info->layer[1].pixels -= info->layer[1].width * 4 * 2;
+ else
+ info->layer[1].pixels -= info->layer[1].width * 2 * 2;
}
info->layer[1].height = oldheight;
@@ -764,6 +834,46 @@ void drawPersons(void) {
Draw room's static object to backbuffer
*/
void drawRoomStaticObject(byte *aptr, byte *rx, byte *ry, byte *rw, byte *rh) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ Graphics::Surface *surf = ega_puzzl_res->getSprite(aptr[0]);
+ byte x = aptr[1];
+ byte y = aptr[2];
+ uint16 w = surf->w;
+ uint16 h = surf->h;
+ byte wcga = w / 4;
+
+ *rx = x & 0x7F;
+ *ry = (y & 0x7F) * 2;
+ *rw = wcga;
+ *rh = h;
+
+ byte *pixels = (byte *)surf->getPixels();
+ int16 pitch = surf->pitch;
+
+ // EGA: ega_BlitSpriteFlip writes left-to-right from ofs (left edge),
+ // so do NOT shift x to the rightmost position (that's a CGA-only convention).
+ byte drawx = x & 0x7F;
+
+ if (y & 0x80) {
+ pixels += pitch * (h - 1);
+ pitch = -pitch;
+ }
+ y = (y * 2) & 0xFF;
+
+ if (aptr[0] == 83) {
+ if (arpla_y_step & 1)
+ y -= 8;
+ arpla_y_step >>= 1;
+ }
+
+ uint16 ofs = CalcXY_p(drawx, y);
+ if (aptr[1] & 0x80)
+ ega_BlitSpriteFlip(pixels, pitch, w, h, backbuffer, ofs);
+ else
+ ega_BlitSprite(pixels, pitch, w, h, backbuffer, ofs);
+ return;
+ }
+
byte x, y, w, h;
int16 pitch;
byte *sprite = loadPuzzlToScratch(aptr[0]);
@@ -906,8 +1016,8 @@ void drawRoomItemsIndicator(void) {
break;
}
}
- drawSpriteN(spridx, 296 / g_vm->_screenPPB, 14, CGA_SCREENBUFFER);
- drawSpriteN(spridx, 296 / g_vm->_screenPPB, 14, backbuffer);
+ drawSpriteN(spridx, 296 / 4, 14, CGA_SCREENBUFFER);
+ drawSpriteN(spridx, 296 / 4, 14, backbuffer);
/*recalculate the number of zapstiks we have*/
script_byte_vars.zapstiks_owned = 0;
@@ -1016,35 +1126,79 @@ void showCommandHint(byte *target) {
}
void loadLutinSprite(uint16 lutidx) {
- byte spridx;
- uint16 flags;
byte *lutin_entry, *lutin_entry_end;
byte *buffer;
- byte *sprite;
- byte sprw, sprh;
+ byte lutW, lutH;
- uint16 i;
+ lutin_entry = seekToEntry(lutin_data, lutidx, &lutin_entry_end);
+ lutW = *lutin_entry++; /* composite width in CGA bytes */
+ lutH = *lutin_entry++; /* composite height in pixels */
+
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ // EGA path: build a CLUT8 flat buffer in lutin_mem.
+ // Layout: [0]=lutW, [1]=lutH, then lutW*4 bytes per row à lutH rows (index 0 = transparent).
+ uint16 pw = (uint16)lutW * 4; // pixel width
+ lutin_mem[0] = lutW;
+ lutin_mem[1] = lutH;
+ memset(lutin_mem + 2, 0, pw * lutH); // clear to transparent (index 0)
+
+ for (; lutin_entry != lutin_entry_end;) {
+ byte spridx = *lutin_entry++;
+ uint16 flags = *lutin_entry++;
+ flags |= (*lutin_entry++) << 8;
+
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(loadSprit(spridx));
+ byte *src = (byte *)surf->getPixels();
+ uint16 sw = surf->w;
+ uint16 sh = surf->h;
+ int16 spitch = surf->pitch;
+
+ // Convert CGA byte-offset to pixel position in lutin buffer
+ uint16 byteOfs = flags & 0x7FFF;
+ uint16 row = (lutW > 0) ? (byteOfs / lutW) : 0;
+ uint16 col = (lutW > 0) ? (byteOfs % lutW) : 0;
+ byte *dst = lutin_mem + 2 + row * pw + col * 4;
+
+ if (flags & 0x8000) { // horizontal flip (mirrors columns, same as CGA mergeSpritesDataFlip)
+ for (uint16 y = 0; y < sh; y++) {
+ for (uint16 x = 0; x < sw; x++) {
+ byte p = src[sw - 1 - x];
+ if (p != 0) dst[x] = p;
+ }
+ src += spitch;
+ dst += pw;
+ }
+ } else {
+ for (uint16 y = 0; y < sh; y++) {
+ for (uint16 x = 0; x < sw; x++) {
+ byte p = src[x];
+ if (p != 0) dst[x] = p;
+ }
+ src += spitch;
+ dst += pw;
+ }
+ }
+ }
+ return;
+ }
+ // CGA path: build CGA mask+pixel buffer in lutin_mem.
buffer = lutin_mem;
-
- for (i = 0; i < 800; i++) { /*TODO: fix size*/
+ for (uint16 i = 0; i < 800; i++) { /*TODO: fix size*/
buffer[i * 2] = 0xFF; /*mask*/
buffer[i * 2 + 1] = 0; /*pixels*/
}
-
- lutin_entry = seekToEntry(lutin_data, lutidx, &lutin_entry_end);
-
- *buffer++ = *lutin_entry++; /*width*/
- *buffer++ = *lutin_entry++; /*height*/
+ *buffer++ = lutW;
+ *buffer++ = lutH;
for (; lutin_entry != lutin_entry_end;) {
- spridx = *lutin_entry++;
- flags = *lutin_entry++;
+ byte spridx = *lutin_entry++;
+ uint16 flags = *lutin_entry++;
flags |= (*lutin_entry++) << 8;
- sprite = loadSprit(spridx);
- sprw = *sprite++;
- sprh = *sprite++;
+ byte *sprite = loadSprit(spridx);
+ byte sprw = *sprite++;
+ byte sprh = *sprite++;
buffer = lutin_mem + 2 + (flags & 0x7FFF) * 2;
if (flags & 0x8000)
@@ -1054,10 +1208,40 @@ void loadLutinSprite(uint16 lutidx) {
}
}
+/*
+EGA helper: draw a lutin composite by overlaying its sub-sprites directly
+on the target framebuffer (no scratch_mem2 packing). Works because
+ega_BlitSprite treats index 0 as transparent.
+*/
+static void egaDrawLutinComposite(uint16 lutidx, byte *target, uint16 baseOfs) {
+ byte *entry, *entry_end;
+ entry = seekToEntry(lutin_data, lutidx, &entry_end);
+ byte w = *entry++; /* composite width in CGA bytes (1 byte = 4 px) */
+ entry++; /* height (unused here) */
+ while (entry < entry_end) {
+ byte sub = *entry++;
+ uint16 flags = *entry++;
+ flags |= (*entry++) << 8;
+ uint16 byteOfs = flags & 0x7FFF;
+ uint16 yy = w ? (byteOfs / w) : 0;
+ uint16 xxBytes = w ? (byteOfs % w) : 0;
+ uint16 subOfs = baseOfs + yy * EGA_BYTES_PER_LINE + xxBytes * 4;
+ byte *sprite = loadSprit(sub);
+ if (flags & 0x8000)
+ drawSpriteFlip(sprite, target, subOfs);
+ else
+ drawSprite(sprite, target, subOfs);
+ }
+}
+
/*
Draw specific room's person idle sprite
*/
void drawCharacterSprite(byte spridx, byte x, byte y, byte *target) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ egaDrawLutinComposite(spridx, target, CalcXY_p(x, y));
+ return;
+ }
lutin_mem = scratch_mem2;
loadLutinSprite(spridx);
@@ -1079,13 +1263,23 @@ char drawZoneAniSprite(rect_t *rect, uint16 index, byte *target) {
spridx = la->sprites[la->phase];
la->phase = (la->phase + 1) % 8;
+ zsprite_draw_ofs = CalcXY_p(rect->sx, rect->sy);
+
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ byte *entry, *entry_end;
+ entry = seekToEntry(lutin_data, spridx, &entry_end);
+ zsprite_w = entry[0]; /* CGA byte width */
+ zsprite_h = entry[1]; /* height in pixels */
+ egaDrawLutinComposite(spridx, target, zsprite_draw_ofs);
+ return ~0;
+ }
+
lutin_mem = scratch_mem2;
loadLutinSprite(spridx);
zsprite_w = scratch_mem2[0];
zsprite_h = scratch_mem2[1];
- zsprite_draw_ofs = CalcXY_p(rect->sx, rect->sy);
drawSprite(scratch_mem2, target, zsprite_draw_ofs);
@@ -1300,6 +1494,19 @@ void prepareTurkey(void) {
Load puzzl sprite to scratch and init draw params
*/
uint16 getPuzzlSprite(byte index, byte x, byte y, uint16 *w, uint16 *h, uint16 *ofs) {
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ Graphics::Surface *surf = ega_puzzl_res->getSprite(index);
+ *w = surf->w / 4;
+ *h = surf->h;
+ *ofs = CalcXY_p(x, y);
+ // Copy EGA pixel data into scratch_mem2+2 so cga_BlitScratchBackSprite can find it
+ byte *dst = scratch_mem2 + 2;
+ for (int row = 0; row < surf->h; row++) {
+ memcpy(dst, (byte *)surf->getPixels() + row * surf->pitch, surf->w);
+ dst += surf->w;
+ }
+ return 0;
+ }
byte *spr = loadPuzzlToScratch(index);
*w = spr[0];
*h = spr[1];
@@ -1374,6 +1581,57 @@ byte *loadMursmSprite(byte index) {
byte *pinfo, *end;
pinfo = seekToEntry(mursm_data, index, &end);
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* EGA: build a CLUT8 buffer (80 px wide à 59 rows = 4720 bytes) */
+ const uint16 egaPitch = 80; /* 20 CGA bytes à 4 px/byte */
+ memset(sprit_load_buffer, 0, egaPitch * 59);
+
+ while (pinfo != end) {
+ byte sprIdx = *pinfo++;
+ uint16 flags = *pinfo++;
+ flags |= (*pinfo++) << 8;
+ uint16 cgaOfs = flags & 0x3FFF; /* offset in CGA flat buffer (pitch=20, 2 bytes/unit) */
+
+ /* Convert CGA flat offset â EGA flat offset */
+ uint16 row = cgaOfs / (20 * 2); /* 20 CGA bytes à 2 bytes/unit = 40 bytes/row */
+ uint16 colCga = (cgaOfs % (20 * 2)) / 2; /* column in CGA bytes */
+ uint16 egaBufOfs = row * egaPitch + colCga * 4;
+
+ Graphics::Surface *surf = ega_puzzl_res->getSprite(sprIdx & 0x7F);
+ byte *src = (byte *)surf->getPixels();
+ uint16 sw = surf->w;
+ uint16 sh = surf->h;
+ int16 spitch = surf->pitch;
+ byte *dst = sprit_load_buffer + egaBufOfs;
+
+ if (sprIdx & 0x80) { /* horizontal flip */
+ for (uint16 y = 0; y < sh; y++) {
+ for (uint16 x = 0; x < sw; x++) {
+ byte p = src[sw - 1 - x];
+ if (p != 0) dst[x] = p;
+ }
+ src += spitch;
+ dst += egaPitch;
+ }
+ } else {
+ for (uint16 y = 0; y < sh; y++) {
+ for (uint16 x = 0; x < sw; x++) {
+ byte p = src[x];
+ if (p != 0) dst[x] = p;
+ }
+ src += spitch;
+ dst += egaPitch;
+ }
+ }
+ }
+
+ cur_frame_width = 20;
+ cur_image_coords_y = 32;
+ cur_image_size_w = 80 / 4;
+ cur_image_size_h = 59;
+ return sprit_load_buffer;
+ }
+
while (pinfo != end) {
uint16 flags;
int16 pitch;
@@ -1507,7 +1765,10 @@ void theWallPhase1_DoorClose1(void) {
loadZone();
spr = loadMursmSprite(0);
- spr += cur_frame_width - 1;
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ spr += cur_frame_width * 4 - 4;
+ else
+ spr += cur_frame_width - 1;
cur_image_coords_x = 64 / 4;
cga_AnimLiftToRight(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
@@ -1531,13 +1792,22 @@ void theWallPhase2_DoorClose2(void) {
loadZone();
spr = loadMursmSprite(0);
- spr += cur_frame_width - 1;
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ spr += cur_frame_width * 4 - 4;
+ else
+ spr += cur_frame_width - 1;
cur_image_coords_x = 64 / 4;
- cga_AnimLiftToRight(10, spr - 10, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ cga_AnimLiftToRight(10, spr - 40, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ else
+ cga_AnimLiftToRight(10, spr - 10, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
spr = loadMursmSprite(1);
cur_image_coords_x = 220 / 4;
- cga_AnimLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 10);
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ cga_AnimLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 40);
+ else
+ cga_AnimLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 10);
IFGM_PlaySample(30);
@@ -1551,18 +1821,28 @@ void drawTheWallDoors(void) {
switch (script_byte_vars.zone_index) {
case 9:
case 102:
- cga_Blit(loadMursmSprite(0) + 10, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / g_vm->_screenPPB, 32));
- if (g_vm->getLanguage() == Common::EN_USA) {
- /*This fixes odd black patch on the right gate door*/
- cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / g_vm->_screenPPB, 32));
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* EGA buffer is 80 px wide; CGA +10 bytes = 40 EGA pixels */
+ cga_Blit(loadMursmSprite(0) + 40, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ if (g_vm->getLanguage() == Common::EN_USA) {
+ cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
+ } else {
+ cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
+ }
} else {
- cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / g_vm->_screenPPB, 32));
+ cga_Blit(loadMursmSprite(0) + 10, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ if (g_vm->getLanguage() == Common::EN_USA) {
+ /*This fixes odd black patch on the right gate door*/
+ cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
+ } else {
+ cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
+ }
}
break;
case 95:
case 103:
- cga_Blit(loadMursmSprite(0), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(64 / g_vm->_screenPPB, 32));
- cga_Blit(loadMursmSprite(1), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(144 / g_vm->_screenPPB, 32));
+ cga_Blit(loadMursmSprite(0), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ cga_Blit(loadMursmSprite(1), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(144 / 4, 32));
break;
}
}
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 58c7fef72da..470685243e1 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -28,6 +28,8 @@
#include "chamber/enums.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
+#include "chamber/ega.h"
+#include "chamber/ega_resource.h"
#include "chamber/cursor.h"
#include "chamber/portrait.h"
#include "chamber/input.h"
@@ -348,29 +350,21 @@ byte wait_delta = 0;
Wait for a specified number of seconds (real time) or a keypress
*/
void wait(byte seconds) {
- warning("STUB: Wait(%d)", seconds);
-
-#if 0
- struct time t;
- uint16 endtime;
-
seconds += wait_delta;
- if (seconds > 127) /*TODO: is this a check for a negative value?*/
+ if (seconds > 127) /*original: treats as signed; cap to 0*/
seconds = 0;
- gettime(&t);
- endtime = t.ti_sec * 100 + t.ti_hund + seconds * 100;
+ if (seconds == 0)
+ return;
- while (buttons == 0) {
- uint16 current;
- gettime(&t);
- current = t.ti_sec * 100 + t.ti_hund;
- if (endtime >= 6000 && current < 2048) /*TODO: some kind of overflow check???*/
- current += 6000;
- if (current >= endtime)
+ uint32 end = g_system->getMillis() + (uint32)seconds * 1000;
+ while (!buttons && !g_vm->_shouldQuit) {
+ pollInputButtonsOnly();
+ if (g_system->getMillis() >= end)
break;
+ g_system->delayMillis(10);
+ g_system->updateScreen();
}
-#endif
}
/*
@@ -677,7 +671,10 @@ uint16 SCR_5_DrawPortraitLiftRight(void) {
return 0;
/*TODO: use local args instead of globals*/
- cga_AnimLiftToRight(width, cur_image_pixels + width - 1, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ cga_AnimLiftToRight(width, cur_image_pixels + width * 4 - 4, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
+ else
+ cga_AnimLiftToRight(width, cur_image_pixels + width - 1, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
return 0;
}
@@ -764,6 +761,8 @@ void twistDraw(byte x, byte y, byte width, byte height, byte *source, byte *targ
for (i = 0; i < width * 4; i++) {
cga_TraceLine(sx, ex, sy, ey, source, target);
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sx += 1;
ex -= 1;
@@ -779,6 +778,8 @@ void twistDraw(byte x, byte y, byte width, byte height, byte *source, byte *targ
for (i = 0; i < height; i++) {
cga_TraceLine(sx, ex, sy, ey, source, target);
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sy -= 1;
ey += 1;
@@ -819,18 +820,24 @@ void arcDraw(byte x, byte y, byte width, byte height, byte *source, byte *target
for (i = 0; i < height; i++) {
cga_TraceLine(sx, ex, sy, ey, source, target);
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sy -= 1;
}
for (i = 0; i < width * 4; i++) {
cga_TraceLine(sx, ex, sy, ey, source, target);
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sx += 1;
}
for (i = 0; i < height + 1; i++) {
cga_TraceLine(sx, ex, sy, ey, source, target);
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sy += 1;
}
@@ -871,6 +878,28 @@ uint16 SCR_D_DrawPortraitDotEffect(void) {
if (!drawPortrait(&script_ptr, &x, &y, &width, &height))
return 0;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ uint16 pw = width * 4;
+ cur_image_end = pw * height;
+ uint16 baseOfs = ega_CalcXY_p(x, y);
+ int16 count = 0;
+ for (offs = 0; offs != cur_image_end;) {
+ uint16 px = offs % pw;
+ uint16 py = offs / pw;
+ target[baseOfs + py * EGA_BYTES_PER_LINE + px] = cur_image_pixels[offs];
+
+ if (count % 20 == 0)
+ ega_blitToScreen(x * 4, y, pw, height);
+
+ offs += step;
+ if (offs > cur_image_end)
+ offs -= cur_image_end;
+ count++;
+ }
+ ega_blitToScreen(x * 4, y, pw, height);
+ return 0;
+ }
+
cur_image_end = width * height;
int16 count = 0;
@@ -923,11 +952,16 @@ uint16 drawPortraitZoomed(byte **params) {
zwidth = *((*params)++);
zheight = *((*params)++);
- /*adjust the rect for new size*/
- last_dirty_rect->width = zwidth + 2;
- last_dirty_rect->height = zheight;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /*EGA can't zoom: draw at original size; dirty rect already has correct dimensions from drawPortrait*/
+ cga_ZoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, cur_image_size_w, cur_image_size_h, frontbuffer, cur_image_offs);
+ } else {
+ /*adjust the rect for new size*/
+ last_dirty_rect->width = zwidth + 2;
+ last_dirty_rect->height = zheight;
- cga_ZoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, zwidth, zheight, frontbuffer, cur_image_offs);
+ cga_ZoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, zwidth, zheight, frontbuffer, cur_image_offs);
+ }
return 0;
}
@@ -958,6 +992,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
script_ptr++;
index = *script_ptr++;
+ warning("SCR_19_HidePortraitLiftLeft: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -967,6 +1002,21 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
/*TODO: This originally was done by reusing door sliding routine*/
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ offs += 4;
+ while (--width)
+ cga_HideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ offs -= 4;
+ uint16 ooffs = offs;
+ byte oh = height;
+ while (height--) {
+ memcpy(frontbuffer + offs, backbuffer + offs, 4);
+ offs += EGA_BYTES_PER_LINE;
+ }
+ ega_blitToScreen(ooffs % EGA_BYTES_PER_LINE, ooffs / EGA_BYTES_PER_LINE, 4, oh);
+ return 0;
+ }
+
/*offs = CalcXY_p(x + 1, y);*/
offs++;
@@ -1004,6 +1054,7 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
script_ptr++;
index = *script_ptr++;
+ warning("SCR_1A_HidePortraitLiftRight: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1013,6 +1064,21 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
/*TODO: This originally was done by reusing door sliding routine*/
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ offs = CalcXY_p(x + width - 2, y);
+ while (--width)
+ cga_HideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ offs += 4;
+ uint16 ooffs = offs;
+ byte oh = height;
+ while (height--) {
+ memcpy(frontbuffer + offs, backbuffer + offs, 4);
+ offs += EGA_BYTES_PER_LINE;
+ }
+ ega_blitToScreen(ooffs % EGA_BYTES_PER_LINE, ooffs / EGA_BYTES_PER_LINE, 4, oh);
+ return 0;
+ }
+
offs = CalcXY_p(x + width - 2, y);
while (--width) {
@@ -1049,6 +1115,7 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
script_ptr++;
index = *script_ptr++;
+ warning("SCR_1B_HidePortraitLiftUp: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1056,6 +1123,12 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
return 0;
}
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* offs = CalcXY_p(x, y) from dirty rect â restore full portrait area */
+ cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ return 0;
+ }
+
offs = CalcXY_p(x, y + 1);
while (--height) {
@@ -1063,12 +1136,13 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
}
/*hide topmost line*/
- /*TODO: move this to CGA?*/
- offs ^= g_vm->_line_offset;
- if ((offs & g_vm->_line_offset) != 0)
- offs -= g_vm->_screenBPL;
- memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
- cga_blitToScreen(offs, width, 1);
+ {
+ offs ^= g_vm->_line_offset;
+ if ((offs & g_vm->_line_offset) != 0)
+ offs -= g_vm->_screenBPL;
+ memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
+ cga_blitToScreen(offs, width, 1);
+ }
return 0;
}
@@ -1085,6 +1159,7 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
script_ptr++;
index = *script_ptr++;
+ warning("SCR_1C_HidePortraitLiftDown: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1092,6 +1167,15 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
return 0;
}
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ /* offs = CalcXY_p(x, y) from dirty rect â restore full portrait area.
+ * The CGA path recalculates offs to y+height-2 (bottom of portrait),
+ * causing ega_CopyScreenBlock to start from the wrong position and
+ * leave most of the portrait unrestoâred. */
+ cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ return 0;
+ }
+
offs = CalcXY_p(x, y + height - 2);
while (--height) {
@@ -1099,12 +1183,13 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
}
/*hide bottommost line*/
- /*TODO: move this to CGA?*/
- offs ^= g_vm->_line_offset;
- if ((offs & g_vm->_line_offset) == 0)
- offs += g_vm->_screenBPL;
- memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
- cga_blitToScreen(offs, width, 1);
+ {
+ offs ^= g_vm->_line_offset;
+ if ((offs & g_vm->_line_offset) == 0)
+ offs += g_vm->_screenBPL;
+ memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
+ cga_blitToScreen(offs, width, 1);
+ }
return 0;
}
@@ -1299,8 +1384,11 @@ void jaggedZoom(byte *source, byte *target) {
ey = points[0].y;
}
cga_TraceLine(sx / 2, ex / 2, sy / 2, ey / 2, source, target);
- /*TODO: waitVBlank(); maybe?*/
}
+ /* One screen update per cycle (not per line) keeps the animation fluid */
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+ waitVBlank();
}
}
@@ -1347,7 +1435,11 @@ void drawStars(star_t *stars, int16 iter, byte *target) {
short z, x, y;
byte pixel, mask;
- target[stars->ofs] &= stars->mask;
+ /* Erase previous star position */
+ if (g_vm->_videoMode == Common::kRenderEGA)
+ target[stars->ofs] = 0;
+ else
+ target[stars->ofs] &= stars->mask;
if (stars->z < 328) {
if (iter >= 30) {
randomStar(stars);
@@ -1368,17 +1460,24 @@ void drawStars(star_t *stars, int16 iter, byte *target) {
continue;
}
- stars->ofs = cga_CalcXY(x, y);
-
- pixel = (stars->z < 0xE00) ? 0xC0 : 0x40;
- pixel >>= (x % 4) * 2;
- mask = 0xC0;
- mask = ~(mask >> (x % 4) * 2);
- stars->pixel = pixel;
- stars->mask = mask;
-
- target[stars->ofs] &= mask;
- target[stars->ofs] |= pixel;
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ stars->ofs = ega_CalcXY_p(x, y);
+ /* EGA: CLUT8 single byte per pixel; bright = white (15), dim = dark gray (8) */
+ pixel = (stars->z < 0xE00) ? 15 : 8;
+ stars->pixel = pixel;
+ stars->mask = 0; /* unused in EGA path */
+ target[stars->ofs] = pixel;
+ } else {
+ stars->ofs = cga_CalcXY(x, y);
+ pixel = (stars->z < 0xE00) ? 0xC0 : 0x40;
+ pixel >>= (x % 4) * 2;
+ mask = 0xC0;
+ mask = ~(mask >> (x % 4) * 2);
+ stars->pixel = pixel;
+ stars->mask = mask;
+ target[stars->ofs] &= mask;
+ target[stars->ofs] |= pixel;
+ }
}
}
@@ -1387,8 +1486,12 @@ Play starfield animation
*/
void animStarfield(star_t *stars, byte *target) {
int16 i;
- for (i = 100; i; i--)
+ for (i = 100; i; i--) {
drawStars(stars, i, target);
+ if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+ waitVBlank();
+ }
}
/*
@@ -1719,6 +1822,8 @@ uint16 SCR_28_MenuLoop(void) {
mask = *script_ptr++;
value = *script_ptr++;
+ warning("SCR_28_MenuLoop: cursor=%d mask=0x%02X value=0x%02X", cursor, mask, value);
+
selectCursor(cursor);
menuLoop(mask, value);
@@ -1794,6 +1899,7 @@ uint16 SCR_23_HidePortrait(void) {
script_ptr++;
index = *script_ptr++;
+ warning("SCR_23_HidePortrait: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1831,6 +1937,7 @@ uint16 SCR_3F_HidePortrait(void) {
Restore screen data from back buffer for all portraits
*/
uint16 SCR_24_PopAllPortraits(void) {
+ warning("SCR_24_PopAllPortraits");
script_ptr++;
popDirtyRects(DirtyRectSprite);
return 0;
@@ -2378,7 +2485,7 @@ uint16 SCR_47_DeProfundisRiseMonster(void) {
waitVBlank();
ofs ^= g_vm->_line_offset;
- if ((ofs & g_vm->_line_offset) != 0)
+ if ((ofs & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs -= g_vm->_screenBPL;
h++;
@@ -2709,7 +2816,7 @@ uint16 SCR_56_MorphRoom98(void) {
memcpy(frontbuffer + ofs, backbuffer + ofs, g_vm->_screenBPL);
waitVBlank();
ofs ^= g_vm->_line_offset;
- if ((ofs & g_vm->_line_offset) != 0)
+ if ((ofs & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs -= g_vm->_screenBPL;
}
@@ -2728,7 +2835,7 @@ void ShowMirrored(uint16 h, uint16 ofs) {
/*move 1 line up*/
ofs2 ^= g_vm->_line_offset;
- if ((ofs2 & g_vm->_line_offset) != 0)
+ if ((ofs2 & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs2 -= g_vm->_screenBPL;
while (h--) {
@@ -2746,7 +2853,7 @@ void ShowMirrored(uint16 h, uint16 ofs) {
/*move 1 line up*/
ofs2 ^= g_vm->_line_offset;
- if ((ofs2 & g_vm->_line_offset) != 0)
+ if ((ofs2 & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs2 -= g_vm->_screenBPL;
}
}
@@ -2824,7 +2931,7 @@ static void AnimSaucer(void) {
/*previous line*/
ofs ^= g_vm->_line_offset;
- if ((ofs & g_vm->_line_offset) != 0)
+ if ((ofs & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs -= g_vm->_screenBPL;
for (i = 0; i < 55; i++) {
@@ -2838,7 +2945,7 @@ static void AnimSaucer(void) {
/*previous line line*/
ofs ^= g_vm->_line_offset;
- if ((ofs & g_vm->_line_offset) != 0)
+ if ((ofs & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs -= g_vm->_screenBPL;
}
@@ -2848,7 +2955,7 @@ static void AnimSaucer(void) {
LiftLines(i + 1, backbuffer, ofs, frontbuffer, ofs2);
ofs2 ^= g_vm->_line_offset;
- if ((ofs2 & g_vm->_line_offset) != 0)
+ if ((ofs2 & g_vm->_line_offset) != 0 || g_vm->_line_offset == 0)
ofs2 -= g_vm->_screenBPL;
waitVBlank();
@@ -3411,18 +3518,30 @@ uint16 GetZoneObjCommand(uint16 offs) {
void DrawStickyNet(void) {
byte x, y, w, h;
- uint16 ofs;
- byte *sprite = loadPuzzlToScratch(80);
-
x = room_bounds_rect.sx;
y = room_bounds_rect.sy;
w = room_bounds_rect.ex - x;
h = room_bounds_rect.ey - y;
- ofs = CalcXY_p(x, y);
+ uint16 ofs = CalcXY_p(x, y);
/*16x30 is the net sprite size*/
+ if (g_vm->_videoMode == Common::kRenderEGA) {
+ Graphics::Surface *surf = ega_puzzl_res->getSprite(80);
+ uint16 sprW = surf->w; /* pixels */
+ uint16 sprH = surf->h;
+ byte *pixels = (byte *)surf->getPixels();
+ int16 pitch = surf->pitch;
+ for (; h >= sprH; h -= sprH) {
+ for (int16 i = 0; i < w; i += sprW / 4)
+ ega_BlitSprite(pixels, pitch, sprW, sprH, frontbuffer, ofs + i * 4);
+ ofs += EGA_BYTES_PER_LINE * sprH;
+ }
+ return;
+ }
+
+ byte *sprite = loadPuzzlToScratch(80);
for (; h; h -= 30) {
int16 i;
for (i = 0; i < w; i += 16 / 4)
Commit: cb6c1a175455d839433df91b63cb34200ae6c2d9
https://github.com/scummvm/scummvm/commit/cb6c1a175455d839433df91b63cb34200ae6c2d9
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Refactor rendering into Renderer class hierarchy
Introduce an abstract Renderer base class with CGARenderer and EGARenderer
subclasses. Methods with different CGA/EGA implementations are virtual;
methods with identical logic (animLiftToDown, animLiftToUp) remain free
functions dispatching through the renderer. All cga_* call sites are
preserved as thin wrappers for backward compatibility.
Changed paths:
A engines/chamber/renderer.h
engines/chamber/anim.cpp
engines/chamber/cga.cpp
engines/chamber/cga.h
engines/chamber/chamber.cpp
engines/chamber/chamber.h
engines/chamber/dialog.cpp
engines/chamber/ega.cpp
engines/chamber/input.cpp
engines/chamber/invent.cpp
engines/chamber/kult.cpp
engines/chamber/menu.cpp
engines/chamber/portrait.cpp
engines/chamber/print.cpp
engines/chamber/room.cpp
engines/chamber/script.cpp
engines/chamber/timer.cpp
diff --git a/engines/chamber/anim.cpp b/engines/chamber/anim.cpp
index cbf1f762e26..7ff01a3dad6 100644
--- a/engines/chamber/anim.cpp
+++ b/engines/chamber/anim.cpp
@@ -122,7 +122,7 @@ void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte
for (offs = 0; offs != cur_image_end;) {
byte mask = 0xC0 >> (((xx + offs % ww) % 4) * 2);
- uint16 ofs = cga_CalcXY(xx + offs % ww, y + offs / ww);
+ uint16 ofs = g_vm->_renderer->calcXY(xx + offs % ww, y + offs / ww);
target[ofs] = (target[ofs] & ~mask) | (source[ofs] & mask);
@@ -141,13 +141,13 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
uint16 delay;
byte ex, ey, updx, updy, updw, updh;
uint16 ofs = CalcXY_p(x, y);
- cga_BackupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
+ g_vm->_renderer->backupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
if (g_vm->_videoMode == Common::kRenderEGA) {
// In EGA mode, loadLutinSprite builds a CLUT8 flat buffer in lutin_mem+2.
// pitch here is sprw*4 (set in playAnimCore for EGA).
ega_BlitSprite(pixels, pitch, (uint16)sprw * 4, sprh, backbuffer, ofs);
} else {
- cga_BlitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
+ g_vm->_renderer->blitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
}
ex = x + sprw;
ey = y + sprh;
@@ -176,9 +176,9 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
if (anim_use_dot_effect)
copyScreenBlockWithDotEffect(backbuffer, updx, updy, updw, updh, frontbuffer);
else {
- cga_CopyScreenBlock(backbuffer, updw, updh, frontbuffer, ofs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, updw, updh, frontbuffer, ofs);
}
- cga_RestoreImage(sprit_load_buffer, backbuffer);
+ g_vm->_renderer->restoreImage(sprit_load_buffer, backbuffer);
last_anim_x = x;
last_anim_y = y;
@@ -189,7 +189,7 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
}
void animUndrawSprite(void) {
- cga_CopyScreenBlock(backbuffer, last_anim_width, last_anim_height, CGA_SCREENBUFFER, CalcXY_p(last_anim_x, last_anim_y));
+ g_vm->_renderer->copyScreenBlock(backbuffer, last_anim_width, last_anim_height, CGA_SCREENBUFFER, CalcXY_p(last_anim_x, last_anim_y));
last_anim_height = 0;
}
diff --git a/engines/chamber/cga.cpp b/engines/chamber/cga.cpp
index a378a75d065..8e21169acae 100644
--- a/engines/chamber/cga.cpp
+++ b/engines/chamber/cga.cpp
@@ -30,6 +30,7 @@
#include "chamber/cga.h"
#include "chamber/ega.h"
#include "chamber/ega_resource.h"
+#include "chamber/renderer.h"
#include "common/debug.h"
@@ -121,11 +122,7 @@ static const uint8 PALETTE_CGA2[4 * 3] = {
/*
Switch to CGA 320x200x2bpp mode
*/
-void switchToGraphicsMode(void) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_switchToGraphicsMode();
- return;
- }
+void CGARenderer::switchToGraphicsMode() {
if (g_system->getWidth() == 720) {
g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
} else {
@@ -148,11 +145,7 @@ void waitVBlank(void) {
g_system->updateScreen();
}
-void cga_ColorSelect(byte csel) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_switchToGraphicsMode();
- return;
- }
+void CGARenderer::colorSelect(byte csel) {
if (g_system->getWidth() == 720) {
g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
g_system->setCursorPalette(Graphics::HGC_G_PALETTE, 0, 2);
@@ -168,11 +161,7 @@ void cga_ColorSelect(byte csel) {
}
}
-void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_blitToScreen(dx, dy, w, h);
- return;
- }
+void CGARenderer::blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
if (!mainSurface) {
mainSurface = new Graphics::Surface();
}
@@ -198,7 +187,7 @@ void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
w = (w + (0x8 / g_vm->_screenBits - 1)) / (0x8 / g_vm->_screenBits);
for (int16 y = 0; y < h; y++) {
- uint16 line_start = cga_CalcXY(dx, dy + y);
+ uint16 line_start = calcXY(dx, dy + y);
byte *src = CGA_SCREENBUFFER + line_start;
byte *dst = (byte *)mainSurface->getBasePtr(dx, y + dy);
@@ -269,25 +258,15 @@ void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
return;
}
-void cga_blitToScreen(int16 ofs, int16 w, int16 h) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- int16 dy = ofs / EGA_BYTES_PER_LINE;
- int16 dx = ofs % EGA_BYTES_PER_LINE;
- ega_blitToScreen(dx, dy, w, h);
- return;
- }
+void CGARenderer::blitToScreen(int16 ofs, int16 w, int16 h) {
uint16 byte_per_line = w / (0x8 / g_vm->_screenBits);
int16 dy = ofs / byte_per_line;
int16 dx = (ofs % byte_per_line) * (0x8 / g_vm->_screenBits);
- cga_blitToScreen(dx, dy, w, h);
+ g_vm->_renderer->blitToScreen(dx, dy, w, h);
}
-void cga_BackBufferToRealFull(void) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_BackBufferToRealFull();
- return;
- }
+void CGARenderer::backBufferToRealFull() {
if (g_vm->_videoMode == Common::RenderMode::kRenderCGA) {
memcpy(CGA_SCREENBUFFER, backbuffer, sizeof(backbuffer));
@@ -319,24 +298,16 @@ void cga_BackBufferToRealFull(void) {
srcPtr += CGA_BYTES_PER_LINE;
}
}
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
-void cga_RealBufferToBackFull(void) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_RealBufferToBackFull();
- return;
- }
+void CGARenderer::realBufferToBackFull() {
memcpy(backbuffer, CGA_SCREENBUFFER, sizeof(backbuffer));
}
/*Copy interlaced screen data to another screen*/
/*NB! w is in bytes*/
-void cga_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, w * 4, h, target, ofs);
- return;
- }
+void CGARenderer::copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
uint16 oh = h;
uint16 oofs = ofs;
while (h--) {
@@ -347,17 +318,13 @@ void cga_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16
}
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
/*
Flip screen and backbuffer
*/
-void cga_SwapRealBackBuffer(void) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_SwapRealBackBuffer();
- return;
- }
+void CGARenderer::swapRealBackBuffer() {
uint16 i;
uint16 *s, *d;
waitVBlank();
@@ -369,18 +336,14 @@ void cga_SwapRealBackBuffer(void) {
*d++ = t;
}
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
/*
Copy current screen's pixels to scratch mem, put new pixels to screen
*/
-void cga_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_SwapScreenRect(pixels, w * 4, h, screen, ofs);
- return;
- }
+void CGARenderer::swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) {
byte *old = scratch_mem2;
uint16 oh = h;
uint16 oofs = ofs;
@@ -396,7 +359,7 @@ void cga_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 o
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
/*
@@ -404,30 +367,16 @@ Calc screen offset from normal pixel coordinates
Out:
screen offset
*/
-uint16 cga_CalcXY(uint16 x, uint16 y) {
- return CalcXY_p(x / 4, y);
+uint16 CGARenderer::calcXY(uint16 x, uint16 y) {
+ return calcXY_p(x / 4, y);
}
uint16 CalcXY(uint16 x, uint16 y) {
- if (g_vm->_videoMode == Common::kRenderEGA)
- return ega_CalcXY(x, y);
- else if (g_vm->_videoMode == Common::RenderMode::kRenderCGA)
- return cga_CalcXY(x, y);
- else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG)
- return HGA_CalcXY(x, y);
- else
- return 0;
+ return g_vm->_renderer->calcXY(x, y);
}
uint16 CalcXY_p(uint16 x, uint16 y) {
- if (g_vm->_videoMode == Common::kRenderEGA)
- return ega_CalcXY_p(x, y);
- else if (g_vm->_videoMode == Common::RenderMode::kRenderCGA)
- return cga_CalcXY_p(x, y);
- else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG)
- return HGA_CalcXY_p(x, y);
- else
- return 0;
+ return g_vm->_renderer->calcXY_p(x, y);
}
/*
@@ -435,7 +384,9 @@ Calc screen offset from packed pixel coordinates
Out:
screen offset
*/
-uint16 cga_CalcXY_p(uint16 x, uint16 y) {
+uint16 CGARenderer::calcXY_p(uint16 x, uint16 y) {
+ if (g_vm->_videoMode == Common::RenderMode::kRenderHercG)
+ return HGA_CalcXY_p(x, y);
uint16 ofs = 0;
if (y & 1)
ofs += g_vm->_line_offset;
@@ -449,7 +400,7 @@ backup screen rect to a buffer
Out:
next buffer ptr
*/
-byte *cga_BackupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
+byte *CGARenderer::backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
if (g_vm->_videoMode == Common::kRenderEGA)
return ega_BackupImage(screen, ofs, w * 4, h, buffer);
*(byte *)(buffer + 0) = h;
@@ -467,18 +418,14 @@ byte *cga_BackupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer
}
byte *cga_BackupImageReal(uint16 ofs, uint16 w, uint16 h) {
- return cga_BackupImage(CGA_SCREENBUFFER, ofs, w, h, scratch_mem2);
+ return g_vm->_renderer->backupImage(CGA_SCREENBUFFER, ofs, w, h, scratch_mem2);
}
/*
Blit progressive image to interlaced screen buffer
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
-void cga_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_Blit(pixels, pw * 4, w * 4, h, screen, ofs);
- return;
- }
+void CGARenderer::blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
byte *src = pixels;
uint16 oofs = ofs;
for (int16 y = 0; y < h; y++) {
@@ -490,23 +437,19 @@ void cga_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), h);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), h);
}
/*
Blit progressive image to interlaced screen buffer, then wait for VBlank
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
-void cga_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- cga_Blit(pixels, pw, w, h, screen, ofs);
+void CGARenderer::blitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ blit(pixels, pw, w, h, screen, ofs);
waitVBlank();
}
-void cga_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_Fill(cga_to_ega_color[(pixel >> 6) & 0x03], w * 4, h, screen, ofs);
- return;
- }
+void CGARenderer::fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 oofs = ofs;
for (int16 y = 0; y < h; y++) {
memset(screen + ofs, pixel, w);
@@ -516,22 +459,18 @@ void cga_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), h);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), h);
}
-void cga_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- cga_Fill(pixel, w, h, screen, ofs);
+void CGARenderer::fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ fill(pixel, w, h, screen, ofs);
waitVBlank();
}
/*
Restore saved image to target screen buffer
*/
-void cga_RestoreImage(byte *buffer, byte *target) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_RestoreImage(buffer, target);
- return;
- }
+void CGARenderer::restoreImage(byte *buffer, byte *target) {
uint16 w, h;
uint16 ofs;
@@ -543,24 +482,20 @@ void cga_RestoreImage(byte *buffer, byte *target) {
ofs = *(uint16 *)(buffer + 2);
buffer += 4; /*TODO: fix me for large int*/
- cga_Blit(buffer, w, w, h, target, ofs);
+ blit(buffer, w, w, h, target, ofs);
}
/*
Restore saved image from scratch mem to target screen buffer
*/
-void cga_RestoreBackupImage(byte *target) {
- cga_RestoreImage(scratch_mem2, target);
+void CGARenderer::restoreBackupImage(byte *target) {
+ restoreImage(scratch_mem2, target);
}
/*
Copy image's real screen data to backbuffer
*/
-void cga_RefreshImageData(byte *buffer) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_RefreshImageData(buffer);
- return;
- }
+void CGARenderer::refreshImageData(byte *buffer) {
uint16 w, h;
uint16 ofs;
@@ -571,18 +506,14 @@ void cga_RefreshImageData(byte *buffer) {
w = *(byte *)(buffer + 1);
ofs = *(uint16 *)(buffer + 2);
- cga_CopyScreenBlock(CGA_SCREENBUFFER, w, h, backbuffer, ofs);
+ copyScreenBlock(CGA_SCREENBUFFER, w, h, backbuffer, ofs);
}
/*
Draw a vertical line with origin x:y and length l, using color
NB! Line must not wrap around the edge
*/
-void cga_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_DrawVLine(x, y, l, cga_to_ega_color[color & 0x03], target);
- return;
- }
+void CGARenderer::drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
uint16 ofs;
uint16 mask = 0;
/*pixels are starting from top bits of byte*/
@@ -607,18 +538,14 @@ void cga_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
}
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen(x, y, 1, ol);
+ g_vm->_renderer->blitToScreen(x, y, 1, ol);
}
/*
Draw a horizontal line with origin x:y and length l, using color
NB! Line must not wrap around the edge
*/
-void cga_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_DrawHLine(x, y, l, cga_to_ega_color[color & 0x03], target);
- return;
- }
+void CGARenderer::drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
uint16 ofs;
uint16 mask = 0;
/*pixels are starting from top bits of byte*/
@@ -651,7 +578,7 @@ void cga_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
}
}
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen(x, y, ol, 1);
+ g_vm->_renderer->blitToScreen(x, y, ol, 1);
}
/*
@@ -659,9 +586,7 @@ Draw horizontal line of length l with color, add surrounding pixels (bmask, bpix
Return next line screen offset
NB! Length specifies byte length of inner segment, not amount of pixels
*/
-uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA)
- return ega_DrawHLineWithEnds(bmask, bpix, color, l, target, ofs);
+uint16 CGARenderer::drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
target[ofs] = (target[ofs] & (bmask >> 8)) | (bpix >> 8);
memset(target + ofs + 1, color, l);
target[ofs + 1 + l] = (target[ofs + 1 + l] & (bmask & 255)) | (bpix & 255);
@@ -671,7 +596,7 @@ uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, by
ofs += g_vm->_screenBPL;
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, l * 4 + 2, 1);
+ g_vm->_renderer->blitToScreen(oofs, l * 4 + 2, 1);
return ofs;
}
@@ -679,16 +604,12 @@ uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, by
/*
Print a character at current cursor pos, then advance
*/
-void cga_PrintChar(byte c, byte *target) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_PrintChar(c, target);
- return;
- }
+void CGARenderer::printChar(byte c, byte *target) {
uint16 i;
byte *font = carpc_data + c * g_vm->_fontHeight;
if (g_vm->_videoMode == Common::RenderMode::kRenderCGA) {
- uint16 ofs = cga_CalcXY_p(char_draw_coords_x++, char_draw_coords_y);
+ uint16 ofs = calcXY_p(char_draw_coords_x++, char_draw_coords_y);
for (i = 0; i < g_vm->_fontHeight; i++) {
c = *font++;
c = char_xlat_table[c];
@@ -699,7 +620,7 @@ void cga_PrintChar(byte c, byte *target) {
}
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen((char_draw_coords_x - 1) * g_vm->_fontWidth, char_draw_coords_y, g_vm->_fontWidth, g_vm->_fontHeight);
+ g_vm->_renderer->blitToScreen((char_draw_coords_x - 1) * g_vm->_fontWidth, char_draw_coords_y, g_vm->_fontWidth, g_vm->_fontHeight);
} else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG) {
const int16 START_X = char_draw_coords_x++;
@@ -712,7 +633,7 @@ void cga_PrintChar(byte c, byte *target) {
}
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen(START_X, START_Y, g_vm->_fontWidth, g_vm->_fontHeight);
+ g_vm->_renderer->blitToScreen(START_X, START_Y, g_vm->_fontWidth, g_vm->_fontHeight);
}
}
@@ -722,12 +643,7 @@ Blit progressive sprite (mask+pixel) from scratch buffer to interlaced screen bu
NB! width specify a number of bytes, not count of pixels
TODO: generalize/merge me with BlitSprite
*/
-void cga_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- // sprofs is in CGA mask+pixel bytes (2 per CGA unit); EGA needs 4 bytes per CGA unit, so *2
- ega_BlitScratchBackSprite(sprofs * 2, w * 4, h, screen, ofs);
- return;
- }
+void CGARenderer::blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
byte x;
byte *pixels = scratch_mem2 + 2 + sprofs;
uint16 oh = h;
@@ -742,45 +658,18 @@ void cga_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen,
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
-void cga_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_BlitFromBackBuffer(w * 4, h, screen, ofs);
- return;
- }
- cga_CopyScreenBlock(backbuffer, w, h, screen, ofs);
+void CGARenderer::blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
+ copyScreenBlock(backbuffer, w, h, screen, ofs);
}
/*
Blit progressive sprite (mask+pixel) to interlaced screen buffer
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
-void cga_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- // pixels are CGA mask+pixel pairs: pixels[x*2]=mask, pixels[x*2+1]=color (2bpp packed)
- // Decode each CGA byte (4 pixels) into 4 CLUT8 EGA pixels.
- // mask bit pair 0x00 = draw pixel, non-zero = keep background.
- uint16 oofs = ofs;
- for (uint16 row = 0; row < h; row++) {
- for (uint16 bx = 0; bx < w; bx++) {
- byte mb = pixels[bx * 2];
- byte cb = pixels[bx * 2 + 1];
- for (int p = 3; p >= 0; p--) {
- byte m = (mb >> (p * 2)) & 0x03;
- byte c = (cb >> (p * 2)) & 0x03;
- if (m == 0)
- screen[ofs + bx * 4 + (3 - p)] = cga_to_ega_color[c];
- }
- }
- pixels += pw;
- ofs += EGA_BYTES_PER_LINE;
- }
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w * 4, h);
- return;
- }
+void CGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
byte x;
uint16 oh = h;
uint16 oofs = ofs;
@@ -794,39 +683,14 @@ void cga_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, ui
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
/*
Blit progressive sprite (mask+pixel) to interlaced screen buffer. Flip the sprite horizontally
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
-void cga_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- // Same as cga_BlitSprite but pixels are drawn right-to-left (horizontal flip).
- // CGA ofs points to the rightmost byte of the sprite row on screen.
- uint16 oofs = ofs;
- for (uint16 row = 0; row < h; row++) {
- for (uint16 bx = 0; bx < w; bx++) {
- byte mb = pixels[bx * 2];
- byte cb = pixels[bx * 2 + 1];
- // bx=0 is rightmost group of 4 pixels, bx=w-1 is leftmost
- for (int p = 3; p >= 0; p--) {
- byte m = (mb >> (p * 2)) & 0x03;
- byte c = (cb >> (p * 2)) & 0x03;
- // pixel bx*4+(3-p) in sprite goes to screen position -(bx*4+(3-p))
- if (m == 0)
- screen[ofs - (bx * 4 + (3 - p))] = cga_to_ega_color[c];
- }
- }
- pixels += pw;
- ofs += EGA_BYTES_PER_LINE;
- }
- uint16 startX = (oofs % EGA_BYTES_PER_LINE) - (w * 4 - 1);
- if (screen == ega_screen)
- ega_blitToScreen(startX, oofs / EGA_BYTES_PER_LINE, w * 4, h);
- return;
- }
+void CGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
byte x;
uint16 oh = h;
uint16 oofs = ofs;
@@ -840,7 +704,7 @@ void cga_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
/*
@@ -851,11 +715,7 @@ Used to draw mouse cursor and backup what's under it
NB! width and pixelswidth specify a number of bytes, not count of pixels
NB! pixel+mask comes in reversed order, compared to regular BlitSprite
*/
-void cga_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_BlitSpriteBak(pixels, pw * 4, w * 4, h, screen, ofs, backup, mask);
- return;
- }
+void CGARenderer::blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
byte x;
uint16 oh = h;
uint16 oofs = ofs;
@@ -871,7 +731,7 @@ void cga_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen,
}
if (screen == CGA_SCREENBUFFER)
- cga_blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
+ g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -888,7 +748,7 @@ void drawSprite(byte *sprite, byte *screen, uint16 ofs) {
byte w, h;
w = *sprite++;
h = *sprite++;
- cga_BlitSprite(sprite, w * 2, w, h, screen, ofs);
+ g_vm->_renderer->blitSprite(sprite, w * 2, w, h, screen, ofs);
}
/*
@@ -904,7 +764,7 @@ void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) {
byte w, h;
w = *sprite++;
h = *sprite++;
- cga_BlitSpriteFlip(sprite, w * 2, w, h, screen, ofs);
+ g_vm->_renderer->blitSpriteFlip(sprite, w * 2, w, h, screen, ofs);
}
/*
@@ -1061,14 +921,14 @@ void cga_AnimLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *scree
uint16 epw = pw * 4;
pixels += epw * (h - 1);
for (i = 1; i <= h; i++) {
- ega_BlitAndWait(pixels, epw, w * 4, i, screen, ofs);
+ g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, ofs);
pixels -= epw;
}
return;
}
pixels += pw * (h - 1);
for (i = 1; i <= h; i++) {
- cga_BlitAndWait(pixels, pw, w, i, screen, ofs);
+ g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, ofs);
pixels -= pw;
}
}
@@ -1079,17 +939,10 @@ Pull and expand image from the right to left
NB! width and pixelswidth specify a number of bytes, not count of pixels
NB! ofs specifies top-right corner of the image
*/
-void cga_AnimLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void CGARenderer::animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 i;
- if (g_vm->_videoMode == Common::kRenderEGA) {
- for (i = 0; i < n; i++) {
- ega_BlitAndWait(pixels, pw * 4, (w + i) * 4, h, screen, ofs);
- ofs -= 4;
- }
- return;
- }
for (i = 0; i < n; i++) {
- cga_BlitAndWait(pixels, pw, w + i, h, screen, ofs);
+ blitAndWait(pixels, pw, w + i, h, screen, ofs);
ofs -= 1;
}
}
@@ -1099,17 +952,10 @@ Blit progressive image to interlaced screen buffer, then wait for VBlank
Push image from the left to right
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
-void cga_AnimLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void CGARenderer::animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 i;
- if (g_vm->_videoMode == Common::kRenderEGA) {
- for (i = 0; i < n; i++) {
- ega_BlitAndWait(pixels, pw * 4, (w + i) * 4, h, screen, ofs);
- pixels -= 4;
- }
- return;
- }
for (i = 0; i < n; i++) {
- cga_BlitAndWait(pixels, pw, w + i, h, screen, ofs);
+ blitAndWait(pixels, pw, w + i, h, screen, ofs);
pixels -= 1;
}
}
@@ -1123,15 +969,14 @@ NB! x:y specifies left-bottom coords
void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) {
uint16 i;
if (g_vm->_videoMode == Common::kRenderEGA) {
- uint16 epw = pw * 4;
for (i = 1; i <= h; i++) {
- ega_BlitAndWait(pixels, epw, w * 4, i, screen, ega_CalcXY_p(x, y));
+ g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, ega_CalcXY_p(x, y));
y -= 1;
}
return;
}
for (i = 1; i <= h; i++) {
- cga_BlitAndWait(pixels, pw, w, i, screen, cga_CalcXY_p(x, y));
+ g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, CalcXY_p(x, y));
y -= 1;
}
}
@@ -1140,11 +985,7 @@ void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen,
/*Fill gap with source screen data*/
/*offs points to block's bottom most line, data will be shifted to next line*/
/*NB! w is in bytes*/
-void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, w * 4, h + n, target, ofs);
- return;
- }
+void CGARenderer::hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1174,7 +1015,7 @@ void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16
memcpy(target + tofs, source + tofs, w);
if (screen == CGA_SCREENBUFFER) {
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenW);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenW);
}
waitVBlank();
@@ -1189,11 +1030,7 @@ void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16
/*Fill gap with source screen data*/
/*offs points to block's top most line, data will be shifted to previous line*/
/*NB! w is in bytes*/
-void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, w * 4, h + n, target, ofs);
- return;
- }
+void CGARenderer::hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1223,7 +1060,7 @@ void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w,
memcpy(target + tofs, source + tofs, w);
if (screen == CGA_SCREENBUFFER) {
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
waitVBlank();
@@ -1238,11 +1075,7 @@ void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w,
/*Fill gap with source screen data*/
/*offs points to block's left most column, data will be shifted to previous column*/
/*NB! w is in bytes*/
-void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, (w + n) * 4, h, target, ofs - n * 4);
- return;
- }
+void CGARenderer::hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1266,7 +1099,7 @@ void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16
}
if (screen == CGA_SCREENBUFFER) {
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
waitVBlank();
@@ -1279,11 +1112,7 @@ void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16
/*Fill gap with source screen data*/
/*offs points to block's right most column, data will be shifted to next column*/
/*NB! w is in bytes*/
-void cga_HideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, (w + n) * 4, h, target, ofs - w * 4);
- return;
- }
+void CGARenderer::hideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
while (n--) {
int16 i;
uint16 sofs, tofs;
@@ -1307,7 +1136,7 @@ void cga_HideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16
}
if (screen == CGA_SCREENBUFFER) {
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
waitVBlank();
@@ -1450,7 +1279,7 @@ static void fallPieces(scrpiece_t *pieces, byte *source, byte *target) {
}
if (target == CGA_SCREENBUFFER) {
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
waitVBlank();
@@ -1458,37 +1287,13 @@ static void fallPieces(scrpiece_t *pieces, byte *source, byte *target) {
} while (again);
}
-void cga_HideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, w * 4, h, target, ofs);
- return;
- }
+void CGARenderer::hideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
scrpiece_t *pieces = (scrpiece_t *)scratch_mem2;
screenToPieces(w, h, screen, ofs, pieces);
fallPieces(pieces, source, target);
}
-void cga_TraceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- /* EGA: Bresenham pixel-by-pixel copy from source to target */
- int16 x0 = sx, y0 = sy, x1 = ex, y1 = ey;
- int16 ddx = (x1 >= x0) ? 1 : -1;
- int16 ddy = (y1 >= y0) ? 1 : -1;
- int16 abw = (x1 >= x0) ? (x1 - x0) : (x0 - x1);
- int16 abh = (y1 >= y0) ? (y1 - y0) : (y0 - y1);
- int16 err = abw - abh;
- for (;;) {
- uint16 o = y0 * EGA_BYTES_PER_LINE + x0;
- if (o < EGA_SCREEN_SIZE)
- target[o] = source[o];
- if (x0 == x1 && y0 == y1) break;
- int16 e2 = err * 2;
- if (e2 > -abh) { err -= abh; x0 += ddx; }
- if (e2 < abw) { err += abw; y0 += ddy; }
- }
- /* Screen blit is done by the caller at the appropriate cadence */
- return;
- }
+void CGARenderer::traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) {
byte b0 = 0;
byte b1 = 0;
byte mask;
@@ -1566,7 +1371,7 @@ void cga_TraceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byt
}
if (target == CGA_SCREENBUFFER)
- cga_blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
+ g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
/*TODO: get rid of this structure and pass everything relevant as arguments?*/
@@ -1676,7 +1481,7 @@ static void cga_Zoom(zoom_t *params, byte tw, byte th, byte *source, byte *targe
params->yval_l = params->eh;
}
- cga_BlitAndWait(scratch_mem2, params->fw, params->fw, th + 2, target, finofs);
+ g_vm->_renderer->blitAndWait(scratch_mem2, params->fw, params->fw, th + 2, target, finofs);
}
#endif
@@ -1744,7 +1549,7 @@ static void cga_ZoomOpt(zoom_t *params, byte tw, byte th, byte *source, byte *ta
yval = params->eh << 8;
}
- cga_BlitAndWait(scratch_mem2, params->fw, params->fw, th + 2, target, finofs);
+ g_vm->_renderer->blitAndWait(scratch_mem2, params->fw, params->fw, th + 2, target, finofs);
}
/*
@@ -1752,12 +1557,7 @@ Draw image zoomed from w:h to nw:nx to target at specified ofs
Use backbuffer pixels to fill sides
NB! w/nw are the number of bytes, not pixels
*/
-void cga_ZoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- /* EGA: instant blit at original size, skip zoom */
- ega_BlitAndWait(pixels, w * 4, w * 4, h, target, ofs);
- return;
- }
+void CGARenderer::zoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs) {
zoom_t zoom;
zoom.pixels = pixels;
@@ -1823,11 +1623,7 @@ Use backbuffer pixels to fill sides
NB! w is the number of bytes, not pixels
NB! ofs is the final image top left corner, not the zoom origin
*/
-void cga_AnimZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_BlitAndWait(pixels, w * 4, w * 4, h, target, ofs);
- return;
- }
+void CGARenderer::animZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) {
uint16 finofs = ofs;
byte x, y, maxside;
@@ -1856,7 +1652,7 @@ void cga_AnimZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) {
cga_AnimZoomOpt(&zoom, w * 4 * 2, h * 2, maxside, target, ofs);
- cga_BlitAndWait(pixels, w, w, h, target, finofs);
+ blitAndWait(pixels, w, w, h, target, finofs);
}
/*
@@ -1930,11 +1726,7 @@ void cga_ZoomInplace(zoom_t *params, byte tw, byte th, byte *source, byte *targe
}
}
-void cga_ZoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_Blit(pixels, w * 4, w * 4, h, target, CalcXY_p(x, y));
- return;
- }
+void CGARenderer::zoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target) {
zoom_t zoom;
zoom.pixels = pixels;
diff --git a/engines/chamber/cga.h b/engines/chamber/cga.h
index ab6c2acabae..b66711e96e7 100644
--- a/engines/chamber/cga.h
+++ b/engines/chamber/cga.h
@@ -80,55 +80,19 @@ extern byte string_ended;
extern byte char_draw_max_width;
extern byte char_draw_max_height;
-void switchToGraphicsMode(void);
void switchToTextMode(void);
void waitVBlank(void);
-void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h);
-void cga_blitToScreen(int16 ofs, int16 w, int16 h);
-
-void cga_ColorSelect(byte csel);
-void cga_BackBufferToRealFull(void);
-void cga_RealBufferToBackFull(void);
-void cga_SwapRealBackBuffer(void);
-
-void cga_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs);
uint16 CalcXY(uint16 x, uint16 y);
uint16 CalcXY_p(uint16 x, uint16 y);
uint16 HGA_CalcXY(uint16 x, uint16 y);
uint16 HGA_CalcXY_p(uint16 x, uint16 y);
-uint16 cga_CalcXY(uint16 x, uint16 y);
uint16 cga_CalcXY_p(uint16 x, uint16 y);
-void cga_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-
-byte *cga_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer);
byte *cga_BackupImageReal(uint16 ofs, uint16 w, uint16 h);
-void cga_RestoreImage(byte *buffer, byte *target);
-void cga_RefreshImageData(byte *buffer);
-void cga_RestoreBackupImage(byte *target);
-
-void cga_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void cga_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void cga_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
-void cga_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
-void cga_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
-uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs);
-
-void cga_PrintChar(byte c, byte *target);
-
-void cga_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void cga_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs);
-
-void cga_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void cga_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
-void cga_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask);
-
void drawSprite(byte *sprite, byte *screen, uint16 ofs);
void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs);
@@ -144,22 +108,6 @@ byte *loadPersSprit(byte index);
void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y);
void cga_AnimLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void cga_AnimLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void cga_AnimLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
-void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-void cga_HideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-
-void cga_HideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-
-void cga_TraceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target);
-
-void cga_ZoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs);
-void cga_AnimZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs);
-
-void cga_ZoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target);
} // End of namespace Chamber
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 65eef6c6f5a..d1138970828 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -33,6 +33,7 @@
#include "engines/util.h"
#include "chamber/chamber.h"
+#include "chamber/renderer.h"
namespace Chamber {
@@ -64,12 +65,18 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
_screenH = _screenW = _screenBits = _screenBPL = _screenPPB = 0;
_line_offset = _line_offset2 = _fontHeight = _fontWidth = 0;
+
+ if (_videoMode == Common::kRenderEGA)
+ _renderer = new EGARenderer();
+ else
+ _renderer = new CGARenderer();
}
ChamberEngine::~ChamberEngine() {
// Dispose your resources here
delete _rnd;
delete[] _pxiData;
+ delete _renderer;
deinitSound();
}
diff --git a/engines/chamber/chamber.h b/engines/chamber/chamber.h
index d70a40c208c..3eeaffb05af 100644
--- a/engines/chamber/chamber.h
+++ b/engines/chamber/chamber.h
@@ -28,6 +28,7 @@
#include "common/rendermode.h"
#include "engines/engine.h"
#include "gui/debugger.h"
+#include "chamber/renderer.h"
namespace Audio {
class SoundHandle;
@@ -98,6 +99,8 @@ public:
Audio::PCSpeaker *_speaker;
+ Renderer *_renderer = nullptr;
+
private:
const ADGameDescription *_gameDescription;
};
diff --git a/engines/chamber/dialog.cpp b/engines/chamber/dialog.cpp
index c9444dbbdcb..7298143abd4 100644
--- a/engines/chamber/dialog.cpp
+++ b/engines/chamber/dialog.cpp
@@ -92,10 +92,10 @@ void popDirtyRects(byte kind) {
byte width, height;
uint16 offs;
while (findDirtyRectAndFree(kind, &x, &y, &width, &height, &offs)) {
- cga_CopyScreenBlock(backbuffer, width, height, frontbuffer, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, frontbuffer, offs);
if (kind == DirtyRectBubble) {
/*pop bubble's spike*/
- cga_CopyScreenBlock(backbuffer, 2, 21, frontbuffer, offs = (x << 8) | y);
+ g_vm->_renderer->copyScreenBlock(backbuffer, 2, 21, frontbuffer, offs = (x << 8) | y);
}
}
}
@@ -125,25 +125,25 @@ void drawPersonBubble(byte x, byte y, byte flags, byte *msg) {
/*upper border*/
ofs = CalcXY_p(x, y);
- ofs = cga_DrawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = cga_DrawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = cga_DrawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = cga_DrawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
/*body*/
char_draw_coords_x = x;
char_draw_coords_y = y + 4;
for (string_ended = 0; !string_ended; char_draw_coords_y += 6) {
- cga_PrintChar(0x3B, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar(0x3B, CGA_SCREENBUFFER);
msg = printStringPadded(msg, CGA_SCREENBUFFER);
- cga_PrintChar(0x3C, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar(0x3C, CGA_SCREENBUFFER);
char_draw_coords_x = x;
}
ofs = CalcXY_p(x, char_draw_coords_y);
- ofs = cga_DrawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = cga_DrawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
w = char_draw_max_width + 2;
h = char_draw_coords_y - y + 2;
diff --git a/engines/chamber/ega.cpp b/engines/chamber/ega.cpp
index da6d7b43db6..f7cc05dca11 100644
--- a/engines/chamber/ega.cpp
+++ b/engines/chamber/ega.cpp
@@ -30,6 +30,7 @@
#include "chamber/ega.h"
#include "chamber/input.h"
#include "chamber/resdata.h"
+#include "chamber/renderer.h"
#include "chamber/room.h"
namespace Chamber {
@@ -65,14 +66,12 @@ const byte EGA_PALETTE[16 * 3] = {
byte *ega_screen = CGA_SCREENBUFFER;
byte *ega_backbuffer = backbuffer;
+const byte cga_to_ega_color[] = { 0, 11, 13, 15 };
+
// ---------------------------------------------------------------------------
// Screen management
// ---------------------------------------------------------------------------
-void ega_switchToGraphicsMode() {
- g_system->getPaletteManager()->setPalette(EGA_PALETTE, 0, 16);
-}
-
void ega_blitToScreen(int16 x, int16 y, int16 w, int16 h) {
if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
@@ -88,23 +87,6 @@ void ega_blitToScreen(int16 x, int16 y, int16 w, int16 h) {
g_system->updateScreen();
}
-void ega_BackBufferToRealFull() {
- memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
-}
-
-void ega_RealBufferToBackFull() {
- memcpy(ega_backbuffer, ega_screen, EGA_SCREEN_SIZE);
-}
-
-void ega_SwapRealBackBuffer() {
- static byte tmp[EGA_SCREEN_SIZE];
- memcpy(tmp, ega_screen, EGA_SCREEN_SIZE);
- memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
- memcpy(ega_backbuffer, tmp, EGA_SCREEN_SIZE);
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
-}
-
// ---------------------------------------------------------------------------
// Offset helpers
// EGA: linear layout, no interlacing â offset = y * 320 + x
@@ -135,21 +117,6 @@ void ega_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16
ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
}
-void ega_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- byte *old = scratch_mem2;
- uint16 oofs = ofs;
- for (uint16 y = 0; y < h; y++) {
- for (uint16 i = 0; i < w; i++) {
- *old++ = screen[ofs + i];
- screen[ofs + i] = *pixels++;
- }
- ofs += EGA_BYTES_PER_LINE;
- }
-
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
-}
-
// EGA backup image header (6 bytes):
// [0] h (byte)
// [1] w_cga = w_pixels / 4 (byte, CGA byte-units; avoids overflow for w <= 1020 px)
@@ -170,147 +137,297 @@ byte *ega_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer
return buffer;
}
-void ega_RestoreImage(byte *buffer, byte *target) {
+void ega_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
+ ega_CopyScreenBlock(ega_backbuffer, w, h, screen, ofs);
+}
+
+void ega_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < w; x++) {
+ if (pixels[x] != 0)
+ screen[ofs + x] = pixels[x];
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+void ega_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 oofs = ofs;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < w; x++) {
+ if (pixels[w - 1 - x] != 0)
+ screen[ofs + x] = pixels[w - 1 - x];
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+}
+
+byte ega_fond_clean[EGA_SCREEN_SIZE];
+
+void ega_drawBackground(byte *target) {
+ memcpy(target, ega_fond_clean, EGA_SCREEN_SIZE);
+}
+
+Graphics::Surface *ega_loadFond(const char *filename) {
+ Common::File fd;
+ if (!fd.open(filename)) {
+ warning("ega_loadFond: cannot open %s", filename);
+ return nullptr;
+ }
+
+ static byte planarData[EGA_PLANAR_SIZE * 4];
+ fd.read(planarData, sizeof(planarData));
+
+ byte *dst = ega_backbuffer;
+ for (uint i = 0; i < EGA_PLANAR_SIZE; i++) {
+ for (int bit = 7; bit >= 0; bit--) {
+ byte px =
+ (((planarData[i] >> bit) & 1) ) |
+ (((planarData[i + EGA_PLANAR_SIZE] >> bit) & 1) << 1) |
+ (((planarData[i + EGA_PLANAR_SIZE*2] >> bit) & 1) << 2) |
+ (((planarData[i + EGA_PLANAR_SIZE*3] >> bit) & 1) << 3);
+ *dst++ = px;
+ }
+ }
+
+ memcpy(ega_fond_clean, ega_backbuffer, EGA_SCREEN_SIZE);
+
+ Graphics::Surface *surface = new Graphics::Surface();
+ surface->init(EGA_WIDTH, EGA_HEIGHT,
+ EGA_BYTES_PER_LINE,
+ ega_backbuffer,
+ Graphics::PixelFormat::createFormatCLUT8());
+ return surface;
+}
+
+// ===========================================================================
+// EGARenderer method implementations
+// Implementations live directly here; no delegation to removed ega_* helpers.
+// ===========================================================================
+
+void EGARenderer::switchToGraphicsMode() {
+ g_system->getPaletteManager()->setPalette(EGA_PALETTE, 0, 16);
+}
+
+void EGARenderer::colorSelect(byte /*csel*/) {
+ g_system->getPaletteManager()->setPalette(EGA_PALETTE, 0, 16);
+}
+
+void EGARenderer::blitToScreen(int16 x, int16 y, int16 w, int16 h) {
+ ega_blitToScreen(x, y, w, h);
+}
+
+void EGARenderer::blitToScreen(int16 ofs, int16 w, int16 h) {
+ int16 dy = ofs / EGA_BYTES_PER_LINE;
+ int16 dx = ofs % EGA_BYTES_PER_LINE;
+ ega_blitToScreen(dx, dy, w, h);
+}
+
+uint16 EGARenderer::calcXY(uint16 x, uint16 y) {
+ return y * EGA_BYTES_PER_LINE + x;
+}
+
+uint16 EGARenderer::calcXY_p(uint16 x, uint16 y) {
+ return y * EGA_BYTES_PER_LINE + x * 4;
+}
+
+void EGARenderer::backBufferToRealFull() {
+ memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+}
+
+void EGARenderer::realBufferToBackFull() {
+ memcpy(ega_backbuffer, ega_screen, EGA_SCREEN_SIZE);
+}
+
+void EGARenderer::swapRealBackBuffer() {
+ static byte tmp[EGA_SCREEN_SIZE];
+ memcpy(tmp, ega_screen, EGA_SCREEN_SIZE);
+ memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
+ memcpy(ega_backbuffer, tmp, EGA_SCREEN_SIZE);
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+}
+
+void EGARenderer::copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ ega_CopyScreenBlock(source, w * 4, h, target, ofs);
+}
+
+void EGARenderer::swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ byte *old = scratch_mem2;
+ uint16 oofs = ofs;
+ uint16 pw = w * 4;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 i = 0; i < pw; i++) {
+ *old++ = screen[ofs + i];
+ screen[ofs + i] = *pixels++;
+ }
+ ofs += EGA_BYTES_PER_LINE;
+ }
+
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, pw, h);
+}
+
+byte *EGARenderer::backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
+ return ega_BackupImage(screen, ofs, w * 4, h, buffer);
+}
+
+void EGARenderer::restoreImage(byte *buffer, byte *target) {
if (!buffer)
return;
uint16 h = *(byte *)(buffer + 0);
- uint16 w = (uint16)*(byte *)(buffer + 1) * 4; // restore pixel width
+ uint16 w = (uint16)*(byte *)(buffer + 1) * 4;
uint16 ofs = *(uint16 *)(buffer + 2);
buffer += 4;
- ega_Blit(buffer, w, w, h, target, ofs);
+ blit(buffer, w / 4, w / 4, h, target, ofs);
}
-void ega_RefreshImageData(byte *buffer) {
+void EGARenderer::refreshImageData(byte *buffer) {
if (!buffer)
return;
uint16 h = *(byte *)(buffer + 0);
- uint16 w = (uint16)*(byte *)(buffer + 1) * 4; // restore pixel width
+ uint16 w = (uint16)*(byte *)(buffer + 1) * 4;
uint16 ofs = *(uint16 *)(buffer + 2);
ega_CopyScreenBlock(ega_screen, w, h, ega_backbuffer, ofs);
}
-void ega_RestoreBackupImage(byte *target) {
- ega_RestoreImage(scratch_mem2, target);
+void EGARenderer::restoreBackupImage(byte *target) {
+ restoreImage(scratch_mem2, target);
}
-void ega_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void EGARenderer::blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 oofs = ofs;
+ uint16 pw_px = pw * 4;
+ uint16 w_px = w * 4;
for (uint16 y = 0; y < h; y++) {
- memcpy(screen + ofs, pixels, w);
- pixels += pw;
+ memcpy(screen + ofs, pixels, w_px);
+ pixels += pw_px;
ofs += EGA_BYTES_PER_LINE;
}
if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
-void ega_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- ega_Blit(pixels, pw, w, h, screen, ofs);
- // waitVBlank is defined in cga.cpp and calls pollInput + delayMillis
+void EGARenderer::blitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ blit(pixels, pw, w, h, screen, ofs);
pollInput();
g_system->delayMillis(10);
}
-void ega_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void EGARenderer::fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ byte egaColor = cga_to_ega_color[(pixel >> 6) & 0x03];
uint16 oofs = ofs;
- debug(1, "ega_Fill: color=%d w=%d h=%d ofs=%d (x=%d y=%d)", pixel, w, h, ofs, ofs % EGA_BYTES_PER_LINE, ofs / EGA_BYTES_PER_LINE);
+ uint16 w_px = w * 4;
+ debug(1, "EGARenderer::fill: color=%d w=%d h=%d ofs=%d", egaColor, w_px, h, ofs);
for (uint16 y = 0; y < h; y++) {
- memset(screen + ofs, pixel, w);
+ memset(screen + ofs, egaColor, w_px);
ofs += EGA_BYTES_PER_LINE;
}
if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
-void ega_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- ega_Fill(pixel, w, h, screen, ofs);
+void EGARenderer::fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ fill(pixel, w, h, screen, ofs);
pollInput();
g_system->delayMillis(10);
}
-void ega_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
- ega_CopyScreenBlock(ega_backbuffer, w, h, screen, ofs);
-}
-
-// ---------------------------------------------------------------------------
-// Sprite blitters
-// EGA sprites are stored as decoded CLUT8: 1 byte per pixel, index 0 = transparent
-// ---------------------------------------------------------------------------
-
-void ega_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void EGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 oofs = ofs;
- for (uint16 y = 0; y < h; y++) {
- for (uint16 x = 0; x < w; x++) {
- if (pixels[x] != 0)
- screen[ofs + x] = pixels[x];
+ for (uint16 row = 0; row < h; row++) {
+ for (uint16 bx = 0; bx < w; bx++) {
+ byte mb = pixels[bx * 2];
+ byte cb = pixels[bx * 2 + 1];
+ for (int p = 3; p >= 0; p--) {
+ byte m = (mb >> (p * 2)) & 0x03;
+ byte c = (cb >> (p * 2)) & 0x03;
+ if (m == 0)
+ screen[ofs + bx * 4 + (3 - p)] = cga_to_ega_color[c];
+ }
}
pixels += pw;
ofs += EGA_BYTES_PER_LINE;
}
-
if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w * 4, h);
}
-void ega_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void EGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 oofs = ofs;
- for (uint16 y = 0; y < h; y++) {
- for (uint16 x = 0; x < w; x++) {
- if (pixels[w - 1 - x] != 0)
- screen[ofs + x] = pixels[w - 1 - x];
+ for (uint16 row = 0; row < h; row++) {
+ for (uint16 bx = 0; bx < w; bx++) {
+ byte mb = pixels[bx * 2];
+ byte cb = pixels[bx * 2 + 1];
+ for (int p = 3; p >= 0; p--) {
+ byte m = (mb >> (p * 2)) & 0x03;
+ byte c = (cb >> (p * 2)) & 0x03;
+ if (m == 0)
+ screen[ofs - (bx * 4 + (3 - p))] = cga_to_ega_color[c];
+ }
}
pixels += pw;
ofs += EGA_BYTES_PER_LINE;
}
-
+ uint16 startX = (oofs % EGA_BYTES_PER_LINE) - (w * 4 - 1);
if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ ega_blitToScreen(startX, oofs / EGA_BYTES_PER_LINE, w * 4, h);
}
-void ega_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
+void EGARenderer::blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
uint16 oofs = ofs;
+ uint16 w_px = w * 4;
for (uint16 y = 0; y < h; y++) {
- for (uint16 x = 0; x < w; x++) {
+ for (uint16 x = 0; x < w_px; x++) {
*backup++ = screen[ofs + x];
if (pixels[x] != 0)
screen[ofs + x] = pixels[x] & mask;
}
- pixels += pw;
+ pixels += pw * 4;
ofs += EGA_BYTES_PER_LINE;
}
if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
-void ega_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- byte *pixels = scratch_mem2 + 2 + sprofs;
- uint16 oofs = ofs;
+void EGARenderer::blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ byte *pixels = scratch_mem2 + 2 + sprofs * 2;
+ uint16 w_px = w * 4;
+ uint16 oofs = ofs;
for (uint16 y = 0; y < h; y++) {
- for (uint16 x = 0; x < w; x++) {
- // In CGA the scratch sprite has (mask, pixel) pairs per pixel-byte.
- // In EGA mode the scratch sprite is plain CLUT8; use ega_backbuffer for transparency.
+ for (uint16 x = 0; x < w_px; x++) {
byte p = pixels[x];
screen[ofs + x] = (p != 0) ? p : ega_backbuffer[ofs + x];
}
- pixels += w;
+ pixels += w_px;
ofs += EGA_BYTES_PER_LINE;
}
if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
-// ---------------------------------------------------------------------------
-// Draw primitives
-// ---------------------------------------------------------------------------
+void EGARenderer::blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
+ ega_BlitFromBackBuffer(w * 4, h, screen, ofs);
+}
-void ega_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+void EGARenderer::drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+ byte egaColor = cga_to_ega_color[color & 0x03];
uint16 ofs = ega_CalcXY(x, y);
for (uint16 i = 0; i < l; i++) {
- target[ofs] = color;
+ target[ofs] = egaColor;
ofs += EGA_BYTES_PER_LINE;
}
@@ -318,43 +435,37 @@ void ega_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
ega_blitToScreen(x, y, 1, l);
}
-void ega_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+void EGARenderer::drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
+ byte egaColor = cga_to_ega_color[color & 0x03];
uint16 ofs = ega_CalcXY(x, y);
- memset(target + ofs, color, l);
+ memset(target + ofs, egaColor, l);
if (target == ega_screen)
ega_blitToScreen(x, y, l, 1);
}
-uint16 ega_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
- // bmask / bpix encode end-cap bytes in CGA 2bpp packed format (high byte = left, low byte = right).
- // color is a CGA 2bpp packed fill byte. l is inner segment length in CGA bytes.
- // Expand everything to CLUT8 EGA pixels: each CGA byte â 4 pixels.
+uint16 EGARenderer::drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
uint16 oofs = ofs;
- // Left end-cap: expand bpix high byte (4 pixels), applying bmask
- byte leftPix = (bpix >> 8) & 0xFF;
+ byte leftPix = (bpix >> 8) & 0xFF;
byte leftMask = (bmask >> 8) & 0xFF;
for (int p = 3; p >= 0; p--) {
- byte m = (leftMask >> (p * 2)) & 0x03;
- byte px = (leftPix >> (p * 2)) & 0x03;
+ byte m = (leftMask >> (p * 2)) & 0x03;
+ byte px = (leftPix >> (p * 2)) & 0x03;
if (m == 0)
target[ofs] = cga_to_ega_color[px];
- // else: leave existing pixel (masked out)
ofs++;
}
- // Inner segment: l CGA bytes â l*4 pixels of solid color
byte egaColor = cga_to_ega_color[(color >> 6) & 0x03];
memset(target + ofs, egaColor, l * 4);
ofs += l * 4;
- // Right end-cap: expand bpix low byte (4 pixels), applying bmask
- byte rightPix = bpix & 0xFF;
+ byte rightPix = bpix & 0xFF;
byte rightMask = bmask & 0xFF;
for (int p = 3; p >= 0; p--) {
- byte m = (rightMask >> (p * 2)) & 0x03;
- byte px = (rightPix >> (p * 2)) & 0x03;
+ byte m = (rightMask >> (p * 2)) & 0x03;
+ byte px = (rightPix >> (p * 2)) & 0x03;
if (m == 0)
target[ofs] = cga_to_ega_color[px];
ofs++;
@@ -367,17 +478,7 @@ uint16 ega_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, by
return oofs + EGA_BYTES_PER_LINE;
}
-// CGA palette 1 high-intensity â EGA color index mapping
-// CGA 0 (background) â EGA 0 (black)
-// CGA 1 (bright cyan) â EGA 11 (bright cyan)
-// CGA 2 (bright magenta) â EGA 13 (bright magenta)
-// CGA 3 (white) â EGA 15 (white)
-const byte cga_to_ega_color[] = { 0, 11, 13, 15 };
-
-void ega_PrintChar(byte c, byte *target) {
- // carpc_data: 64 characters à fontHeight bytes, each byte encodes a 4-pixel row.
- // char_xlat_table maps each font byte to a CGA 2bpp packed byte.
- // We extract the 4 CGA 2-bit color values and map to EGA indices.
+void EGARenderer::printChar(byte c, byte *target) {
byte *font = carpc_data + c * g_vm->_fontHeight;
uint16 ofs = ega_CalcXY_p(char_draw_coords_x, char_draw_coords_y);
@@ -398,59 +499,68 @@ void ega_PrintChar(byte c, byte *target) {
g_vm->_fontWidth, g_vm->_fontHeight);
}
-// ---------------------------------------------------------------------------
-// Background loader (Phase 1 milestone)
-// Reads a 32000-byte 4-plane EGA file and unpacks it into ega_backbuffer.
-// Format: 4 planes à 8000 bytes.
-// plane[0] = bits 0 of each pixel (8 pixels per byte, MSB first)
-// plane[1] = bits 1
-// plane[2] = bits 2
-// plane[3] = bits 3
-// Resulting pixel index = bit3<<3 | bit2<<2 | bit1<<1 | bit0
-// Reference: kult/kult.cpp:268-285
-// ---------------------------------------------------------------------------
-Graphics::Surface *ega_loadFond(const char *filename) {
- Common::File fd;
- if (!fd.open(filename)) {
- warning("ega_loadFond: cannot open %s", filename);
- return nullptr;
+void EGARenderer::animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ for (uint16 i = 0; i < n; i++) {
+ blitAndWait(pixels, pw, w + i, h, screen, ofs);
+ ofs -= 4;
}
+}
- static byte planarData[EGA_PLANAR_SIZE * 4];
- fd.read(planarData, sizeof(planarData));
-
- byte *dst = ega_backbuffer;
- for (uint i = 0; i < EGA_PLANAR_SIZE; i++) {
- for (int bit = 7; bit >= 0; bit--) {
- byte px =
- (((planarData[i] >> bit) & 1) ) |
- (((planarData[i + EGA_PLANAR_SIZE] >> bit) & 1) << 1) |
- (((planarData[i + EGA_PLANAR_SIZE*2]>> bit) & 1) << 2) |
- (((planarData[i + EGA_PLANAR_SIZE*3]>> bit) & 1) << 3);
- *dst++ = px;
- }
+void EGARenderer::animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ for (uint16 i = 0; i < n; i++) {
+ blitAndWait(pixels, pw, w + i, h, screen, ofs);
+ pixels -= 4;
}
+}
- // Save a clean copy for background restoration
- memcpy(ega_fond_clean, ega_backbuffer, EGA_SCREEN_SIZE);
+void EGARenderer::hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ ega_CopyScreenBlock(source, w * 4, h + n, target, ofs);
+}
- // Return a Graphics::Surface that wraps ega_backbuffer so the existing
- // loadFond() caller chain (which expects a Surface*) stays happy.
- Graphics::Surface *surface = new Graphics::Surface();
- surface->init(EGA_WIDTH, EGA_HEIGHT,
- EGA_BYTES_PER_LINE,
- ega_backbuffer,
- Graphics::PixelFormat::createFormatCLUT8());
- return surface;
+void EGARenderer::hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ ega_CopyScreenBlock(source, w * 4, h + n, target, ofs);
}
-// Clean copy of decoded FOND.EGA for room background restoration
-byte ega_fond_clean[EGA_SCREEN_SIZE];
+void EGARenderer::hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ ega_CopyScreenBlock(source, (w + n) * 4, h, target, ofs - n * 4);
+}
-void ega_drawBackground(byte *target) {
- // In EGA mode, the FOND.EGA contains the pre-rendered background.
- // Restore the entire frame from the saved clean copy.
- memcpy(target, ega_fond_clean, EGA_SCREEN_SIZE);
+void EGARenderer::hideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ ega_CopyScreenBlock(source, (w + n) * 4, h, target, ofs - w * 4);
+}
+
+void EGARenderer::hideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+ ega_CopyScreenBlock(source, w * 4, h, target, ofs);
+}
+
+void EGARenderer::traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) {
+ int16 x0 = sx, y0 = sy, x1 = ex, y1 = ey;
+ int16 ddx = (x1 >= x0) ? 1 : -1;
+ int16 ddy = (y1 >= y0) ? 1 : -1;
+ int16 abw = (x1 >= x0) ? (x1 - x0) : (x0 - x1);
+ int16 abh = (y1 >= y0) ? (y1 - y0) : (y0 - y1);
+ int16 err = abw - abh;
+ for (;;) {
+ uint16 o = y0 * EGA_BYTES_PER_LINE + x0;
+ if (o < EGA_SCREEN_SIZE)
+ target[o] = source[o];
+ if (x0 == x1 && y0 == y1) break;
+ int16 e2 = err * 2;
+ if (e2 > -abh) { err -= abh; x0 += ddx; }
+ if (e2 < abw) { err += abw; y0 += ddy; }
+ }
+}
+
+void EGARenderer::zoomImage(byte *pixels, byte w, byte h, byte /*nw*/, byte /*nh*/, byte *target, uint16 ofs) {
+ blitAndWait(pixels, w, w, h, target, ofs);
+}
+
+void EGARenderer::animZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) {
+ blitAndWait(pixels, w, w, h, target, ofs);
+}
+
+void EGARenderer::zoomInplaceXY(byte *pixels, byte w, byte h, byte /*nw*/, byte /*nh*/, uint16 x, uint16 y, byte *target) {
+ blit(pixels, w, w, h, target, ega_CalcXY_p(x, y));
}
} // End of namespace Chamber
diff --git a/engines/chamber/input.cpp b/engines/chamber/input.cpp
index c017331df65..714dbf58a4d 100644
--- a/engines/chamber/input.cpp
+++ b/engines/chamber/input.cpp
@@ -189,7 +189,7 @@ int16 askQuitGame(void) {
}
}
}
- cga_CopyScreenBlock(backbuffer, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, frontbuffer, CalcXY_p(draw_x, draw_y));
+ g_vm->_renderer->copyScreenBlock(backbuffer, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, frontbuffer, CalcXY_p(draw_x, draw_y));
keymapper->getKeymap("quit-dialog")->setEnabled(false);
keymapper->getKeymap("chamber-default")->setEnabled(true);
diff --git a/engines/chamber/invent.cpp b/engines/chamber/invent.cpp
index 9f5adf31e45..9fea7ba147a 100644
--- a/engines/chamber/invent.cpp
+++ b/engines/chamber/invent.cpp
@@ -79,7 +79,7 @@ void drawInventoryBox(uint16 filtermask, uint16 filtervalue) {
continue;
if (count == 0) {
/*once first valid item found, draw the box*/
- cga_FillAndWait(inv_bgcolor, 64 / 4, 64, CGA_SCREENBUFFER, CalcXY_p(232 / 4, 56));
+ g_vm->_renderer->fillAndWait(inv_bgcolor, 64 / 4, 64, CGA_SCREENBUFFER, CalcXY_p(232 / 4, 56));
playSound(20);
}
inventory_spots[count].name = inventory_items[i].name;
@@ -125,7 +125,7 @@ void openInventory(uint16 filtermask, uint16 filtervalue) {
} while (buttons == 0);
undrawCursor(frontbuffer);
}
- cga_RestoreImage(scratch_mem2, frontbuffer);
+ g_vm->_renderer->restoreImage(scratch_mem2, frontbuffer);
playSound(20);
switch (((item_t *)script_vars[kScrPool3_CurrentItem])->name) {
case 108: /*DAGGER*/
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index 63187dd9262..0d7097520cf 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -274,7 +274,7 @@ Common::Error ChamberEngine::init() {
IFGM_Init();
- switchToGraphicsMode();
+ g_vm->_renderer->switchToGraphicsMode();
/* Install timer callback */
initTimer();
@@ -284,9 +284,9 @@ Common::Error ChamberEngine::init() {
if (g_vm->_videoMode == Common::RenderMode::kRenderEGA) {
/* EGA title screen â load planar EGA splash (same format as FOND.EGA) */
splash = ega_loadFond("PRESEGA.EGA");
- cga_ColorSelect(0x30); // sets EGA palette
+ g_vm->_renderer->colorSelect(0x30); // sets EGA palette
if (splash)
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
} else {
if (g_vm->getLanguage() == Common::EN_USA) {
/* Load title screen */
@@ -306,12 +306,12 @@ Common::Error ChamberEngine::init() {
if (!isCustomHerc) {
/* Select intense cyan-mageta palette */
- cga_ColorSelect(0x30);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->colorSelect(0x30);
+ g_vm->_renderer->backBufferToRealFull();
} else {
/* Set authentic Hercules Green phosphor palette */
g_system->getPaletteManager()->setPalette(Graphics::HGC_G_PALETTE, 0, 2);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
}
}
@@ -321,12 +321,6 @@ Common::Error ChamberEngine::init() {
delete splash;
}
-<<<<<<< HEAD
- splash->free();
- delete splash;
-
-=======
->>>>>>> 6182990634e (chamber: Implement EGA rendering path)
/* Wait for a keypress */
clearKeyboard();
readKeyboardChar();
@@ -351,7 +345,7 @@ Common::Error ChamberEngine::init() {
if (_shouldQuit)
return Common::kNoError;
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
clearKeyboard();
/* Wait for a valid language choice */
@@ -372,7 +366,7 @@ Common::Error ChamberEngine::init() {
res_diali[0].name[4] = c;
if (g_vm->getLanguage() != Common::EN_USA)
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
/* Load script and other static resources */
/* Those are normally embedded in the executable, but here we load extracted ones*/
@@ -410,7 +404,7 @@ Common::Error ChamberEngine::init() {
}
/*TODO: is this necessary?*/
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
/* Create clean game state snapshot */
saveRestartGame();
diff --git a/engines/chamber/menu.cpp b/engines/chamber/menu.cpp
index 4c655e3dc04..85653292fd3 100644
--- a/engines/chamber/menu.cpp
+++ b/engines/chamber/menu.cpp
@@ -173,7 +173,7 @@ void actionsMenu(byte **pinfo) {
drawSpriteN(25, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
}
- cga_RestoreBackupImage(CGA_SCREENBUFFER);
+ g_vm->_renderer->restoreBackupImage(CGA_SCREENBUFFER);
*pinfo += numchoices * 3;
}
diff --git a/engines/chamber/portrait.cpp b/engines/chamber/portrait.cpp
index d96c512312a..6d864dc50f7 100644
--- a/engines/chamber/portrait.cpp
+++ b/engines/chamber/portrait.cpp
@@ -353,12 +353,12 @@ void drawBoxAroundSpot(void) {
w *= g_vm->_screenPPB;
}
- cga_DrawVLine(x, y, h - 1, 0, CGA_SCREENBUFFER);
- cga_DrawHLine(x, y, w - 1, 0, CGA_SCREENBUFFER);
- cga_DrawVLine(x + w - 1, y, h - 1, 0, CGA_SCREENBUFFER);
- cga_DrawHLine(x, y + h - 1, w - 1, 0, CGA_SCREENBUFFER);
+ g_vm->_renderer->drawVLine(x, y, h - 1, 0, CGA_SCREENBUFFER);
+ g_vm->_renderer->drawHLine(x, y, w - 1, 0, CGA_SCREENBUFFER);
+ g_vm->_renderer->drawVLine(x + w - 1, y, h - 1, 0, CGA_SCREENBUFFER);
+ g_vm->_renderer->drawHLine(x, y + h - 1, w - 1, 0, CGA_SCREENBUFFER);
- cga_RefreshImageData(*spot_sprite);
+ g_vm->_renderer->refreshImageData(*spot_sprite);
}
/*Get on-screen image as specified by script to temp buffer and register it with dirty rect of kind 2
@@ -400,7 +400,7 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
*height = cur_image_size_h;
if (right_button) {
- cga_BlitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
return 0;
}
@@ -415,7 +415,7 @@ void playHurtSound() {
}
void blinkWithSound(byte color) {
- cga_ColorSelect(color);
+ g_vm->_renderer->colorSelect(color);
playHurtSound();
selectPalette();
}
@@ -474,7 +474,7 @@ void animPortrait(byte layer, byte index, byte delay) {
}
getDirtyRectAndSetSprite(layer, &kind, &x, &y, &width, &height, &offs);
waitVBlank();
- cga_BlitAndWait(cur_image_pixels, width, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, width, width, height, CGA_SCREENBUFFER, offs);
waitVBlankTimer();
if (delay) {
if (ani[-1] == 37) { /*TODO: what is it?*/
diff --git a/engines/chamber/print.cpp b/engines/chamber/print.cpp
index da93f04ecde..168d1e73a1d 100644
--- a/engines/chamber/print.cpp
+++ b/engines/chamber/print.cpp
@@ -108,7 +108,7 @@ byte chars_color_wonc[] = {0x55, 0x57, 0x5D, 0x5F, 0x75, 0xF7, 0x7D, 0x7F, 0xD5,
void printStringPad(uint16 w, byte *target) {
while (w--)
- cga_PrintChar(0, target);
+ g_vm->_renderer->printChar(0, target);
}
byte *printWord(byte *str, byte *target) {
@@ -123,7 +123,7 @@ byte *printWord(byte *str, byte *target) {
str++;
return str;
}
- cga_PrintChar(c, target);
+ g_vm->_renderer->printChar(c, target);
skip_1st:
;
@@ -131,9 +131,9 @@ skip_1st:
str++;
if (f) {
if (f == 0x80)
- cga_PrintChar(0x25, target);
+ g_vm->_renderer->printChar(0x25, target);
else if (f != 0x40)
- cga_PrintChar(0x21, target);
+ g_vm->_renderer->printChar(0x21, target);
else
return str;
}
@@ -154,7 +154,7 @@ byte *printStringLine(byte *str, uint16 *left, byte *target) {
if (string_ended || (mw == 0))
break;
mw--;
- cga_PrintChar(0, target);
+ g_vm->_renderer->printChar(0, target);
}
*left = mw;
return str;
@@ -210,31 +210,31 @@ void cga_DrawTextBox(byte *msg, byte *target) {
y = draw_y;
w = (char_draw_max_width + 2) * 4 - 2;
- cga_DrawHLine(x + 2, y, w - 2, 0, target); /*box top*/
+ g_vm->_renderer->drawHLine(x + 2, y, w - 2, 0, target); /*box top*/
for (i = 0; i < 3; i++)
- cga_DrawHLine(x + 1, y + 1 + i, w, 1, target); /*top margin*/
- cga_DrawVLine(x, y + 2, 2, 0, target); /*left top corner 1*/
- cga_DrawVLine(x + 1, y + 1, 1, 0, target); /*left top corner 2*/
- cga_DrawVLine(x + w, y + 1, 1, 0, target); /*right top corner 1*/
- cga_DrawVLine(x + w + 1, y + 2, 2, 0, target); /*right top corner 2*/
+ g_vm->_renderer->drawHLine(x + 1, y + 1 + i, w, 1, target); /*top margin*/
+ g_vm->_renderer->drawVLine(x, y + 2, 2, 0, target); /*left top corner 1*/
+ g_vm->_renderer->drawVLine(x + 1, y + 1, 1, 0, target); /*left top corner 2*/
+ g_vm->_renderer->drawVLine(x + w, y + 1, 1, 0, target); /*right top corner 1*/
+ g_vm->_renderer->drawVLine(x + w + 1, y + 2, 2, 0, target); /*right top corner 2*/
char_draw_coords_y = draw_y + 4;
string_ended = 0;
do {
char_draw_coords_x = draw_x;
- cga_PrintChar(0x3B, target);
+ g_vm->_renderer->printChar(0x3B, target);
msg = printStringPadded(msg, target);
- cga_PrintChar(0x3C, target);
+ g_vm->_renderer->printChar(0x3C, target);
char_draw_coords_y += 6;
} while (!string_ended);
x = draw_x * 4;
y = char_draw_coords_y;
- cga_DrawHLine(x + 1, y, w, 1, target); /*bottom margin*/
- cga_DrawVLine(x + 1, y, 1, 0, target); /*bottom left corner 1*/
- cga_DrawHLine(x + 2, y + 1, w - 2, 0, target); /*box bottom*/
- cga_DrawVLine(x + 1, y, 1, 0, target); /*TODO: duplicated?*/
- cga_DrawVLine(x + w, y, 1, 0, target); /*bottom right corner*/
+ g_vm->_renderer->drawHLine(x + 1, y, w, 1, target); /*bottom margin*/
+ g_vm->_renderer->drawVLine(x + 1, y, 1, 0, target); /*bottom left corner 1*/
+ g_vm->_renderer->drawHLine(x + 2, y + 1, w - 2, 0, target); /*box bottom*/
+ g_vm->_renderer->drawVLine(x + 1, y, 1, 0, target); /*TODO: duplicated?*/
+ g_vm->_renderer->drawVLine(x + w, y, 1, 0, target); /*bottom right corner*/
}
void drawMessage(byte *msg, byte *target) {
@@ -260,7 +260,7 @@ void drawMessage(byte *msg, byte *target) {
cga_BackupImageReal(CalcXY_p(x, y), char_draw_max_width + 2, char_draw_max_height); /*backup orig. screen data*/
cga_DrawTextBox(msg, target); /*draw box with text*/
promptWait(); /*wait keypress*/
- cga_RestoreBackupImage(target); /*restore screen data*/
+ g_vm->_renderer->restoreBackupImage(target); /*restore screen data*/
}
#if 1
diff --git a/engines/chamber/renderer.h b/engines/chamber/renderer.h
new file mode 100644
index 00000000000..993130a5588
--- /dev/null
+++ b/engines/chamber/renderer.h
@@ -0,0 +1,172 @@
+/* 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 CHAMBER_RENDERER_H
+#define CHAMBER_RENDERER_H
+
+#include "chamber/common.h"
+
+namespace Chamber {
+
+class Renderer {
+public:
+ virtual ~Renderer() {}
+
+ virtual void switchToGraphicsMode() = 0;
+ virtual void colorSelect(byte csel) = 0;
+ virtual void blitToScreen(int16 x, int16 y, int16 w, int16 h) = 0;
+ virtual void blitToScreen(int16 ofs, int16 w, int16 h) = 0;
+
+ virtual uint16 calcXY(uint16 x, uint16 y) = 0;
+ virtual uint16 calcXY_p(uint16 x, uint16 y) = 0;
+
+ virtual void backBufferToRealFull() = 0;
+ virtual void realBufferToBackFull() = 0;
+ virtual void swapRealBackBuffer() = 0;
+ virtual void copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
+ virtual void swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+
+ virtual byte *backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) = 0;
+ virtual void restoreImage(byte *buffer, byte *target) = 0;
+ virtual void refreshImageData(byte *buffer) = 0;
+ virtual void restoreBackupImage(byte *target) = 0;
+
+ virtual void blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void blitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+
+ virtual void blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) = 0;
+ virtual void blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) = 0;
+
+ virtual void drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) = 0;
+ virtual void drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) = 0;
+ virtual uint16 drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) = 0;
+ virtual void printChar(byte c, byte *target) = 0;
+
+ virtual void animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+
+ virtual void hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
+ virtual void hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
+ virtual void hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
+ virtual void hideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
+ virtual void hideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
+
+ virtual void traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) = 0;
+
+ virtual void zoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs) = 0;
+ virtual void animZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) = 0;
+ virtual void zoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target) = 0;
+};
+
+class CGARenderer : public Renderer {
+public:
+ void switchToGraphicsMode() override;
+ void colorSelect(byte csel) override;
+ void blitToScreen(int16 x, int16 y, int16 w, int16 h) override;
+ void blitToScreen(int16 ofs, int16 w, int16 h) override;
+ uint16 calcXY(uint16 x, uint16 y) override;
+ uint16 calcXY_p(uint16 x, uint16 y) override;
+ void backBufferToRealFull() override;
+ void realBufferToBackFull() override;
+ void swapRealBackBuffer() override;
+ void copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ byte *backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) override;
+ void restoreImage(byte *buffer, byte *target) override;
+ void refreshImageData(byte *buffer) override;
+ void restoreBackupImage(byte *target) override;
+ void blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) override;
+ void blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) override;
+ void drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
+ void drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
+ uint16 drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) override;
+ void printChar(byte c, byte *target) override;
+ void animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) override;
+ void zoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs) override;
+ void animZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) override;
+ void zoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target) override;
+};
+
+class EGARenderer : public Renderer {
+public:
+ void switchToGraphicsMode() override;
+ void colorSelect(byte csel) override;
+ void blitToScreen(int16 x, int16 y, int16 w, int16 h) override;
+ void blitToScreen(int16 ofs, int16 w, int16 h) override;
+ uint16 calcXY(uint16 x, uint16 y) override;
+ uint16 calcXY_p(uint16 x, uint16 y) override;
+ void backBufferToRealFull() override;
+ void realBufferToBackFull() override;
+ void swapRealBackBuffer() override;
+ void copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ byte *backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) override;
+ void restoreImage(byte *buffer, byte *target) override;
+ void refreshImageData(byte *buffer) override;
+ void restoreBackupImage(byte *target) override;
+ void blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) override;
+ void blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) override;
+ void drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
+ void drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
+ uint16 drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) override;
+ void printChar(byte c, byte *target) override;
+ void animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void hideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
+ void traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target) override;
+ void zoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs) override;
+ void animZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs) override;
+ void zoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target) override;
+};
+
+} // End of namespace Chamber
+
+#endif // CHAMBER_RENDERER_H
diff --git a/engines/chamber/room.cpp b/engines/chamber/room.cpp
index 55ce1663a57..4d03dd0ef0b 100644
--- a/engines/chamber/room.cpp
+++ b/engines/chamber/room.cpp
@@ -145,12 +145,12 @@ static const byte cga_color_sels[] = {
};
void selectSpecificPalette(byte index) {
- cga_ColorSelect(cga_color_sels[index]);
+ g_vm->_renderer->colorSelect(cga_color_sels[index]);
}
void selectPalette(void) {
- cga_ColorSelect(cga_color_sels[script_byte_vars.palette_index]);
+ g_vm->_renderer->colorSelect(cga_color_sels[script_byte_vars.palette_index]);
}
/*
@@ -160,7 +160,7 @@ void blitSpritesToBackBuffer(void) {
int16 i;
for (i = 0; i < MAX_SPRITES; i++) {
byte *sprite = sprites_list[i];
- cga_RestoreImage(sprite, backbuffer);
+ g_vm->_renderer->restoreImage(sprite, backbuffer);
}
}
@@ -171,7 +171,7 @@ void refreshSpritesData(void) {
int16 i;
for (i = 0; i < MAX_SPRITES; i++) {
byte *sprite = sprites_list[i];
- cga_RefreshImageData(sprite);
+ g_vm->_renderer->refreshImageData(sprite);
}
}
@@ -301,7 +301,7 @@ void drawBackground(byte *target, byte vblank) {
byte *pixels = gauss_data + 0x3C8; /*TODO: better const*/
for (i = 0; i < 53; i++) {
/*draw a tile, alternating between two variants*/
- cga_Blit(pixels + (i & 1 ? 0 : kBgW * kBgH), kBgW, kBgW, kBgH, target, offs);
+ g_vm->_renderer->blit(pixels + (i & 1 ? 0 : kBgW * kBgH), kBgW, kBgW, kBgH, target, offs);
if (vblank)
waitVBlank();
if (g_vm->_videoMode == Common::RenderMode::kRenderCGA) {
@@ -314,7 +314,7 @@ void drawBackground(byte *target, byte vblank) {
offs = (182 / 2) * CGA_BYTES_PER_LINE; /*TODO: calcxy?*/
for (i = 0; i < 9; i++) {
- cga_Blit(pixels, kBgW, kBgW, 9, target, offs);
+ g_vm->_renderer->blit(pixels, kBgW, kBgW, 9, target, offs);
offs += kBgW;
}
}
@@ -558,13 +558,13 @@ void drawRoomDoor(void) {
uint16 offs = info->layer[i].offs;
if (!info->flipped)
- cga_BlitSprite(pixels, w * 2, w, h, backbuffer, offs);
+ g_vm->_renderer->blitSprite(pixels, w * 2, w, h, backbuffer, offs);
else
- cga_BlitSpriteFlip(pixels, w * 2, w, h, backbuffer, offs);
+ g_vm->_renderer->blitSpriteFlip(pixels, w * 2, w, h, backbuffer, offs);
}
waitVBlank();
waitVBlank();
- cga_CopyScreenBlock(backbuffer, info->width, info->height, frontbuffer, info->offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, info->width, info->height, frontbuffer, info->offs);
}
/*
@@ -691,7 +691,7 @@ Play animation at the selected spot or specified coordinates
*/
void animateSpot(const animdesc_t *info) {
byte *sprite = *spot_sprite;
- cga_RestoreImage(sprite, backbuffer);
+ g_vm->_renderer->restoreImage(sprite, backbuffer);
if (info->index & ANIMFLG_USESPOT) {
/*at selected spot*/
cursor_x = found_spot->sx * 4;
@@ -913,9 +913,9 @@ void drawRoomStaticObject(byte *aptr, byte *rx, byte *ry, byte *rw, byte *rh) {
/*TODO: check if this results in any glitches in Who Will Be Saved*/
if (aptr[1] & 0x80)
- cga_BlitSpriteFlip(sprite, pitch, w, h, backbuffer, CalcXY_p(x, y));
+ g_vm->_renderer->blitSpriteFlip(sprite, pitch, w, h, backbuffer, CalcXY_p(x, y));
else
- cga_BlitSprite(sprite, pitch, w, h, backbuffer, CalcXY_p(x, y));
+ g_vm->_renderer->blitSprite(sprite, pitch, w, h, backbuffer, CalcXY_p(x, y));
}
/*
@@ -972,20 +972,20 @@ void drawRoomStatics(void) {
char_xlat_table = chars_color_wonb;
/*print room name*/
- cga_PrintChar(0x3B, backbuffer);
+ g_vm->_renderer->printChar(0x3B, backbuffer);
drawObjectHint(); /* area name */
- cga_PrintChar(0x3C, backbuffer);
+ g_vm->_renderer->printChar(0x3C, backbuffer);
/*draw border around hint text*/
xx = (room_hint_bar_coords_x - 1) * 4;
y = room_hint_bar_coords_y;
ww = (room_hint_bar_width + 2) * 4;
- cga_DrawHLine(xx, y - 2, ww, 2, backbuffer);
- cga_DrawHLine(xx, y - 1, ww, 0, backbuffer);
- cga_DrawHLine(xx, y + 6, ww, 2, backbuffer);
- cga_DrawVLine(xx, y - 2, 9, 2, backbuffer);
- cga_DrawVLine(xx + ww - 1, y - 2, 9, 2, backbuffer);
+ g_vm->_renderer->drawHLine(xx, y - 2, ww, 2, backbuffer);
+ g_vm->_renderer->drawHLine(xx, y - 1, ww, 0, backbuffer);
+ g_vm->_renderer->drawHLine(xx, y + 6, ww, 2, backbuffer);
+ g_vm->_renderer->drawVLine(xx, y - 2, 9, 2, backbuffer);
+ g_vm->_renderer->drawVLine(xx + ww - 1, y - 2, 9, 2, backbuffer);
}
/*
@@ -1060,7 +1060,7 @@ void refreshZone(void) {
if (!skip_zone_transition && !right_button)
drawBackground(CGA_SCREENBUFFER, 1);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
in_de_profundis = 0;
IFGM_StopSample();
@@ -1091,10 +1091,10 @@ void drawObjectHint(void) {
printStringCentered(seekToString(motsi_data, object_hint), backbuffer);
#ifdef DEBUG_ZONE
- cga_PrintChar(0x20, backbuffer);
- cga_PrintChar(0x10 + script_byte_vars.zone_index / 100, backbuffer);
- cga_PrintChar(0x10 + (script_byte_vars.zone_index / 10) % 10, backbuffer);
- cga_PrintChar(0x10 + script_byte_vars.zone_index % 10, backbuffer);
+ g_vm->_renderer->printChar(0x20, backbuffer);
+ g_vm->_renderer->printChar(0x10 + script_byte_vars.zone_index / 100, backbuffer);
+ g_vm->_renderer->printChar(0x10 + (script_byte_vars.zone_index / 10) % 10, backbuffer);
+ g_vm->_renderer->printChar(0x10 + script_byte_vars.zone_index % 10, backbuffer);
#endif
}
@@ -1104,7 +1104,7 @@ Copy object hint from backbuffer to screen
void showObjectHint(byte *target) {
if (script_byte_vars.zone_index == 135)
return;
- cga_CopyScreenBlock(backbuffer, room_hint_bar_width + 2, 9, target, CalcXY_p(room_hint_bar_coords_x - 1, room_hint_bar_coords_y - 2));
+ g_vm->_renderer->copyScreenBlock(backbuffer, room_hint_bar_width + 2, 9, target, CalcXY_p(room_hint_bar_coords_x - 1, room_hint_bar_coords_y - 2));
}
/*
@@ -1122,7 +1122,7 @@ void drawCommandHint(void) {
Copy command hint from backbuffer to screen
*/
void showCommandHint(byte *target) {
- cga_CopyScreenBlock(backbuffer, cmd_hint_bar_width + 2, 9, target, CalcXY_p(cmd_hint_bar_coords_x - 1, cmd_hint_bar_coords_y - 2));
+ g_vm->_renderer->copyScreenBlock(backbuffer, cmd_hint_bar_width + 2, 9, target, CalcXY_p(cmd_hint_bar_coords_x - 1, cmd_hint_bar_coords_y - 2));
}
void loadLutinSprite(uint16 lutidx) {
@@ -1523,7 +1523,7 @@ void backupScreenOfSpecialRoom(void) {
case 22: /* DE PROFUNDIS */
case 23: /* DE PROFUNDIS */
case 24: /* THE WALL */
- cga_RealBufferToBackFull();
+ g_vm->_renderer->realBufferToBackFull();
break;
}
}
@@ -1673,7 +1673,7 @@ void theWallOpenRightDoor(byte x, byte y, byte width, byte height, byte limit) {
uint16 offs = CalcXY_p(x + width - 2, y);
while (--width) {
- cga_HideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
if (width == limit)
return;
}
@@ -1691,7 +1691,7 @@ void theWallOpenRightDoor(byte x, byte y, byte width, byte height, byte limit) {
offs += CGA_BYTES_PER_LINE;
}
- cga_blitToScreen(ooffs, 1, oh);
+ g_vm->_renderer->blitToScreen(ooffs, 1, oh);
}
/*
@@ -1702,7 +1702,7 @@ void theWallOpenLeftDoor(byte x, byte y, byte width, byte height, byte limit) {
uint16 offs = CalcXY_p(x + 1, y);
while (--width) {
- cga_HideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
if (width == limit)
return;
}
@@ -1719,7 +1719,7 @@ void theWallOpenLeftDoor(byte x, byte y, byte width, byte height, byte limit) {
if ((offs & g_vm->_line_offset) == 0)
offs += CGA_BYTES_PER_LINE;
}
- cga_blitToScreen(ooffs, 1, oh);
+ g_vm->_renderer->blitToScreen(ooffs, 1, oh);
}
/*
@@ -1770,11 +1770,11 @@ void theWallPhase1_DoorClose1(void) {
else
spr += cur_frame_width - 1;
cur_image_coords_x = 64 / 4;
- cga_AnimLiftToRight(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToRight(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
spr = loadMursmSprite(1);
cur_image_coords_x = 220 / 4;
- cga_AnimLiftToLeft(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
IFGM_StopSample();
@@ -1798,16 +1798,16 @@ void theWallPhase2_DoorClose2(void) {
spr += cur_frame_width - 1;
cur_image_coords_x = 64 / 4;
if (g_vm->_videoMode == Common::kRenderEGA)
- cga_AnimLiftToRight(10, spr - 40, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToRight(10, spr - 40, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
else
- cga_AnimLiftToRight(10, spr - 10, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToRight(10, spr - 10, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
spr = loadMursmSprite(1);
cur_image_coords_x = 220 / 4;
if (g_vm->_videoMode == Common::kRenderEGA)
- cga_AnimLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 40);
+ g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 40);
else
- cga_AnimLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 10);
+ g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 10);
IFGM_PlaySample(30);
@@ -1823,26 +1823,26 @@ void drawTheWallDoors(void) {
case 102:
if (g_vm->_videoMode == Common::kRenderEGA) {
/* EGA buffer is 80 px wide; CGA +10 bytes = 40 EGA pixels */
- cga_Blit(loadMursmSprite(0) + 40, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(0) + 40, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
if (g_vm->getLanguage() == Common::EN_USA) {
- cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
} else {
- cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
}
} else {
- cga_Blit(loadMursmSprite(0) + 10, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(0) + 10, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
if (g_vm->getLanguage() == Common::EN_USA) {
/*This fixes odd black patch on the right gate door*/
- cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
} else {
- cga_Blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
}
}
break;
case 95:
case 103:
- cga_Blit(loadMursmSprite(0), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
- cga_Blit(loadMursmSprite(1), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(144 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(0), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(144 / 4, 32));
break;
}
}
@@ -1889,7 +1889,7 @@ Return current and next free buffer ptr
*/
byte *backupSpotImage(spot_t *spot, byte **spotback, byte *buffer) {
*spotback = buffer;
- buffer = cga_BackupImage(backbuffer, CalcXY_p(spot->sx, spot->sy), spot->ex - spot->sx, spot->ey - spot->sy, buffer);
+ buffer = g_vm->_renderer->backupImage(backbuffer, CalcXY_p(spot->sx, spot->sy), spot->ex - spot->sx, spot->ey - spot->sy, buffer);
return buffer;
}
@@ -1930,9 +1930,9 @@ void drawSpots(byte *target) {
updateCursor();
waitVBlank();
undrawCursor(target);
- cga_CopyScreenBlock(backbuffer, zsprite_w, zsprite_h, target, zsprite_draw_ofs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, zsprite_w, zsprite_h, target, zsprite_draw_ofs);
drawCursor(target);
- cga_RestoreImage(sprites_list[zone_spr_index - 1], backbuffer);
+ g_vm->_renderer->restoreImage(sprites_list[zone_spr_index - 1], backbuffer);
return;
}
spridx = zone_spr_index; /*TODO: not neded?*/
@@ -2082,7 +2082,7 @@ void updateProtozorqs(void) {
}
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
blitSpritesToBackBuffer();
drawCursor(frontbuffer);
@@ -2120,7 +2120,7 @@ void updateProtozorqs(void) {
animateSpot(&anim34);
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
blitSpritesToBackBuffer();
drawCursor(frontbuffer);
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 470685243e1..f58b77556e4 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -672,9 +672,9 @@ uint16 SCR_5_DrawPortraitLiftRight(void) {
/*TODO: use local args instead of globals*/
if (g_vm->_videoMode == Common::kRenderEGA)
- cga_AnimLiftToRight(width, cur_image_pixels + width * 4 - 4, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
+ g_vm->_renderer->animLiftToRight(width, cur_image_pixels + width * 4 - 4, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
else
- cga_AnimLiftToRight(width, cur_image_pixels + width - 1, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
+ g_vm->_renderer->animLiftToRight(width, cur_image_pixels + width - 1, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
return 0;
}
@@ -690,7 +690,7 @@ uint16 SCR_6_DrawPortraitLiftLeft(void) {
return 0;
/*TODO: use local args instead of globals*/
- cga_AnimLiftToLeft(width, cur_image_pixels, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x + width - 1, y));
+ g_vm->_renderer->animLiftToLeft(width, cur_image_pixels, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x + width - 1, y));
return 0;
}
@@ -737,7 +737,7 @@ uint16 SCR_9_DrawPortrait(void) {
if (!drawPortrait(&script_ptr, &x, &y, &width, &height))
return 0;
- cga_BlitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
return 0;
}
@@ -760,7 +760,7 @@ void twistDraw(byte x, byte y, byte width, byte height, byte *source, byte *targ
ey = y + height - 1;
for (i = 0; i < width * 4; i++) {
- cga_TraceLine(sx, ex, sy, ey, source, target);
+ g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
@@ -777,7 +777,7 @@ void twistDraw(byte x, byte y, byte width, byte height, byte *source, byte *targ
ey = t;
for (i = 0; i < height; i++) {
- cga_TraceLine(sx, ex, sy, ey, source, target);
+ g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
@@ -800,9 +800,9 @@ uint16 SCR_B_DrawPortraitTwistEffect(void) {
offs = CalcXY_p(x, y);
- cga_SwapScreenRect(cur_image_pixels, width, height, backbuffer, offs);
+ g_vm->_renderer->swapScreenRect(cur_image_pixels, width, height, backbuffer, offs);
twistDraw(x, y, width, height, backbuffer, frontbuffer);
- cga_BlitAndWait(scratch_mem2, width, width, height, backbuffer, offs);
+ g_vm->_renderer->blitAndWait(scratch_mem2, width, width, height, backbuffer, offs);
return 0;
}
@@ -819,7 +819,7 @@ void arcDraw(byte x, byte y, byte width, byte height, byte *source, byte *target
ey = y + height - 1;
for (i = 0; i < height; i++) {
- cga_TraceLine(sx, ex, sy, ey, source, target);
+ g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
@@ -827,7 +827,7 @@ void arcDraw(byte x, byte y, byte width, byte height, byte *source, byte *target
}
for (i = 0; i < width * 4; i++) {
- cga_TraceLine(sx, ex, sy, ey, source, target);
+ g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
@@ -835,7 +835,7 @@ void arcDraw(byte x, byte y, byte width, byte height, byte *source, byte *target
}
for (i = 0; i < height + 1; i++) {
- cga_TraceLine(sx, ex, sy, ey, source, target);
+ g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
@@ -857,9 +857,9 @@ uint16 SCR_C_DrawPortraitArcEffect(void) {
offs = CalcXY_p(x, y);
- cga_SwapScreenRect(cur_image_pixels, width, height, backbuffer, offs);
+ g_vm->_renderer->swapScreenRect(cur_image_pixels, width, height, backbuffer, offs);
arcDraw(x, y, width, height, backbuffer, frontbuffer);
- cga_BlitAndWait(scratch_mem2, width, width, height, backbuffer, offs);
+ g_vm->_renderer->blitAndWait(scratch_mem2, width, width, height, backbuffer, offs);
return 0;
}
@@ -914,7 +914,7 @@ uint16 SCR_D_DrawPortraitDotEffect(void) {
target[CalcXY_p(x + offs % cur_image_size_w, y + offs / cur_image_size_w)] = cur_image_pixels[offs]; // TODO check this
if (count % 5 == 0)
- cga_blitToScreen(offs, g_vm->_screenPPB, 1);
+ g_vm->_renderer->blitToScreen(offs, g_vm->_screenPPB, 1);
offs += step;
if (offs > cur_image_end)
@@ -936,7 +936,7 @@ uint16 SCR_E_DrawPortraitZoomIn(void) {
if (!drawPortrait(&script_ptr, &x, &y, &width, &height))
return 0;
- cga_AnimZoomIn(cur_image_pixels, cur_image_size_w, cur_image_size_h, frontbuffer, cur_image_offs);
+ g_vm->_renderer->animZoomIn(cur_image_pixels, cur_image_size_w, cur_image_size_h, frontbuffer, cur_image_offs);
return 0;
}
@@ -954,13 +954,13 @@ uint16 drawPortraitZoomed(byte **params) {
if (g_vm->_videoMode == Common::kRenderEGA) {
/*EGA can't zoom: draw at original size; dirty rect already has correct dimensions from drawPortrait*/
- cga_ZoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, cur_image_size_w, cur_image_size_h, frontbuffer, cur_image_offs);
+ g_vm->_renderer->zoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, cur_image_size_w, cur_image_size_h, frontbuffer, cur_image_offs);
} else {
/*adjust the rect for new size*/
last_dirty_rect->width = zwidth + 2;
last_dirty_rect->height = zheight;
- cga_ZoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, zwidth, zheight, frontbuffer, cur_image_offs);
+ g_vm->_renderer->zoomImage(cur_image_pixels, cur_image_size_w, cur_image_size_h, zwidth, zheight, frontbuffer, cur_image_offs);
}
return 0;
}
@@ -996,7 +996,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1005,7 +1005,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
if (g_vm->_videoMode == Common::kRenderEGA) {
offs += 4;
while (--width)
- cga_HideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
offs -= 4;
uint16 ooffs = offs;
byte oh = height;
@@ -1021,7 +1021,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
offs++;
while (--width) {
- cga_HideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
}
offs--;
@@ -1037,7 +1037,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
if ((offs & g_vm->_line_offset) == 0)
offs += g_vm->_screenBPL;
}
- cga_blitToScreen(ooffs, 1, oh);
+ g_vm->_renderer->blitToScreen(ooffs, 1, oh);
return 0;
}
@@ -1058,7 +1058,7 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1067,7 +1067,7 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
if (g_vm->_videoMode == Common::kRenderEGA) {
offs = CalcXY_p(x + width - 2, y);
while (--width)
- cga_HideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
offs += 4;
uint16 ooffs = offs;
byte oh = height;
@@ -1082,7 +1082,7 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
offs = CalcXY_p(x + width - 2, y);
while (--width) {
- cga_HideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
}
offs++;
@@ -1098,7 +1098,7 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
if ((offs & g_vm->_line_offset) == 0)
offs += g_vm->_screenBPL;
}
- cga_blitToScreen(ooffs, 1, oh);
+ g_vm->_renderer->blitToScreen(ooffs, 1, oh);
return 0;
}
@@ -1119,20 +1119,20 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
if (g_vm->_videoMode == Common::kRenderEGA) {
/* offs = CalcXY_p(x, y) from dirty rect â restore full portrait area */
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
offs = CalcXY_p(x, y + 1);
while (--height) {
- cga_HideScreenBlockLiftToUp(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToUp(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
}
/*hide topmost line*/
@@ -1141,7 +1141,7 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
if ((offs & g_vm->_line_offset) != 0)
offs -= g_vm->_screenBPL;
memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
- cga_blitToScreen(offs, width, 1);
+ g_vm->_renderer->blitToScreen(offs, width, 1);
}
return 0;
}
@@ -1163,7 +1163,7 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1172,14 +1172,14 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
* The CGA path recalculates offs to y+height-2 (bottom of portrait),
* causing ega_CopyScreenBlock to start from the wrong position and
* leave most of the portrait unrestoâred. */
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
offs = CalcXY_p(x, y + height - 2);
while (--height) {
- cga_HideScreenBlockLiftToDown(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToDown(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
}
/*hide bottommost line*/
@@ -1188,7 +1188,7 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
if ((offs & g_vm->_line_offset) == 0)
offs += g_vm->_screenBPL;
memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
- cga_blitToScreen(offs, width, 1);
+ g_vm->_renderer->blitToScreen(offs, width, 1);
}
return 0;
}
@@ -1209,7 +1209,7 @@ uint16 SCR_1E_HidePortraitTwist(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1233,7 +1233,7 @@ uint16 SCR_1F_HidePortraitArc(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1257,7 +1257,7 @@ uint16 SCR_20_HidePortraitDots(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1383,7 +1383,7 @@ void jaggedZoom(byte *source, byte *target) {
ex = points[0].x;
ey = points[0].y;
}
- cga_TraceLine(sx / 2, ex / 2, sy / 2, ey / 2, source, target);
+ g_vm->_renderer->traceLine(sx / 2, ex / 2, sy / 2, ey / 2, source, target);
}
/* One screen update per cycle (not per line) keeps the animation fluid */
if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
@@ -1468,7 +1468,7 @@ void drawStars(star_t *stars, int16 iter, byte *target) {
stars->mask = 0; /* unused in EGA path */
target[stars->ofs] = pixel;
} else {
- stars->ofs = cga_CalcXY(x, y);
+ stars->ofs = g_vm->_renderer->calcXY(x, y);
pixel = (stars->z < 0xE00) ? 0xC0 : 0x40;
pixel >>= (x % 4) * 2;
mask = 0xC0;
@@ -1503,8 +1503,8 @@ uint16 SCR_26_GameOver(void) {
script_byte_vars.game_paused = 1;
memset(backbuffer, 0, sizeof(backbuffer) - 2); /*TODO: original bug?*/
jaggedZoom(backbuffer, frontbuffer);
- cga_BackBufferToRealFull();
- cga_ColorSelect(0x30);
+ g_vm->_renderer->backBufferToRealFull();
+ g_vm->_renderer->colorSelect(0x30);
animStarfield(initStarfield(), frontbuffer);
playAnim(44, 156 / 4, 95);
script_byte_vars.zone_index = 135;
@@ -1515,7 +1515,7 @@ uint16 SCR_26_GameOver(void) {
jaggedZoom(backbuffer, frontbuffer);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
restartGame();
return 0;
}
@@ -1661,7 +1661,7 @@ Display a static sprite in the room (to screen)
uint16 SCR_11_DrawRoomObject(void) {
byte x, y, w, h;
SCR_DrawRoomObjectBack(&x, &y, &w, &h);
- cga_CopyScreenBlock(backbuffer, w, h, frontbuffer, CalcXY_p(x, y));
+ g_vm->_renderer->copyScreenBlock(backbuffer, w, h, frontbuffer, CalcXY_p(x, y));
return 0;
}
@@ -1846,8 +1846,8 @@ uint16 SCR_2A_PopDialogRect(void) {
index = *script_ptr++;
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs); /*TODO: implicit target*/
- cga_CopyScreenBlock(backbuffer, 2, 21, CGA_SCREENBUFFER, offs = (x << 8) | y); /*TODO: implicit target*/
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs); /*TODO: implicit target*/
+ g_vm->_renderer->copyScreenBlock(backbuffer, 2, 21, CGA_SCREENBUFFER, offs = (x << 8) | y); /*TODO: implicit target*/
cur_dlg_index = 0;
@@ -1878,11 +1878,11 @@ uint16 SCR_22_HidePortraitShatter(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
- cga_HideShatterFall(CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideShatterFall(CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1903,11 +1903,11 @@ uint16 SCR_23_HidePortrait(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1958,7 +1958,7 @@ Draw updated Hands in Who Will Be Saved
uint16 SCR_41_LiftHand(void) {
script_ptr++;
redrawRoomStatics(92, script_byte_vars.hands);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
playSound(31);
return 0;
}
@@ -2007,13 +2007,13 @@ uint16 SCR_30_Fight(void) {
player_image[1] = x;
player_image[2] = y;
if (drawPortrait(&image, &x, &y, &width, &height))
- cga_AnimLiftToLeft(width, cur_image_pixels, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x + width - 1, y));
+ g_vm->_renderer->animLiftToLeft(width, cur_image_pixels, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x + width - 1, y));
blinkToWhite();
if (pers->name != 44 && pers->name != 56 && pers->name != 51) { /*VORT, MONKEY, TURKEY*/
getDirtyRectAndFree(1, &kind, &x, &y, &width, &height, &offs);
- cga_CopyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
}
/*check fight outcome*/
@@ -2261,8 +2261,8 @@ void FightWin(void) {
script_byte_vars.bvar_67 = 0;
if (script_byte_vars.bvar_43 != 18 && *spot_sprite != 0) {
- cga_RestoreImage(*spot_sprite, frontbuffer);
- cga_RestoreImage(*spot_sprite, backbuffer);
+ g_vm->_renderer->restoreImage(*spot_sprite, frontbuffer);
+ g_vm->_renderer->restoreImage(*spot_sprite, backbuffer);
if (script_byte_vars.extreme_violence == 0
&& script_byte_vars.bvar_60 == 0
@@ -2293,7 +2293,7 @@ void DrawDeathAnim(void) {
/*remove existing cadaver if any*/
if (selectPerson(PersonOffset(kPersCadaver))) {
found_spot->flags &= ~SPOTFLG_80;
- cga_RestoreImage(*spot_sprite, backbuffer);
+ g_vm->_renderer->restoreImage(*spot_sprite, backbuffer);
}
for (i = 0; i < 23; i++) {
@@ -2334,7 +2334,7 @@ uint16 SCR_60_ReviveCadaver(void) {
pers->area = script_byte_vars.zone_area;
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
return 0;
}
@@ -2395,7 +2395,7 @@ uint16 SCR_15_SelectSpot(void) {
uint16 SCR_44_BackBufferToScreen(void) {
script_ptr++;
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
return 0;
}
@@ -2410,27 +2410,27 @@ uint16 SCR_45_DeProfundisRoomEntry(void) {
/*draw Platform*/
sprofs = getPuzzlSprite(3, 140 / 4, 174, &w, &h, &ofs);
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
/*draw Granite Monster*/
sprofs = getPuzzlSprite(119, 128 / 4, 94, &w, &h, &ofs);
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
promptWait();
for (; h; h--) {
waitVBlank();
waitVBlank();
- cga_BlitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
ofs ^= g_vm->_line_offset;
if ((ofs & g_vm->_line_offset) == 0)
ofs += g_vm->_screenBPL;
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
}
- cga_BlitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
return 0;
}
@@ -2454,12 +2454,12 @@ uint16 SCR_46_DeProfundisLowerHook(void) {
for (; y; y--) {
waitVBlank();
- cga_BlitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
h++;
sprofs -= 20 / 4 * 2;
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
}
return 0;
@@ -2490,7 +2490,7 @@ uint16 SCR_47_DeProfundisRiseMonster(void) {
h++;
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
}
return 0;
@@ -2513,14 +2513,14 @@ uint16 SCR_48_DeProfundisLowerMonster(void) {
for (; y; y--) {
waitVBlank();
- cga_BlitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
ofs ^= g_vm->_line_offset;
if ((ofs & g_vm->_line_offset) == 0)
ofs += g_vm->_screenBPL;
h--;
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
}
return 0;
@@ -2544,15 +2544,15 @@ uint16 SCR_49_DeProfundisRiseHook(void) {
for (; y; y--) {
waitVBlank();
- cga_BlitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
h--;
sprofs += 20 / 4 * 2;
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
}
- cga_BlitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
return 0;
}
@@ -2585,7 +2585,7 @@ uint16 SCR_65_DeProfundisMovePlatform(void) {
for (; y; y--) {
waitVBlank();
- cga_BlitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
ofs ^= g_vm->_line_offset;
if ((ofs & g_vm->_line_offset) == 0)
@@ -2593,11 +2593,11 @@ uint16 SCR_65_DeProfundisMovePlatform(void) {
h--;
- cga_BlitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
}
if (state)
- cga_BlitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
return 0;
}
@@ -2614,7 +2614,7 @@ uint16 SCR_66_DeProfundisRideToExit(void) {
/*draw Granite Monster*/
sprofs = getPuzzlSprite(119, 128 / 4, 139, &w, &h, &ofs);
- cga_BlitScratchBackSprite(sprofs, w, 20, backbuffer, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, 20, backbuffer, ofs);
dot_effect_delay = 1;
dot_effect_step = 17;
@@ -2811,7 +2811,7 @@ uint16 SCR_56_MorphRoom98(void) {
redrawRoomStatics(98, 0);
- ofs = cga_CalcXY(0, 136);
+ ofs = g_vm->_renderer->calcXY(0, 136);
for (h = 60; h; h--) {
memcpy(frontbuffer + ofs, backbuffer + ofs, g_vm->_screenBPL);
waitVBlank();
@@ -2887,8 +2887,8 @@ static void AnimSaucer(void) {
byte scroll_done = 0;
memset(backbuffer, 0, sizeof(backbuffer) - 2); /*TODO: original bug?*/
- cga_BackBufferToRealFull();
- cga_ColorSelect(0x30);
+ g_vm->_renderer->backBufferToRealFull();
+ g_vm->_renderer->colorSelect(0x30);
right_button = 0;
if (!drawPortrait(&pimage1, &x, &y, &width, &height))
@@ -2919,9 +2919,9 @@ static void AnimSaucer(void) {
height_prev -= (yy - 1);
/*scale the saucer*/
- cga_ZoomInplaceXY(cur_image_pixels, width, height, ww, hh, xx, yy, backbuffer);
+ g_vm->_renderer->zoomInplaceXY(cur_image_pixels, width, height, ww, hh, xx, yy, backbuffer);
- baseofs = cga_CalcXY(0, yy);
+ baseofs = g_vm->_renderer->calcXY(0, yy);
if (!scroll_done) {
/*scroll the saucer*/
@@ -2949,7 +2949,7 @@ static void AnimSaucer(void) {
ofs -= g_vm->_screenBPL;
}
- ofs2 = cga_CalcXY(0, 200 - 1);
+ ofs2 = g_vm->_renderer->calcXY(0, 200 - 1);
for (i = 0; i < 108; i++) {
LiftLines(i + 1, backbuffer, ofs, frontbuffer, ofs2);
@@ -3008,11 +3008,11 @@ void theEnd(void) {
while (!loadFond())
askDisk2();
jaggedZoom(backbuffer, frontbuffer);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
} else {
while (!loadSplash("PRES.BIN"))
askDisk2();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
}
}
@@ -3105,7 +3105,7 @@ uint16 SCR_63_LiftSpot6(void) {
zone_spots[6].ey -= 5;
backupSpotsImages();
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
return 0;
}
@@ -3342,7 +3342,7 @@ uint16 CMD_2_PsiPowers(void) {
drawHintsAndCursor(CGA_SCREENBUFFER);
} while (buttons == 0);
undrawCursor(CGA_SCREENBUFFER);
- cga_RestoreBackupImage(CGA_SCREENBUFFER);
+ g_vm->_renderer->restoreBackupImage(CGA_SCREENBUFFER);
return ScriptRerun;
}
@@ -3375,7 +3375,7 @@ uint16 CMD_4_EnergyLevel(void) {
anim = 41 + (script_byte_vars.psy_energy / 16);
if (drawPortrait(&image, &x, &y, &width, &height)) {
- cga_BlitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
}
do {
@@ -3450,7 +3450,7 @@ uint16 CMD_8_Timer(void) {
byte *image = timer_image;
if (drawPortrait(&image, &x, &y, &width, &height)) {
- cga_BlitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
}
do {
@@ -3461,10 +3461,10 @@ uint16 CMD_8_Timer(void) {
char_draw_coords_y = 120;
waitVBlank();
- cga_PrintChar(timer / (60 * 60) + 16, CGA_SCREENBUFFER);
- cga_PrintChar((minutes & 1) ? 26 : 0, CGA_SCREENBUFFER); /*colon*/
- cga_PrintChar(minutes / (60 * 10) + 16, CGA_SCREENBUFFER);
- cga_PrintChar(minutes / 60 + 16, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar(timer / (60 * 60) + 16, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar((minutes & 1) ? 26 : 0, CGA_SCREENBUFFER); /*colon*/
+ g_vm->_renderer->printChar(minutes / (60 * 10) + 16, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar(minutes / 60 + 16, CGA_SCREENBUFFER);
pollInputButtonsOnly();
} while (buttons == 0);
@@ -3498,7 +3498,7 @@ uint16 CMD_A_PsiSolarEyes(void) {
if (zone_palette == 14) {
redrawRoomStatics(script_byte_vars.zone_room, zone_palette);
zone_palette = 0;
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
}
the_command = Swap16(script_word_vars.wvar_AA);
@@ -3564,7 +3564,7 @@ uint16 CMD_B_PsiStickyFingers(void) {
selectCursor(CURSOR_FLY);
menuLoop(0, 0);
playSound(224);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
restoreScreenOfSpecialRoom();
if (script_byte_vars.cur_spot_idx == 0 || GetZoneObjCommand(0 * 2) == 0)
@@ -3660,10 +3660,10 @@ uint16 CMD_E_PsiZoneScan(void) {
for (y = room_bounds_rect.sy; h; y++, h--) {
spot_t *spot;
for (x = 0; x < w; x++) frontbuffer[offs + x] = ~frontbuffer[offs + x];
- cga_blitToScreen(offs, w, 1);
+ g_vm->_renderer->blitToScreen(offs, w, 1);
waitVBlank();
for (x = 0; x < w; x++) frontbuffer[offs + x] = ~frontbuffer[offs + x];
- cga_blitToScreen(offs, w, 1);
+ g_vm->_renderer->blitToScreen(offs, w, 1);
for (spot = zone_spots; spot != zone_spots_end; spot++) {
if ((spot->flags & ~(SPOTFLG_40 | 7)) == (SPOTFLG_20 | SPOTFLG_8) && spot->sy == y) {
@@ -3908,18 +3908,18 @@ uint16 CMD_13_ActivateFountain(void) {
for (i = 0; i < 10; i++) {
drawRoomStaticObject(water1, &x, &y, &w, &h);
waitVBlank();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
for (j = 0; j < 0x1FFF; j++) ; /*TODO: weak delay*/
drawRoomStaticObject(water2, &x, &y, &w, &h);
waitVBlank();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
for (j = 0; j < 0x1FFF; j++) ; /*TODO: weak delay*/
}
drawRoomStaticObject(headl, &x, &y, &w, &h);
drawRoomStaticObject(headr, &x, &y, &w, &h);
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
return 0;
}
@@ -3936,7 +3936,7 @@ uint16 CMD_14_VortAppear(void) {
next_vorts_cmd = 0xA015;
blitSpritesToBackBuffer();
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
next_vorts_ticks = Swap16(script_word_vars.timer_ticks2) + 5;
return 0;
}
@@ -4072,7 +4072,7 @@ uint16 CMD_19_AspirantAppear(void) {
animateSpot(&anim23);
blitSpritesToBackBuffer();
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
if (script_byte_vars.aspirant_flags == 5) {
the_command = 0xC029;
script_byte_vars.aspirant_flags = 0;
@@ -4147,7 +4147,7 @@ uint16 CMD_1E_TurkeyAppear(void) {
next_turkey_cmd = 0xA01F;
blitSpritesToBackBuffer();
drawPersons();
- cga_BackBufferToRealFull();
+ g_vm->_renderer->backBufferToRealFull();
next_turkey_ticks = Swap16(script_word_vars.timer_ticks2) + 5;
return 0;
}
diff --git a/engines/chamber/timer.cpp b/engines/chamber/timer.cpp
index 2a2bb17bee1..d7f7896c33a 100644
--- a/engines/chamber/timer.cpp
+++ b/engines/chamber/timer.cpp
@@ -42,7 +42,7 @@ void animateGauss(byte *target) {
phase = (phase + 1) % 4;
script_byte_vars.gauss_phase = phase;
sprite = gauss_data + 8 + phase * (8 * 30);
- cga_Blit(sprite, 8, 8, 30, target, 80); /*draw to 0:4*/
+ g_vm->_renderer->blit(sprite, 8, 8, 30, target, 80); /*draw to 0:4*/
}
void timerCallback(void *refCon) {
Commit: 897d9a7b3f58c2f851c9fa031c13a052e4e79a15
https://github.com/scummvm/scummvm/commit/897d9a7b3f58c2f851c9fa031c13a052e4e79a15
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Remove renderer mode checks by moving format dispatch into EGARenderer
Changed paths:
engines/chamber/anim.cpp
engines/chamber/chamber.cpp
engines/chamber/cursor.cpp
engines/chamber/ega.cpp
engines/chamber/kult.cpp
engines/chamber/portrait.cpp
engines/chamber/resdata.cpp
engines/chamber/room.cpp
engines/chamber/script.cpp
engines/chamber/timer.cpp
diff --git a/engines/chamber/anim.cpp b/engines/chamber/anim.cpp
index 7ff01a3dad6..2384cad0246 100644
--- a/engines/chamber/anim.cpp
+++ b/engines/chamber/anim.cpp
@@ -74,8 +74,6 @@ void animLoadSprite(byte **panim) {
void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx, int8 dy) {
if (anim_flags == 7)
return;
- // In EGA mode, lutin_mem CLUT8 buffer has 4 bytes per column (1 byte/pixel à 4 pixels).
- // In CGA mode, mask+pixel pairs give 2 bytes per column.
uint16 bytes_per_col = (g_vm->_videoMode == Common::kRenderEGA) ? 4 : 2;
if (anim_flags & 4) {
if (anim_cycle == 0)
@@ -142,13 +140,7 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
byte ex, ey, updx, updy, updw, updh;
uint16 ofs = CalcXY_p(x, y);
g_vm->_renderer->backupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
- if (g_vm->_videoMode == Common::kRenderEGA) {
- // In EGA mode, loadLutinSprite builds a CLUT8 flat buffer in lutin_mem+2.
- // pitch here is sprw*4 (set in playAnimCore for EGA).
- ega_BlitSprite(pixels, pitch, (uint16)sprw * 4, sprh, backbuffer, ofs);
- } else {
- g_vm->_renderer->blitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
- }
+ g_vm->_renderer->blitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
ex = x + sprw;
ey = y + sprh;
if (last_anim_height != 0) {
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index d1138970828..06be502db71 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -55,8 +55,6 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
_prioritycommand_2 = false;
_pxiData = NULL;
- // Read render mode from ScummVM settings (--render-mode command line flag).
- // Supported: cga (default), herc, ega.
Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
if (renderMode == Common::kRenderEGA || renderMode == Common::kRenderHercG)
_videoMode = renderMode;
diff --git a/engines/chamber/cursor.cpp b/engines/chamber/cursor.cpp
index 022097dbf00..603da0980aa 100644
--- a/engines/chamber/cursor.cpp
+++ b/engines/chamber/cursor.cpp
@@ -71,12 +71,11 @@ void selectCursor(uint16 num) {
byte *dst = cursorImage;
if (g_vm->_videoMode == Common::kRenderEGA) {
- // EGA SOURI.EGA: 64 bytes/cursor, 4 bytes per row.
- // Each row = two little-endian 16-bit planes:
- // planeA (bytes 0,1): outline/black mask (bit set = black pixel)
- // planeB (bytes 2,3): fill/white mask (bit set = white pixel)
- // MSB of each word = leftmost pixel (pixel 0).
- // A=0,B=0 â transparent; A=1,B=0 â black (EGA 0); A=0/1,B=1 â white (EGA 15).
+ /*EGA SOURI.EGA: 64 bytes/cursor, 4 bytes per row.
+ Each row = two little-endian 16-bit planes:
+ planeA (bytes 0,1): black mask (bit set = black pixel)
+ planeB (bytes 2,3): white mask (bit set = white pixel)
+ A=0,B=0 -> transparent; A=1,B=0 -> black; B=1 -> white.*/
cursor_shape = souri_data + num * (CURSOR_WIDTH * CURSOR_HEIGHT / 4);
byte *src = cursor_shape;
for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
@@ -87,11 +86,11 @@ void selectCursor(uint16 num) {
byte bitA = (planeA >> (CURSOR_WIDTH - 1 - x)) & 1;
byte bitB = (planeB >> (CURSOR_WIDTH - 1 - x)) & 1;
if (!bitA && !bitB)
- *dst++ = 255; // transparent
+ *dst++ = 255; /*transparent*/
else if (bitB)
- *dst++ = 15; // white
+ *dst++ = 15; /*white*/
else
- *dst++ = 0; // black
+ *dst++ = 0; /*black*/
}
}
} else {
diff --git a/engines/chamber/ega.cpp b/engines/chamber/ega.cpp
index f7cc05dca11..b63c34e9303 100644
--- a/engines/chamber/ega.cpp
+++ b/engines/chamber/ega.cpp
@@ -328,7 +328,6 @@ void EGARenderer::fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs)
byte egaColor = cga_to_ega_color[(pixel >> 6) & 0x03];
uint16 oofs = ofs;
uint16 w_px = w * 4;
- debug(1, "EGARenderer::fill: color=%d w=%d h=%d ofs=%d", egaColor, w_px, h, ofs);
for (uint16 y = 0; y < h; y++) {
memset(screen + ofs, egaColor, w_px);
ofs += EGA_BYTES_PER_LINE;
@@ -346,6 +345,20 @@ void EGARenderer::fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint
void EGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 oofs = ofs;
+ if ((pw < 0 ? -pw : pw) == (int16)(w * 4)) {
+ uint16 ega_w = w * 4;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < ega_w; x++) {
+ if (pixels[x] != 0)
+ screen[ofs + x] = pixels[x];
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, ega_w, h);
+ return;
+ }
for (uint16 row = 0; row < h; row++) {
for (uint16 bx = 0; bx < w; bx++) {
byte mb = pixels[bx * 2];
@@ -366,6 +379,20 @@ void EGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *s
void EGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 oofs = ofs;
+ if ((pw < 0 ? -pw : pw) == (int16)(w * 4)) {
+ uint16 ega_w = w * 4;
+ for (uint16 y = 0; y < h; y++) {
+ for (uint16 x = 0; x < ega_w; x++) {
+ if (pixels[ega_w - 1 - x] != 0)
+ screen[ofs + x] = pixels[ega_w - 1 - x];
+ }
+ pixels += pw;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+ if (screen == ega_screen)
+ ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, ega_w, h);
+ return;
+ }
for (uint16 row = 0; row < h; row++) {
for (uint16 bx = 0; bx < w; bx++) {
byte mb = pixels[bx * 2];
@@ -549,6 +576,8 @@ void EGARenderer::traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *so
if (e2 > -abh) { err -= abh; x0 += ddx; }
if (e2 < abw) { err += abw; y0 += ddy; }
}
+ if (target == ega_screen)
+ ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
}
void EGARenderer::zoomImage(byte *pixels, byte w, byte h, byte /*nw*/, byte /*nh*/, byte *target, uint16 ofs) {
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index 0d7097520cf..f13856d3d87 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -236,16 +236,15 @@ Common::Error ChamberEngine::init() {
// Initialize graphics using following:
bool isCustomHerc = false;
if (_videoMode == Common::RenderMode::kRenderEGA) {
- // EGA: 320x200 CLUT8 linear framebuffer, 1 byte per pixel, no interlacing
- _screenW = 320;
- _screenH = 200;
+ _screenW = 320;
+ _screenH = 200;
_screenBits = 8;
- _screenPPB = 1;
- _screenBPL = _screenW;
- _line_offset = 0;
+ _screenPPB = 1;
+ _screenBPL = _screenW;
+ _line_offset = 0;
_line_offset2 = 0;
_fontHeight = 6;
- _fontWidth = 4;
+ _fontWidth = 4;
initGraphics(_screenW, _screenH);
} else {
if (_videoMode == Common::RenderMode::kRenderHercG) {
@@ -284,7 +283,7 @@ Common::Error ChamberEngine::init() {
if (g_vm->_videoMode == Common::RenderMode::kRenderEGA) {
/* EGA title screen â load planar EGA splash (same format as FOND.EGA) */
splash = ega_loadFond("PRESEGA.EGA");
- g_vm->_renderer->colorSelect(0x30); // sets EGA palette
+ g_vm->_renderer->colorSelect(0x30);
if (splash)
g_vm->_renderer->backBufferToRealFull();
} else {
@@ -373,7 +372,7 @@ Common::Error ChamberEngine::init() {
if (!loadStaticData())
exitGame();
-/* Load text resources */
+ /* Load text resources */
if (!loadVepciData() || !loadDesciData() || !loadDialiData())
exitGame();
@@ -418,8 +417,6 @@ Common::Error ChamberEngine::init() {
}
}
- exitGame();
-
return Common::kNoError;
}
diff --git a/engines/chamber/portrait.cpp b/engines/chamber/portrait.cpp
index 6d864dc50f7..ed1111c82a1 100644
--- a/engines/chamber/portrait.cpp
+++ b/engines/chamber/portrait.cpp
@@ -20,8 +20,6 @@
*/
#include "common/system.h"
-#include "common/rendermode.h"
-#include "graphics/surface.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/portrait.h"
@@ -159,53 +157,37 @@ byte *loadPortrait(byte **pinfo, byte *end) {
return sprit_load_buffer + 2;
}
-/* Expand a CGA 2bpp packed byte into 4 CLUT8 EGA pixels */
static void ega_expandCgaByte(byte cgaByte, byte *dst) {
for (int p = 3; p >= 0; p--)
*dst++ = cga_to_ega_color[(cgaByte >> (p * 2)) & 0x03];
}
-/*
-Build portrait frame in CLUT8 format for EGA mode.
-Pixel width = pframe->width * 4, stored row by row.
-Header bytes: [height][width_cga] to stay compatible with existing callers.
-*/
static void ega_makePortraitFrame(byte index, byte *target) {
persframe_t *pf = &pers_frames[index];
- uint16 pw = pf->width * 4; // pixel width
+ uint16 pw = pf->width * 4;
byte fillCol = cga_to_ega_color[(pf->fill >> 6) & 0x03];
- debug(1, "ega_makePortraitFrame: frame=%d h=%d w=%d fillEGA=%d", index, pf->height, pf->width, fillCol);
*target++ = pf->height;
- *target++ = pf->width; // CGA-unit width for compatibility
+ *target++ = pf->width;
cur_frame_width = pf->width;
- // Top border row
for (uint16 x = 0; x < pf->width; x++)
ega_expandCgaByte(pf->topbot, target + x * 4);
target += pw;
- // Middle rows
for (uint16 i = 0; i < pf->height - 2; i++) {
ega_expandCgaByte(pf->left, target);
- // Fill middle with solid color from fill byte
- byte fillCol2 = cga_to_ega_color[(pf->fill >> 6) & 0x03];
- memset(target + 4, fillCol2, (pf->width - 2) * 4);
+ memset(target + 4, fillCol, (pf->width - 2) * 4);
ega_expandCgaByte(pf->right, target + (pf->width - 1) * 4);
target += pw;
}
- // Bottom border row
for (uint16 x = 0; x < pf->width; x++)
ega_expandCgaByte(pf->topbot, target + x * 4);
}
-/*
-Composite CLUT8 pers sprites onto EGA portrait frame.
-Sprites from ega_perso_res are already decoded CLUT8 Graphics::Surface.
-*/
static byte *ega_loadPortrait(byte **pinfo, byte *end) {
- uint16 frame_pw = cur_frame_width * 4; // pixel width of frame
+ uint16 frame_pw = cur_frame_width * 4;
while (*pinfo != end) {
byte index;
@@ -221,18 +203,17 @@ static byte *ega_loadPortrait(byte **pinfo, byte *end) {
uint16 sh = surf->h;
int16 spitch = surf->pitch;
- // Decode CGA byte offset to row/col in the frame
uint16 cga_ofs = flags & 0x3FFF;
uint16 row = cga_ofs / cur_frame_width;
uint16 col_cga = cga_ofs % cur_frame_width;
byte *dst = sprit_load_buffer + 2 + 2 + row * frame_pw + col_cga * 4;
- if (flags & 0x8000) { // vertical flip
+ if (flags & 0x8000) { /*vertical flip*/
src += spitch * (sh - 1);
spitch = -spitch;
}
- if (flags & 0x4000) { // horizontal flip
+ if (flags & 0x4000) { /*horizontal flip*/
for (uint16 y = 0; y < sh; y++) {
for (uint16 x = 0; x < sw; x++) {
byte p = src[sw - 1 - x];
@@ -341,7 +322,6 @@ void drawBoxAroundSpot(void) {
/*decode ofs back to x:y*/
if (g_vm->_videoMode == Common::kRenderEGA) {
- /* EGA: linear layout, offset = y * 320 + x */
y = ofs / EGA_BYTES_PER_LINE;
x = ofs % EGA_BYTES_PER_LINE;
w *= 4; /* w was stored in CGA byte units */
@@ -371,9 +351,8 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
index = *((*desc)++);
if (index == 0xFF) {
- if (script_byte_vars.dirty_rect_kind != 0) {
+ if (script_byte_vars.dirty_rect_kind != 0)
return 0;
- }
drawBoxAroundSpot();
if (!selectCurrentAnim(&xx, &yy, &index))
return 0;
@@ -384,8 +363,6 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
cur_image_coords_x = xx;
cur_image_coords_y = yy;
cur_image_idx = index;
- debug(1, "drawPortrait: index=%d x=%d y=%d (pixel x=%d y=%d)", index, xx, yy, xx * 4, yy);
-
image = loadPortraitWithFrame(index - 1);
cur_image_size_h = *image++;
cur_image_size_w = *image++;
diff --git a/engines/chamber/resdata.cpp b/engines/chamber/resdata.cpp
index 5836ff94100..e9ddf45a3f8 100644
--- a/engines/chamber/resdata.cpp
+++ b/engines/chamber/resdata.cpp
@@ -132,8 +132,7 @@ ResEntry_tp res_static[] = {
{"$", NULL}
};
-// EGA Kult2.pxi uses SOURI.EGA / GAUSS.EGA and stores the script template
-// data under "kultega.bin" instead of TEMPL.BIN
+/*EGA uses SOURI.EGA / GAUSS.EGA; script template is "kultega.bin" not TEMPL.BIN*/
ResEntry_tp res_static_ega[] = {
{"ARPLA.BIN", &arpla_data},
{"ALEAT.BIN", &aleat_data},
diff --git a/engines/chamber/room.cpp b/engines/chamber/room.cpp
index 4d03dd0ef0b..6e9cc7970ab 100644
--- a/engines/chamber/room.cpp
+++ b/engines/chamber/room.cpp
@@ -462,8 +462,7 @@ void initRoomDoorInfo(byte index) {
h = surf->h;
ox = x & 0x7F;
- // EGA: ega_BlitSpriteFlip writes left-to-right, so use original ox for offset.
- // (CGA convention shifts x to rightmost byte; EGA does not need that.)
+ /*EGA blitter uses left-edge offset; no rightmost-byte shift needed*/
y = (y * 2) & 0xFF;
@@ -534,33 +533,18 @@ Draw sliding door
void drawRoomDoor(void) {
int16 i;
doorinfo_t *info = (doorinfo_t *)scratch_mem2;
- if (g_vm->_videoMode == Common::kRenderEGA) {
- for (i = 0; i < kNumDoorSprites; i++) {
- uint16 w = info->layer[i].width * 4;
- byte h = info->layer[i].height;
- byte *pixels = info->layer[i].pixels;
- uint16 offs = info->layer[i].offs;
-
- if (!info->flipped)
- ega_BlitSprite(pixels, w, w, h, backbuffer, offs);
- else
- ega_BlitSpriteFlip(pixels, w, w, h, backbuffer, offs);
- }
- waitVBlank();
- waitVBlank();
- ega_BlitFromBackBuffer(info->width * 4, info->height, frontbuffer, info->offs);
- return;
- }
+ bool isEGA = (g_vm->_videoMode == Common::kRenderEGA);
for (i = 0; i < kNumDoorSprites; i++) {
byte w = info->layer[i].width;
byte h = info->layer[i].height;
byte *pixels = info->layer[i].pixels;
uint16 offs = info->layer[i].offs;
+ int16 pitch = isEGA ? w * 4 : w * 2;
if (!info->flipped)
- g_vm->_renderer->blitSprite(pixels, w * 2, w, h, backbuffer, offs);
+ g_vm->_renderer->blitSprite(pixels, pitch, w, h, backbuffer, offs);
else
- g_vm->_renderer->blitSpriteFlip(pixels, w * 2, w, h, backbuffer, offs);
+ g_vm->_renderer->blitSpriteFlip(pixels, pitch, w, h, backbuffer, offs);
}
waitVBlank();
waitVBlank();
@@ -850,8 +834,7 @@ void drawRoomStaticObject(byte *aptr, byte *rx, byte *ry, byte *rw, byte *rh) {
byte *pixels = (byte *)surf->getPixels();
int16 pitch = surf->pitch;
- // EGA: ega_BlitSpriteFlip writes left-to-right from ofs (left edge),
- // so do NOT shift x to the rightmost position (that's a CGA-only convention).
+ /*EGA blitter uses left-edge offset; no rightmost-byte shift needed*/
byte drawx = x & 0x7F;
if (y & 0x80) {
@@ -1135,12 +1118,11 @@ void loadLutinSprite(uint16 lutidx) {
lutH = *lutin_entry++; /* composite height in pixels */
if (g_vm->_videoMode == Common::kRenderEGA) {
- // EGA path: build a CLUT8 flat buffer in lutin_mem.
- // Layout: [0]=lutW, [1]=lutH, then lutW*4 bytes per row à lutH rows (index 0 = transparent).
- uint16 pw = (uint16)lutW * 4; // pixel width
+ /*EGA: build CLUT8 flat buffer in lutin_mem: [0]=lutW, [1]=lutH, then lutW*4 bytes/row*/
+ uint16 pw = (uint16)lutW * 4;
lutin_mem[0] = lutW;
lutin_mem[1] = lutH;
- memset(lutin_mem + 2, 0, pw * lutH); // clear to transparent (index 0)
+ memset(lutin_mem + 2, 0, pw * lutH);
for (; lutin_entry != lutin_entry_end;) {
byte spridx = *lutin_entry++;
@@ -1153,13 +1135,13 @@ void loadLutinSprite(uint16 lutidx) {
uint16 sh = surf->h;
int16 spitch = surf->pitch;
- // Convert CGA byte-offset to pixel position in lutin buffer
+ /*decode CGA byte-offset to pixel position in lutin buffer*/
uint16 byteOfs = flags & 0x7FFF;
uint16 row = (lutW > 0) ? (byteOfs / lutW) : 0;
uint16 col = (lutW > 0) ? (byteOfs % lutW) : 0;
byte *dst = lutin_mem + 2 + row * pw + col * 4;
- if (flags & 0x8000) { // horizontal flip (mirrors columns, same as CGA mergeSpritesDataFlip)
+ if (flags & 0x8000) { /*horizontal flip*/
for (uint16 y = 0; y < sh; y++) {
for (uint16 x = 0; x < sw; x++) {
byte p = src[sw - 1 - x];
@@ -1182,7 +1164,7 @@ void loadLutinSprite(uint16 lutidx) {
return;
}
- // CGA path: build CGA mask+pixel buffer in lutin_mem.
+ /*CGA path: build CGA mask+pixel buffer in lutin_mem*/
buffer = lutin_mem;
for (uint16 i = 0; i < 800; i++) { /*TODO: fix size*/
buffer[i * 2] = 0xFF; /*mask*/
@@ -1499,7 +1481,7 @@ uint16 getPuzzlSprite(byte index, byte x, byte y, uint16 *w, uint16 *h, uint16 *
*w = surf->w / 4;
*h = surf->h;
*ofs = CalcXY_p(x, y);
- // Copy EGA pixel data into scratch_mem2+2 so cga_BlitScratchBackSprite can find it
+ /*copy EGA pixel data into scratch_mem2+2 for blitScratchBackSprite*/
byte *dst = scratch_mem2 + 2;
for (int row = 0; row < surf->h; row++) {
memcpy(dst, (byte *)surf->getPixels() + row * surf->pitch, surf->w);
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index f58b77556e4..75c44de5295 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -761,8 +761,6 @@ void twistDraw(byte x, byte y, byte width, byte height, byte *source, byte *targ
for (i = 0; i < width * 4; i++) {
g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sx += 1;
ex -= 1;
@@ -778,8 +776,6 @@ void twistDraw(byte x, byte y, byte width, byte height, byte *source, byte *targ
for (i = 0; i < height; i++) {
g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sy -= 1;
ey += 1;
@@ -820,24 +816,18 @@ void arcDraw(byte x, byte y, byte width, byte height, byte *source, byte *target
for (i = 0; i < height; i++) {
g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sy -= 1;
}
for (i = 0; i < width * 4; i++) {
g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sx += 1;
}
for (i = 0; i < height + 1; i++) {
g_vm->_renderer->traceLine(sx, ex, sy, ey, source, target);
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
sy += 1;
}
@@ -992,7 +982,6 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
script_ptr++;
index = *script_ptr++;
- warning("SCR_19_HidePortraitLiftLeft: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1054,7 +1043,6 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
script_ptr++;
index = *script_ptr++;
- warning("SCR_1A_HidePortraitLiftRight: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1115,7 +1103,6 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
script_ptr++;
index = *script_ptr++;
- warning("SCR_1B_HidePortraitLiftUp: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1124,7 +1111,6 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
}
if (g_vm->_videoMode == Common::kRenderEGA) {
- /* offs = CalcXY_p(x, y) from dirty rect â restore full portrait area */
g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1136,13 +1122,12 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
}
/*hide topmost line*/
- {
- offs ^= g_vm->_line_offset;
- if ((offs & g_vm->_line_offset) != 0)
- offs -= g_vm->_screenBPL;
- memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
- g_vm->_renderer->blitToScreen(offs, width, 1);
- }
+ /*TODO: move this to CGA?*/
+ offs ^= g_vm->_line_offset;
+ if ((offs & g_vm->_line_offset) != 0)
+ offs -= g_vm->_screenBPL;
+ memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
+ g_vm->_renderer->blitToScreen(offs, width, 1);
return 0;
}
@@ -1159,7 +1144,6 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
script_ptr++;
index = *script_ptr++;
- warning("SCR_1C_HidePortraitLiftDown: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1168,10 +1152,6 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
}
if (g_vm->_videoMode == Common::kRenderEGA) {
- /* offs = CalcXY_p(x, y) from dirty rect â restore full portrait area.
- * The CGA path recalculates offs to y+height-2 (bottom of portrait),
- * causing ega_CopyScreenBlock to start from the wrong position and
- * leave most of the portrait unrestoâred. */
g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
return 0;
}
@@ -1183,13 +1163,12 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
}
/*hide bottommost line*/
- {
- offs ^= g_vm->_line_offset;
- if ((offs & g_vm->_line_offset) == 0)
- offs += g_vm->_screenBPL;
- memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
- g_vm->_renderer->blitToScreen(offs, width, 1);
- }
+ /*TODO: move this to CGA?*/
+ offs ^= g_vm->_line_offset;
+ if ((offs & g_vm->_line_offset) == 0)
+ offs += g_vm->_screenBPL;
+ memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
+ g_vm->_renderer->blitToScreen(offs, width, 1);
return 0;
}
@@ -1385,9 +1364,6 @@ void jaggedZoom(byte *source, byte *target) {
}
g_vm->_renderer->traceLine(sx / 2, ex / 2, sy / 2, ey / 2, source, target);
}
- /* One screen update per cycle (not per line) keeps the animation fluid */
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
}
}
@@ -1435,7 +1411,6 @@ void drawStars(star_t *stars, int16 iter, byte *target) {
short z, x, y;
byte pixel, mask;
- /* Erase previous star position */
if (g_vm->_videoMode == Common::kRenderEGA)
target[stars->ofs] = 0;
else
@@ -1462,10 +1437,9 @@ void drawStars(star_t *stars, int16 iter, byte *target) {
if (g_vm->_videoMode == Common::kRenderEGA) {
stars->ofs = ega_CalcXY_p(x, y);
- /* EGA: CLUT8 single byte per pixel; bright = white (15), dim = dark gray (8) */
pixel = (stars->z < 0xE00) ? 15 : 8;
stars->pixel = pixel;
- stars->mask = 0; /* unused in EGA path */
+ stars->mask = 0;
target[stars->ofs] = pixel;
} else {
stars->ofs = g_vm->_renderer->calcXY(x, y);
@@ -1488,8 +1462,6 @@ void animStarfield(star_t *stars, byte *target) {
int16 i;
for (i = 100; i; i--) {
drawStars(stars, i, target);
- if (g_vm->_videoMode == Common::kRenderEGA && target == CGA_SCREENBUFFER)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
waitVBlank();
}
}
@@ -1822,8 +1794,6 @@ uint16 SCR_28_MenuLoop(void) {
mask = *script_ptr++;
value = *script_ptr++;
- warning("SCR_28_MenuLoop: cursor=%d mask=0x%02X value=0x%02X", cursor, mask, value);
-
selectCursor(cursor);
menuLoop(mask, value);
@@ -1899,7 +1869,6 @@ uint16 SCR_23_HidePortrait(void) {
script_ptr++;
index = *script_ptr++;
- warning("SCR_23_HidePortrait: index=%d", index);
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
@@ -1937,7 +1906,6 @@ uint16 SCR_3F_HidePortrait(void) {
Restore screen data from back buffer for all portraits
*/
uint16 SCR_24_PopAllPortraits(void) {
- warning("SCR_24_PopAllPortraits");
script_ptr++;
popDirtyRects(DirtyRectSprite);
return 0;
@@ -3529,7 +3497,7 @@ void DrawStickyNet(void) {
if (g_vm->_videoMode == Common::kRenderEGA) {
Graphics::Surface *surf = ega_puzzl_res->getSprite(80);
- uint16 sprW = surf->w; /* pixels */
+ uint16 sprW = surf->w;
uint16 sprH = surf->h;
byte *pixels = (byte *)surf->getPixels();
int16 pitch = surf->pitch;
diff --git a/engines/chamber/timer.cpp b/engines/chamber/timer.cpp
index d7f7896c33a..392f307c7b6 100644
--- a/engines/chamber/timer.cpp
+++ b/engines/chamber/timer.cpp
@@ -32,10 +32,8 @@ namespace Chamber {
void animateGauss(byte *target) {
- // In EGA mode, the gauss animation tiles are CGA format data.
- // The EGA background (FOND.EGA) already includes the gauss area pre-rendered.
if (g_vm->_videoMode == Common::kRenderEGA)
- return;
+ return; /*gauss area is pre-rendered in FOND.EGA*/
byte *sprite;
byte phase = getRand() % 4;
if (phase == script_byte_vars.gauss_phase)
Commit: 0f27cdba16e7b429dbc3c54eb19267b8ca087683
https://github.com/scummvm/scummvm/commit/0f27cdba16e7b429dbc3c54eb19267b8ca087683
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-26T00:54:56+02:00
Commit Message:
CHAMBER: Address review comments
Changed paths:
engines/chamber/anim.cpp
engines/chamber/cga.cpp
engines/chamber/cga.h
engines/chamber/chamber.cpp
engines/chamber/cursor.cpp
engines/chamber/cursor.h
engines/chamber/dialog.cpp
engines/chamber/ega.cpp
engines/chamber/ega.h
engines/chamber/input.cpp
engines/chamber/invent.cpp
engines/chamber/kult.cpp
engines/chamber/menu.cpp
engines/chamber/module.mk
engines/chamber/portrait.cpp
engines/chamber/print.cpp
engines/chamber/renderer.h
engines/chamber/resdata.h
engines/chamber/room.cpp
engines/chamber/script.cpp
diff --git a/engines/chamber/anim.cpp b/engines/chamber/anim.cpp
index 2384cad0246..7cd7aa00311 100644
--- a/engines/chamber/anim.cpp
+++ b/engines/chamber/anim.cpp
@@ -110,7 +110,7 @@ void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx
void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte height, byte *target) {
if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_CopyScreenBlock(source, width * 4, height, target, ega_CalcXY_p(x, y));
+ g_vm->_renderer->copyScreenBlock(source, width, height, target, g_vm->_renderer->calcXY_p(x, y));
return;
}
uint16 offs;
@@ -138,7 +138,7 @@ void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte
void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 pitch) {
uint16 delay;
byte ex, ey, updx, updy, updw, updh;
- uint16 ofs = CalcXY_p(x, y);
+ uint16 ofs = g_vm->_renderer->calcXY_p(x, y);
g_vm->_renderer->backupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
g_vm->_renderer->blitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
ex = x + sprw;
@@ -158,7 +158,7 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
}
updw = ex - updx;
updh = ey - updy;
- ofs = CalcXY_p(updx, updy);
+ ofs = g_vm->_renderer->calcXY_p(updx, updy);
/*TODO looks like here was some code before*/
for (delay = 0; delay < anim_draw_delay; delay++) {
g_system->delayMillis(1000 / 16 / 25);
@@ -181,7 +181,7 @@ void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 p
}
void animUndrawSprite(void) {
- g_vm->_renderer->copyScreenBlock(backbuffer, last_anim_width, last_anim_height, CGA_SCREENBUFFER, CalcXY_p(last_anim_x, last_anim_y));
+ g_vm->_renderer->copyScreenBlock(backbuffer, last_anim_width, last_anim_height, SCREENBUFFER, g_vm->_renderer->calcXY_p(last_anim_x, last_anim_y));
last_anim_height = 0;
}
diff --git a/engines/chamber/cga.cpp b/engines/chamber/cga.cpp
index 8e21169acae..85978fd58bb 100644
--- a/engines/chamber/cga.cpp
+++ b/engines/chamber/cga.cpp
@@ -67,7 +67,7 @@ uint16 HGA_CalcXY(uint16 x, uint16 y) {
}
extern byte backbuffer[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
-byte CGA_SCREENBUFFER[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
+byte SCREENBUFFER[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
Graphics::Surface *mainSurface = nullptr;
extern byte *scratch_mem2;
@@ -140,7 +140,7 @@ void switchToTextMode(void) {
void waitVBlank(void) {
pollInput();
if (g_vm->_videoMode == Common::kRenderEGA)
- ega_blitToScreen(0, 0, 320, 200);
+ g_vm->_renderer->blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
g_system->delayMillis(10);
g_system->updateScreen();
}
@@ -188,7 +188,7 @@ void CGARenderer::blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
for (int16 y = 0; y < h; y++) {
uint16 line_start = calcXY(dx, dy + y);
- byte *src = CGA_SCREENBUFFER + line_start;
+ byte *src = SCREENBUFFER + line_start;
byte *dst = (byte *)mainSurface->getBasePtr(dx, y + dy);
for (int16 x = 0; x < w; x++) {
@@ -238,7 +238,7 @@ void CGARenderer::blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
byte *dst = (byte *)mainSurface->getBasePtr(destX, destY);
for (int x_bytes = startX_bytes; x_bytes < endX_bytes; x_bytes++) {
- byte cga_byte = CGA_SCREENBUFFER[bank + line + x_bytes];
+ byte cga_byte = SCREENBUFFER[bank + line + x_bytes];
for (int p = 0; p < 4; p++) {
byte color = (cga_byte >> (6 - p * 2)) & 3;
byte finalColor = (color == 0) ? 0 : 1;
@@ -268,7 +268,7 @@ void CGARenderer::blitToScreen(int16 ofs, int16 w, int16 h) {
void CGARenderer::backBufferToRealFull() {
if (g_vm->_videoMode == Common::RenderMode::kRenderCGA) {
- memcpy(CGA_SCREENBUFFER, backbuffer, sizeof(backbuffer));
+ memcpy(SCREENBUFFER, backbuffer, sizeof(backbuffer));
} else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG) {
byte tempBackbuffer[0x4000];
@@ -293,7 +293,7 @@ void CGARenderer::backBufferToRealFull() {
byte *srcPtr = tempBackbuffer;
for (int16 row = 0; row < CGA_HEIGHT; row++) {
- byte *destPtr = CGA_SCREENBUFFER + HGA_CalcXY(0, row);
+ byte *destPtr = SCREENBUFFER + HGA_CalcXY(0, row);
memmove(destPtr, srcPtr, CGA_BYTES_PER_LINE);
srcPtr += CGA_BYTES_PER_LINE;
}
@@ -302,7 +302,7 @@ void CGARenderer::backBufferToRealFull() {
}
void CGARenderer::realBufferToBackFull() {
- memcpy(backbuffer, CGA_SCREENBUFFER, sizeof(backbuffer));
+ memcpy(backbuffer, SCREENBUFFER, sizeof(backbuffer));
}
/*Copy interlaced screen data to another screen*/
@@ -317,7 +317,7 @@ void CGARenderer::copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target
ofs += g_vm->_screenBPL;
}
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -328,7 +328,7 @@ void CGARenderer::swapRealBackBuffer() {
uint16 i;
uint16 *s, *d;
waitVBlank();
- s = (uint16 *)CGA_SCREENBUFFER;
+ s = (uint16 *)SCREENBUFFER;
d = (uint16 *)backbuffer;
for (i = 0; i < sizeof(backbuffer) / 2; i++) {
uint16 t = *s;
@@ -358,7 +358,7 @@ void CGARenderer::swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen,
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -371,13 +371,6 @@ uint16 CGARenderer::calcXY(uint16 x, uint16 y) {
return calcXY_p(x / 4, y);
}
-uint16 CalcXY(uint16 x, uint16 y) {
- return g_vm->_renderer->calcXY(x, y);
-}
-
-uint16 CalcXY_p(uint16 x, uint16 y) {
- return g_vm->_renderer->calcXY_p(x, y);
-}
/*
Calc screen offset from packed pixel coordinates
@@ -401,8 +394,6 @@ Out:
next buffer ptr
*/
byte *CGARenderer::backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
- if (g_vm->_videoMode == Common::kRenderEGA)
- return ega_BackupImage(screen, ofs, w * 4, h, buffer);
*(byte *)(buffer + 0) = h;
*(byte *)(buffer + 1) = w;
*(uint16 *)(buffer + 2) = ofs;
@@ -418,7 +409,7 @@ byte *CGARenderer::backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byt
}
byte *cga_BackupImageReal(uint16 ofs, uint16 w, uint16 h) {
- return g_vm->_renderer->backupImage(CGA_SCREENBUFFER, ofs, w, h, scratch_mem2);
+ return g_vm->_renderer->backupImage(SCREENBUFFER, ofs, w, h, scratch_mem2);
}
/*
@@ -436,7 +427,7 @@ void CGARenderer::blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), h);
}
@@ -458,7 +449,7 @@ void CGARenderer::fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs)
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), h);
}
@@ -506,7 +497,7 @@ void CGARenderer::refreshImageData(byte *buffer) {
w = *(byte *)(buffer + 1);
ofs = *(uint16 *)(buffer + 2);
- copyScreenBlock(CGA_SCREENBUFFER, w, h, backbuffer, ofs);
+ copyScreenBlock(SCREENBUFFER, w, h, backbuffer, ofs);
}
/*
@@ -527,7 +518,7 @@ void CGARenderer::drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *targ
mask >>= (x % g_vm->_screenPPB) * g_vm->_screenPPB;
pixel >>= (x % g_vm->_screenPPB) * g_vm->_screenPPB;
- ofs = CalcXY_p(x / g_vm->_screenPPB, y);
+ ofs = g_vm->_renderer->calcXY_p(x / g_vm->_screenPPB, y);
uint16 ol = l;
while (l--) {
@@ -537,7 +528,7 @@ void CGARenderer::drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *targ
ofs += g_vm->_screenBPL;
}
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen(x, y, 1, ol);
}
@@ -560,7 +551,7 @@ void CGARenderer::drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *targ
mask >>= (x % g_vm->_screenPPB) * g_vm->_screenPPB;
pixel >>= (x % g_vm->_screenPPB) * g_vm->_screenPPB;
- ofs = CalcXY_p(x / g_vm->_screenPPB, y);
+ ofs = g_vm->_renderer->calcXY_p(x / g_vm->_screenPPB, y);
uint16 ol = l;
while (l--) {
@@ -577,7 +568,7 @@ void CGARenderer::drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *targ
pixel = color << ((g_vm->_screenPPB - 1) * g_vm->_screenPPB);
}
}
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen(x, y, ol, 1);
}
@@ -595,7 +586,7 @@ uint16 CGARenderer::drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uin
if ((ofs & g_vm->_line_offset) == 0)
ofs += g_vm->_screenBPL;
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, l * 4 + 2, 1);
return ofs;
@@ -619,7 +610,7 @@ void CGARenderer::printChar(byte c, byte *target) {
ofs += g_vm->_screenBPL;
}
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen((char_draw_coords_x - 1) * g_vm->_fontWidth, char_draw_coords_y, g_vm->_fontWidth, g_vm->_fontHeight);
} else if (g_vm->_videoMode == Common::RenderMode::kRenderHercG) {
@@ -632,7 +623,7 @@ void CGARenderer::printChar(byte c, byte *target) {
target[ofs] = c;
}
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen(START_X, START_Y, g_vm->_fontWidth, g_vm->_fontHeight);
}
}
@@ -657,7 +648,7 @@ void CGARenderer::blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -682,7 +673,7 @@ void CGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *s
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -703,7 +694,7 @@ void CGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byt
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -730,7 +721,7 @@ void CGARenderer::blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte
ofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER)
+ if (screen == SCREENBUFFER)
g_vm->_renderer->blitToScreen(oofs, w * (0x8 / g_vm->_screenBits), oh);
}
@@ -739,32 +730,22 @@ void CGARenderer::blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte
Blit progressive sprite (w+h+mask+pixel) to interlaced screen buffer.
In EGA mode sprite is a decoded CLUT8 Graphics::Surface; w and h come from it.
*/
-void drawSprite(byte *sprite, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
- ega_BlitSprite((byte *)surf->getPixels(), surf->pitch, surf->w, surf->h, screen, ofs);
- return;
- }
+void CGARenderer::drawSprite(byte *sprite, byte *screen, uint16 ofs) {
byte w, h;
w = *sprite++;
h = *sprite++;
- g_vm->_renderer->blitSprite(sprite, w * 2, w, h, screen, ofs);
+ blitSprite(sprite, w * 2, w, h, screen, ofs);
}
/*
Blit progressive sprite (w+h+mask+pixel) to interlaced screen buffer, horizontally flipped.
In EGA mode sprite is a decoded CLUT8 Graphics::Surface.
*/
-void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) {
- if (g_vm->_videoMode == Common::kRenderEGA) {
- Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
- ega_BlitSpriteFlip((byte *)surf->getPixels(), surf->pitch, surf->w, surf->h, screen, ofs);
- return;
- }
+void CGARenderer::drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) {
byte w, h;
w = *sprite++;
h = *sprite++;
- g_vm->_renderer->blitSpriteFlip(sprite, w * 2, w, h, screen, ofs);
+ blitSpriteFlip(sprite, w * 2, w, h, screen, ofs);
}
/*
@@ -852,16 +833,12 @@ extern byte sprit_data[RES_SPRIT_MAX];
byte sprit_load_buffer[8192];
-byte *loadSprit(byte index) {
- if (g_vm->_videoMode == Common::kRenderEGA)
- return reinterpret_cast<byte *>(ega_sprit_res->getSprite(index));
+byte *CGARenderer::loadSprit(byte index) {
loadSprite(index, sprit_data + 4, sprit_load_buffer, 0);
return sprit_load_buffer;
}
-byte *loadPersSprit(byte index) {
- if (g_vm->_videoMode == Common::kRenderEGA)
- return reinterpret_cast<byte *>(ega_perso_res->getSprite(index));
+byte *CGARenderer::loadPersSprit(byte index) {
#if 1
/*Use separate memory for pers1/pers2*/
if (index < 61)
@@ -880,34 +857,27 @@ byte *loadPersSprit(byte index) {
void drawSpriteN(byte index, uint16 x, uint16 y, byte *target) {
uint16 ofs;
byte *sprite;
- sprite = loadSprit(index);
- ofs = CalcXY_p(x, y);
- drawSprite(sprite, target, ofs);
+ sprite = g_vm->_renderer->loadSprit(index);
+ ofs = g_vm->_renderer->calcXY_p(x, y);
+ g_vm->_renderer->drawSprite(sprite, target, ofs);
}
void drawSpriteNFlip(byte index, uint16 x, uint16 y, byte *target) {
uint16 ofs;
byte *sprite;
- sprite = loadSprit(index);
- ofs = CalcXY_p(x, y);
- drawSpriteFlip(sprite, target, ofs);
+ sprite = g_vm->_renderer->loadSprit(index);
+ ofs = g_vm->_renderer->calcXY_p(x, y);
+ g_vm->_renderer->drawSpriteFlip(sprite, target, ofs);
}
-void backupAndShowSprite(byte index, byte x, byte y) {
+void CGARenderer::backupAndShowSprite(byte index, byte x, byte y) {
byte *sprite = loadSprit(index);
- uint16 ofs = CalcXY_p(x, y);
-
- if (g_vm->_videoMode == Common::kRenderEGA) {
- Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
- ega_BackupImage(ega_screen, ofs, surf->w, surf->h, scratch_mem2);
- drawSprite(sprite, ega_screen, ofs);
- return;
- }
+ uint16 ofs = calcXY_p(x, y);
byte w = sprite[0];
byte h = sprite[1];
cga_BackupImageReal(ofs, w, h);
- drawSprite(sprite, CGA_SCREENBUFFER, ofs);
+ drawSprite(sprite, SCREENBUFFER, ofs);
}
/*
@@ -915,20 +885,11 @@ Blit progressive image to interlaced screen buffer, then wait for VBlank
Push image from the top to down
NB! width and pixelswidth specify a number of bytes, not count of pixels
*/
-void cga_AnimLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+void CGARenderer::animLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
uint16 i;
- if (g_vm->_videoMode == Common::kRenderEGA) {
- uint16 epw = pw * 4;
- pixels += epw * (h - 1);
- for (i = 1; i <= h; i++) {
- g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, ofs);
- pixels -= epw;
- }
- return;
- }
pixels += pw * (h - 1);
for (i = 1; i <= h; i++) {
- g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, ofs);
+ blitAndWait(pixels, pw, w, i, screen, ofs);
pixels -= pw;
}
}
@@ -966,17 +927,10 @@ Push image from the down to up
NB! width and pixelswidth specify a number of bytes, not count of pixels
NB! x:y specifies left-bottom coords
*/
-void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) {
+void CGARenderer::animLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) {
uint16 i;
- if (g_vm->_videoMode == Common::kRenderEGA) {
- for (i = 1; i <= h; i++) {
- g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, ega_CalcXY_p(x, y));
- y -= 1;
- }
- return;
- }
for (i = 1; i <= h; i++) {
- g_vm->_renderer->blitAndWait(pixels, pw, w, i, screen, CalcXY_p(x, y));
+ blitAndWait(pixels, pw, w, i, screen, calcXY_p(x, y));
y -= 1;
}
}
@@ -1014,7 +968,7 @@ void CGARenderer::hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source
/*fill just freed line with new pixels*/
memcpy(target + tofs, source + tofs, w);
- if (screen == CGA_SCREENBUFFER) {
+ if (screen == SCREENBUFFER) {
g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenW);
}
@@ -1059,7 +1013,7 @@ void CGARenderer::hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source,
/*fill just freed line with new pixels*/
memcpy(target + tofs, source + tofs, w);
- if (screen == CGA_SCREENBUFFER) {
+ if (screen == SCREENBUFFER) {
g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
@@ -1098,7 +1052,7 @@ void CGARenderer::hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source
sofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER) {
+ if (screen == SCREENBUFFER) {
g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
@@ -1135,7 +1089,7 @@ void CGARenderer::hideScreenBlockLiftToRight(uint16 n, byte *screen, byte *sourc
sofs += g_vm->_screenBPL;
}
- if (screen == CGA_SCREENBUFFER) {
+ if (screen == SCREENBUFFER) {
g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
@@ -1278,7 +1232,7 @@ static void fallPieces(scrpiece_t *pieces, byte *source, byte *target) {
again = 1;
}
- if (target == CGA_SCREENBUFFER) {
+ if (target == SCREENBUFFER) {
g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
@@ -1319,15 +1273,15 @@ void CGARenderer::traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *so
dy = h * 2;
if (g_vm->_videoMode == Common::RenderMode::kRenderCGA) {
- ofs = CalcXY_p(sx / 4, sy);
+ ofs = g_vm->_renderer->calcXY_p(sx / 4, sy);
mask = 0xC0 >> ((sx % 4) * 2);
} else {
- ofs = CalcXY_p(sx / 8, sy);
+ ofs = g_vm->_renderer->calcXY_p(sx / 8, sy);
mask = 0x80 >> (sx % 8); // TODO: check this
}
/*
- ofs = CalcXY_p(sx / 4, sy);
+ ofs = g_vm->_renderer->calcXY_p(sx / 4, sy);
mask = 0xC0 >> ((sx % 4) * 2);
*/
@@ -1370,7 +1324,7 @@ void CGARenderer::traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *so
target[ofs] = (target[ofs] & ~mask) | (source[ofs] & mask);
}
- if (target == CGA_SCREENBUFFER)
+ if (target == SCREENBUFFER)
g_vm->_renderer->blitToScreen(0, 0, g_vm->_screenW, g_vm->_screenH);
}
@@ -1736,7 +1690,7 @@ void CGARenderer::zoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh,
zoom.eh = h - 1;
zoom.xbase = x % 4;
- cga_ZoomInplace(&zoom, nw, nh, target, target, CalcXY_p(x, y));
+ cga_ZoomInplace(&zoom, nw, nh, target, target, g_vm->_renderer->calcXY_p(x, y));
}
} // End of namespace Chamber
diff --git a/engines/chamber/cga.h b/engines/chamber/cga.h
index b66711e96e7..ee5060130ee 100644
--- a/engines/chamber/cga.h
+++ b/engines/chamber/cga.h
@@ -59,14 +59,14 @@ namespace Chamber {
#define CGA_PIXELS_PER_BYTE (8 / CGA_BITS_PER_PIXEL)
#define CGA_BYTES_PER_LINE (CGA_WIDTH / CGA_PIXELS_PER_BYTE)
-extern byte CGA_SCREENBUFFER[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
+extern byte SCREENBUFFER[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
#define CGA_FONT_HEIGHT 6
#define CGA_NEXT_LINE(offs) ((CGA_ODD_LINES_OFS ^ (offs)) + (((offs) & CGA_ODD_LINES_OFS) ? 0 : CGA_BYTES_PER_LINE))
#define CGA_PREV_LINE(offs) ((CGA_ODD_LINES_OFS ^ (offs)) - (((offs) & CGA_ODD_LINES_OFS) ? CGA_BYTES_PER_LINE : 0))
-#define frontbuffer CGA_SCREENBUFFER
+#define frontbuffer SCREENBUFFER
extern byte backbuffer[0xFA00]; ///< CGA/HGA: 0xB800, EGA: 0xFA00 (64000)
extern byte sprit_load_buffer[8192];
@@ -84,8 +84,6 @@ void switchToTextMode(void);
void waitVBlank(void);
-uint16 CalcXY(uint16 x, uint16 y);
-uint16 CalcXY_p(uint16 x, uint16 y);
uint16 HGA_CalcXY(uint16 x, uint16 y);
uint16 HGA_CalcXY_p(uint16 x, uint16 y);
@@ -93,22 +91,11 @@ uint16 cga_CalcXY_p(uint16 x, uint16 y);
byte *cga_BackupImageReal(uint16 ofs, uint16 w, uint16 h);
-void drawSprite(byte *sprite, byte *screen, uint16 ofs);
-void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs);
-
void drawSpriteN(byte index, uint16 x, uint16 y, byte *target);
void drawSpriteNFlip(byte index, uint16 x, uint16 y, byte *target);
-void backupAndShowSprite(byte index, byte x, byte y);
-
byte *loadSprite(byte index, byte *bank, byte *buffer, byte header_only);
-byte *loadSprit(byte index);
-byte *loadPersSprit(byte index);
-
-void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y);
-void cga_AnimLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
} // End of namespace Chamber
#endif
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 06be502db71..dcc8e0b8726 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -56,7 +56,7 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
_pxiData = NULL;
Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
- if (renderMode == Common::kRenderEGA || renderMode == Common::kRenderHercG)
+ if (renderMode == Common::kRenderEGA || renderMode == Common::kRenderHercG || renderMode == Common::kRenderHercA)
_videoMode = renderMode;
else
_videoMode = Common::kRenderCGA;
diff --git a/engines/chamber/cursor.cpp b/engines/chamber/cursor.cpp
index 603da0980aa..73344c56f12 100644
--- a/engines/chamber/cursor.cpp
+++ b/engines/chamber/cursor.cpp
@@ -27,6 +27,8 @@
#include "chamber/resdata.h"
#include "chamber/cga.h"
#include "chamber/ega.h"
+#include "chamber/renderer.h"
+#include "graphics/palette.h"
namespace Chamber {
@@ -64,62 +66,69 @@ byte cursorImage[CURSOR_WIDTH * CURSOR_HEIGHT];
/*
Select cursor shape and its hotspot
*/
-void selectCursor(uint16 num) {
+void CGARenderer::selectCursor(uint16 num) {
cursor_x_shift = cursor_shifts[num][0];
cursor_y_shift = cursor_shifts[num][1];
byte *dst = cursorImage;
- if (g_vm->_videoMode == Common::kRenderEGA) {
- /*EGA SOURI.EGA: 64 bytes/cursor, 4 bytes per row.
- Each row = two little-endian 16-bit planes:
- planeA (bytes 0,1): black mask (bit set = black pixel)
- planeB (bytes 2,3): white mask (bit set = white pixel)
- A=0,B=0 -> transparent; A=1,B=0 -> black; B=1 -> white.*/
- cursor_shape = souri_data + num * (CURSOR_WIDTH * CURSOR_HEIGHT / 4);
- byte *src = cursor_shape;
- for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
- uint16 planeA = (uint16)src[0] | ((uint16)src[1] << 8);
- uint16 planeB = (uint16)src[2] | ((uint16)src[3] << 8);
- src += 4;
- for (int16 x = 0; x < CURSOR_WIDTH; x++) {
- byte bitA = (planeA >> (CURSOR_WIDTH - 1 - x)) & 1;
- byte bitB = (planeB >> (CURSOR_WIDTH - 1 - x)) & 1;
- if (!bitA && !bitB)
- *dst++ = 255; /*transparent*/
- else if (bitB)
- *dst++ = 15; /*white*/
- else
- *dst++ = 0; /*black*/
- }
- }
- } else {
- cursor_shape = souri_data + num * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / 4;
- byte *src = cursor_shape;
- for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
- for (int16 x = 0; x < CURSOR_HEIGHT / 4; x++) {
- byte colors = *src;
- byte masks = *(src++ + CURSOR_HEIGHT * CURSOR_WIDTH / 4);
-
- for (int16 c = 0; c < 4; c++) {
- byte color = (colors & 0xC0) >> 6;
- byte mask = (masks & 0xC0) >> 6;
- colors <<= 2;
- masks <<= 2;
-
- if (!mask)
- *dst++ = color;
- else {
- *dst++ = 255;
- }
+ cursor_shape = souri_data + num * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / 4;
+ byte *src = cursor_shape;
+ for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
+ for (int16 x = 0; x < CURSOR_HEIGHT / 4; x++) {
+ byte colors = *src;
+ byte masks = *(src++ + CURSOR_HEIGHT * CURSOR_WIDTH / 4);
+
+ for (int16 c = 0; c < 4; c++) {
+ byte color = (colors & 0xC0) >> 6;
+ byte mask = (masks & 0xC0) >> 6;
+ colors <<= 2;
+ masks <<= 2;
+
+ if (!mask)
+ *dst++ = color;
+ else {
+ *dst++ = 255;
}
}
}
}
g_system->setMouseCursor(cursorImage, CURSOR_WIDTH, CURSOR_HEIGHT, cursor_x_shift, cursor_y_shift, 255);
- if (g_vm->_videoMode == Common::kRenderEGA)
- g_system->setCursorPalette(EGA_PALETTE, 0, 16);
+ g_system->showMouse(true);
+}
+
+void EGARenderer::selectCursor(uint16 num) {
+ cursor_x_shift = cursor_shifts[num][0];
+ cursor_y_shift = cursor_shifts[num][1];
+
+ byte *dst = cursorImage;
+
+ /*EGA SOURI.EGA: 64 bytes/cursor, 4 bytes per row.
+ Each row = two little-endian 16-bit planes:
+ planeA (bytes 0,1): black mask (bit set = black pixel)
+ planeB (bytes 2,3): white mask (bit set = white pixel)
+ A=0,B=0 -> transparent; A=1,B=0 -> black; B=1 -> white.*/
+ cursor_shape = souri_data + num * (CURSOR_WIDTH * CURSOR_HEIGHT / 4);
+ byte *src = cursor_shape;
+ for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
+ uint16 planeA = (uint16)src[0] | ((uint16)src[1] << 8);
+ uint16 planeB = (uint16)src[2] | ((uint16)src[3] << 8);
+ src += 4;
+ for (int16 x = 0; x < CURSOR_WIDTH; x++) {
+ byte bitA = (planeA >> (CURSOR_WIDTH - 1 - x)) & 1;
+ byte bitB = (planeB >> (CURSOR_WIDTH - 1 - x)) & 1;
+ if (!bitA && !bitB)
+ *dst++ = 255; /*transparent*/
+ else if (bitB)
+ *dst++ = 15; /*white*/
+ else
+ *dst++ = 0; /*black*/
+ }
+ }
+
+ g_system->setMouseCursor(cursorImage, CURSOR_WIDTH, CURSOR_HEIGHT, cursor_x_shift, cursor_y_shift, 255);
+ g_system->setCursorPalette(Graphics::Palette::createEGAPalette().data(), 0, 16);
g_system->showMouse(true);
}
diff --git a/engines/chamber/cursor.h b/engines/chamber/cursor.h
index b0388e55523..0a22c84a352 100644
--- a/engines/chamber/cursor.h
+++ b/engines/chamber/cursor.h
@@ -48,7 +48,6 @@ extern byte *cursor_shape;
extern byte cursor_anim_ticks;
extern byte cursor_anim_phase;
-void selectCursor(uint16 num);
void updateCursor(void);
void drawCursor(byte *target);
void undrawCursor(byte *target);
diff --git a/engines/chamber/dialog.cpp b/engines/chamber/dialog.cpp
index 7298143abd4..7235a716442 100644
--- a/engines/chamber/dialog.cpp
+++ b/engines/chamber/dialog.cpp
@@ -105,7 +105,7 @@ void desciTextBox(uint16 x, uint16 y, uint16 width, byte *msg) {
draw_y = y;
char_draw_max_width = width;
cga_DrawTextBox(msg, frontbuffer);
- addDirtyRect(DirtyRectText, draw_x, draw_y, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, CalcXY_p(draw_x, draw_y));
+ addDirtyRect(DirtyRectText, draw_x, draw_y, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, g_vm->_renderer->calcXY_p(draw_x, draw_y));
}
/*Draw dialog bubble with text and spike*/
@@ -124,26 +124,26 @@ void drawPersonBubble(byte x, byte y, byte flags, byte *msg) {
}
/*upper border*/
- ofs = CalcXY_p(x, y);
- ofs = g_vm->_renderer->drawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = g_vm->_renderer->drawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = g_vm->_renderer->drawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = g_vm->_renderer->drawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->calcXY_p(x, y);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, SCREENBUFFER, ofs);
/*body*/
char_draw_coords_x = x;
char_draw_coords_y = y + 4;
for (string_ended = 0; !string_ended; char_draw_coords_y += 6) {
- g_vm->_renderer->printChar(0x3B, CGA_SCREENBUFFER);
- msg = printStringPadded(msg, CGA_SCREENBUFFER);
- g_vm->_renderer->printChar(0x3C, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar(0x3B, SCREENBUFFER);
+ msg = printStringPadded(msg, SCREENBUFFER);
+ g_vm->_renderer->printChar(0x3C, SCREENBUFFER);
char_draw_coords_x = x;
}
- ofs = CalcXY_p(x, char_draw_coords_y);
- ofs = g_vm->_renderer->drawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
- ofs = g_vm->_renderer->drawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->calcXY_p(x, char_draw_coords_y);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, SCREENBUFFER, ofs);
+ ofs = g_vm->_renderer->drawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, SCREENBUFFER, ofs);
w = char_draw_max_width + 2;
h = char_draw_coords_y - y + 2;
@@ -151,32 +151,32 @@ void drawPersonBubble(byte x, byte y, byte flags, byte *msg) {
/*draw spike*/
switch (flags & SPIKE_MASK) {
case SPIKE_UPLEFT: /*upper-left spike*/
- ofs = CalcXY_p(x + 1, y - 7);
- drawSpriteN(18, x + 1, y - 7, CGA_SCREENBUFFER);
+ ofs = g_vm->_renderer->calcXY_p(x + 1, y - 7);
+ drawSpriteN(18, x + 1, y - 7, SCREENBUFFER);
break;
case SPIKE_UPRIGHT: /*upper-right spike*/
- ofs = CalcXY_p(x + char_draw_max_width, y - 7) - 1;
- drawSpriteNFlip(18, x + char_draw_max_width, y - 7, CGA_SCREENBUFFER);
+ ofs = g_vm->_renderer->calcXY_p(x + char_draw_max_width, y - 7) - 1;
+ drawSpriteNFlip(18, x + char_draw_max_width, y - 7, SCREENBUFFER);
break;
case SPIKE_DNRIGHT: /*lower-right spike*/
- ofs = CalcXY_p(x + char_draw_max_width, char_draw_coords_y + 1) - 1;
- drawSpriteNFlip(21, x + char_draw_max_width, char_draw_coords_y + 1, CGA_SCREENBUFFER);
+ ofs = g_vm->_renderer->calcXY_p(x + char_draw_max_width, char_draw_coords_y + 1) - 1;
+ drawSpriteNFlip(21, x + char_draw_max_width, char_draw_coords_y + 1, SCREENBUFFER);
break;
case SPIKE_DNLEFT: /*lower-left spike*/
- ofs = CalcXY_p(x + 1, char_draw_coords_y + 1);
- drawSpriteN(21, x + 1, char_draw_coords_y + 1, CGA_SCREENBUFFER);
+ ofs = g_vm->_renderer->calcXY_p(x + 1, char_draw_coords_y + 1);
+ drawSpriteN(21, x + 1, char_draw_coords_y + 1, SCREENBUFFER);
break;
case SPIKE_BUBRIGHT: /*lower-right bubbles*/
- ofs = CalcXY_p(x + char_draw_max_width, char_draw_coords_y + 4);
- drawSpriteN(20, x + char_draw_max_width, char_draw_coords_y + 4, CGA_SCREENBUFFER);
+ ofs = g_vm->_renderer->calcXY_p(x + char_draw_max_width, char_draw_coords_y + 4);
+ drawSpriteN(20, x + char_draw_max_width, char_draw_coords_y + 4, SCREENBUFFER);
break;
case SPIKE_BUBLEFT: /*lower-left bubbles*/
- ofs = CalcXY_p(x + 1, char_draw_coords_y + 4);
- drawSpriteN(19, x + 1, char_draw_coords_y + 4, CGA_SCREENBUFFER);
+ ofs = g_vm->_renderer->calcXY_p(x + 1, char_draw_coords_y + 4);
+ drawSpriteN(19, x + 1, char_draw_coords_y + 4, SCREENBUFFER);
break;
}
- addDirtyRect(DirtyRectBubble, ofs >> 8, ofs & 255, w, h, CalcXY_p(x, y));
+ addDirtyRect(DirtyRectBubble, ofs >> 8, ofs & 255, w, h, g_vm->_renderer->calcXY_p(x, y));
}
void showPromptAnim(void) {
@@ -189,7 +189,7 @@ void showPromptAnim(void) {
void promptWait(void) {
if (g_vm->_videoMode == Common::kRenderEGA)
- ega_blitToScreen(0, 0, 320, 200);
+ g_vm->_renderer->blitToScreen(0, 0, 320, 200);
cursor_anim_phase = 0;
do {
diff --git a/engines/chamber/ega.cpp b/engines/chamber/ega.cpp
index b63c34e9303..1c237a959d0 100644
--- a/engines/chamber/ega.cpp
+++ b/engines/chamber/ega.cpp
@@ -21,6 +21,7 @@
#include "common/file.h"
#include "common/system.h"
+#include "graphics/palette.h"
#include "graphics/paletteman.h"
#include "graphics/surface.h"
@@ -31,150 +32,37 @@
#include "chamber/input.h"
#include "chamber/resdata.h"
#include "chamber/renderer.h"
+#include "chamber/ega_resource.h"
#include "chamber/room.h"
namespace Chamber {
-// ---------------------------------------------------------------------------
-// EGA 16-color palette (standard EGA RGB values)
-// Source: kult/kult.cpp â this is the correct version (NOT BGR-swapped)
-// ---------------------------------------------------------------------------
-const byte EGA_PALETTE[16 * 3] = {
- 0x00, 0x00, 0x00, // 0 black
- 0x00, 0x00, 0xaa, // 1 dark blue
- 0x00, 0xaa, 0x00, // 2 dark green
- 0x00, 0xaa, 0xaa, // 3 dark cyan
- 0xaa, 0x00, 0x00, // 4 dark red
- 0xaa, 0x00, 0xaa, // 5 dark magenta
- 0xaa, 0x55, 0x00, // 6 brown
- 0xaa, 0xaa, 0xaa, // 7 light grey
- 0x00, 0x00, 0x00, // 8 dark grey (same as black in standard EGA)
- 0x55, 0x55, 0xff, // 9 bright blue
- 0x55, 0xff, 0x55, // 10 bright green
- 0x55, 0xff, 0xff, // 11 bright cyan
- 0xff, 0x55, 0x55, // 12 bright red
- 0xff, 0x55, 0xff, // 13 bright magenta
- 0xff, 0xff, 0x55, // 14 yellow
- 0xff, 0xff, 0xff, // 15 white
-};
-
-// ---------------------------------------------------------------------------
-// EGA framebuffers â aliases to the shared CGA/EGA buffers (both 64000 bytes)
-// ega_screen -> CGA_SCREENBUFFER (frontbuffer in room.cpp)
-// ega_backbuffer -> backbuffer (backbuffer in room.cpp)
-// ---------------------------------------------------------------------------
-byte *ega_screen = CGA_SCREENBUFFER;
byte *ega_backbuffer = backbuffer;
const byte cga_to_ega_color[] = { 0, 11, 13, 15 };
-// ---------------------------------------------------------------------------
-// Screen management
-// ---------------------------------------------------------------------------
-
-void ega_blitToScreen(int16 x, int16 y, int16 w, int16 h) {
- if (x < 0) { w += x; x = 0; }
- if (y < 0) { h += y; y = 0; }
- if (x + w > EGA_WIDTH) w = EGA_WIDTH - x;
- if (y + h > EGA_HEIGHT) h = EGA_HEIGHT - y;
- if (w <= 0 || h <= 0)
- return;
-
- g_system->copyRectToScreen(
- ega_screen + y * EGA_BYTES_PER_LINE + x,
- EGA_BYTES_PER_LINE,
- x, y, w, h);
- g_system->updateScreen();
-}
-
-// ---------------------------------------------------------------------------
-// Offset helpers
-// EGA: linear layout, no interlacing â offset = y * 320 + x
-// ---------------------------------------------------------------------------
-
-uint16 ega_CalcXY(uint16 x, uint16 y) {
- return y * EGA_BYTES_PER_LINE + x;
-}
-
-// "packed" variant: x is in 4-pixel units (matching CGA convention)
-uint16 ega_CalcXY_p(uint16 x, uint16 y) {
- return y * EGA_BYTES_PER_LINE + x * 4;
-}
-
// ---------------------------------------------------------------------------
// Memory / block blit helpers
// w is in *bytes* == *pixels* in EGA mode (1 byte per pixel)
// ---------------------------------------------------------------------------
-void ega_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
+static void ega_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
uint16 oofs = ofs;
for (uint16 y = 0; y < h; y++) {
memcpy(target + ofs, source + ofs, w);
ofs += EGA_BYTES_PER_LINE;
}
- if (target == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
-}
-
-// EGA backup image header (6 bytes):
-// [0] h (byte)
-// [1] w_cga = w_pixels / 4 (byte, CGA byte-units; avoids overflow for w <= 1020 px)
-// [2:3] ofs (uint16, linear EGA offset)
-// Pixel data follows at buffer+4, w_pixels bytes per row à h rows.
-// w is passed as pixel width (w_cga * 4). Callers from cga_BackupImage
-// already multiply by 4; callers from backupAndShowSprite pass surf->w directly.
-byte *ega_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
- *(byte *)(buffer + 0) = (byte)h;
- *(byte *)(buffer + 1) = (byte)(w >> 2); // store CGA byte-units to keep in one byte
- *(uint16 *)(buffer + 2) = ofs;
- buffer += 4;
- for (uint16 y = 0; y < h; y++) {
- memcpy(buffer, source + ofs, w);
- buffer += w;
- ofs += EGA_BYTES_PER_LINE;
- }
- return buffer;
-}
-
-void ega_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
- ega_CopyScreenBlock(ega_backbuffer, w, h, screen, ofs);
-}
-
-void ega_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- uint16 oofs = ofs;
- for (uint16 y = 0; y < h; y++) {
- for (uint16 x = 0; x < w; x++) {
- if (pixels[x] != 0)
- screen[ofs + x] = pixels[x];
- }
- pixels += pw;
- ofs += EGA_BYTES_PER_LINE;
- }
-
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
-}
-
-void ega_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
- uint16 oofs = ofs;
- for (uint16 y = 0; y < h; y++) {
- for (uint16 x = 0; x < w; x++) {
- if (pixels[w - 1 - x] != 0)
- screen[ofs + x] = pixels[w - 1 - x];
- }
- pixels += pw;
- ofs += EGA_BYTES_PER_LINE;
- }
-
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w, h);
+ if (target == SCREENBUFFER)
+ g_vm->_renderer->blitToScreen((int16)(oofs % EGA_BYTES_PER_LINE), (int16)(oofs / EGA_BYTES_PER_LINE), (int16)w, (int16)h);
}
byte ega_fond_clean[EGA_SCREEN_SIZE];
void ega_drawBackground(byte *target) {
memcpy(target, ega_fond_clean, EGA_SCREEN_SIZE);
+ if (target == SCREENBUFFER)
+ g_vm->_renderer->blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
}
Graphics::Surface *ega_loadFond(const char *filename) {
@@ -214,22 +102,36 @@ Graphics::Surface *ega_loadFond(const char *filename) {
// Implementations live directly here; no delegation to removed ega_* helpers.
// ===========================================================================
+static void setGameEGAPalette() {
+ Graphics::Palette pal = Graphics::Palette::createEGAPalette();
+ byte palData[16 * 3];
+ memcpy(palData, pal.data(), sizeof(palData));
+ /* This game remaps EGA color 8 to black (not standard dark gray) */
+ palData[8 * 3] = palData[8 * 3 + 1] = palData[8 * 3 + 2] = 0;
+ g_system->getPaletteManager()->setPalette(palData, 0, 16);
+}
+
void EGARenderer::switchToGraphicsMode() {
- g_system->getPaletteManager()->setPalette(EGA_PALETTE, 0, 16);
+ setGameEGAPalette();
}
void EGARenderer::colorSelect(byte /*csel*/) {
- g_system->getPaletteManager()->setPalette(EGA_PALETTE, 0, 16);
+ setGameEGAPalette();
}
void EGARenderer::blitToScreen(int16 x, int16 y, int16 w, int16 h) {
- ega_blitToScreen(x, y, w, h);
+ if (x < 0) { w += x; x = 0; }
+ if (y < 0) { h += y; y = 0; }
+ if (x + w > EGA_WIDTH) w = EGA_WIDTH - x;
+ if (y + h > EGA_HEIGHT) h = EGA_HEIGHT - y;
+ if (w <= 0 || h <= 0)
+ return;
+ g_system->copyRectToScreen(SCREENBUFFER + y * EGA_BYTES_PER_LINE + x, EGA_BYTES_PER_LINE, x, y, w, h);
+ g_system->updateScreen();
}
void EGARenderer::blitToScreen(int16 ofs, int16 w, int16 h) {
- int16 dy = ofs / EGA_BYTES_PER_LINE;
- int16 dx = ofs % EGA_BYTES_PER_LINE;
- ega_blitToScreen(dx, dy, w, h);
+ blitToScreen((int16)(ofs % EGA_BYTES_PER_LINE), (int16)(ofs / EGA_BYTES_PER_LINE), w, h);
}
uint16 EGARenderer::calcXY(uint16 x, uint16 y) {
@@ -241,20 +143,20 @@ uint16 EGARenderer::calcXY_p(uint16 x, uint16 y) {
}
void EGARenderer::backBufferToRealFull() {
- memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+ memcpy(SCREENBUFFER, ega_backbuffer, EGA_SCREEN_SIZE);
+ blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
}
void EGARenderer::realBufferToBackFull() {
- memcpy(ega_backbuffer, ega_screen, EGA_SCREEN_SIZE);
+ memcpy(ega_backbuffer, SCREENBUFFER, EGA_SCREEN_SIZE);
}
void EGARenderer::swapRealBackBuffer() {
static byte tmp[EGA_SCREEN_SIZE];
- memcpy(tmp, ega_screen, EGA_SCREEN_SIZE);
- memcpy(ega_screen, ega_backbuffer, EGA_SCREEN_SIZE);
+ memcpy(tmp, SCREENBUFFER, EGA_SCREEN_SIZE);
+ memcpy(SCREENBUFFER, ega_backbuffer, EGA_SCREEN_SIZE);
memcpy(ega_backbuffer, tmp, EGA_SCREEN_SIZE);
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+ blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
}
void EGARenderer::copyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) {
@@ -273,12 +175,22 @@ void EGARenderer::swapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen,
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, pw, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, pw, h);
}
byte *EGARenderer::backupImage(byte *screen, uint16 ofs, uint16 w, uint16 h, byte *buffer) {
- return ega_BackupImage(screen, ofs, w * 4, h, buffer);
+ w = w * 4;
+ *(byte *)(buffer + 0) = (byte)h;
+ *(byte *)(buffer + 1) = (byte)(w >> 2);
+ *(uint16 *)(buffer + 2) = ofs;
+ buffer += 4;
+ for (uint16 y = 0; y < h; y++) {
+ memcpy(buffer, screen + ofs, w);
+ buffer += w;
+ ofs += EGA_BYTES_PER_LINE;
+ }
+ return buffer;
}
void EGARenderer::restoreImage(byte *buffer, byte *target) {
@@ -297,7 +209,7 @@ void EGARenderer::refreshImageData(byte *buffer) {
uint16 h = *(byte *)(buffer + 0);
uint16 w = (uint16)*(byte *)(buffer + 1) * 4;
uint16 ofs = *(uint16 *)(buffer + 2);
- ega_CopyScreenBlock(ega_screen, w, h, ega_backbuffer, ofs);
+ ega_CopyScreenBlock(SCREENBUFFER, w, h, ega_backbuffer, ofs);
}
void EGARenderer::restoreBackupImage(byte *target) {
@@ -314,8 +226,8 @@ void EGARenderer::blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
void EGARenderer::blitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
@@ -333,8 +245,8 @@ void EGARenderer::fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs)
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
void EGARenderer::fillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs) {
@@ -355,8 +267,8 @@ void EGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *s
pixels += pw;
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, ega_w, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, ega_w, h);
return;
}
for (uint16 row = 0; row < h; row++) {
@@ -373,8 +285,8 @@ void EGARenderer::blitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *s
pixels += pw;
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w * 4, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w * 4, h);
}
void EGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
@@ -389,8 +301,8 @@ void EGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byt
pixels += pw;
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, ega_w, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, ega_w, h);
return;
}
for (uint16 row = 0; row < h; row++) {
@@ -408,8 +320,8 @@ void EGARenderer::blitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byt
ofs += EGA_BYTES_PER_LINE;
}
uint16 startX = (oofs % EGA_BYTES_PER_LINE) - (w * 4 - 1);
- if (screen == ega_screen)
- ega_blitToScreen(startX, oofs / EGA_BYTES_PER_LINE, w * 4, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(startX, oofs / EGA_BYTES_PER_LINE, w * 4, h);
}
void EGARenderer::blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) {
@@ -425,8 +337,8 @@ void EGARenderer::blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
void EGARenderer::blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) {
@@ -442,33 +354,33 @@ void EGARenderer::blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte
ofs += EGA_BYTES_PER_LINE;
}
- if (screen == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
+ if (screen == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, w_px, h);
}
void EGARenderer::blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) {
- ega_BlitFromBackBuffer(w * 4, h, screen, ofs);
+ ega_CopyScreenBlock(ega_backbuffer, w * 4, h, screen, ofs);
}
void EGARenderer::drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
byte egaColor = cga_to_ega_color[color & 0x03];
- uint16 ofs = ega_CalcXY(x, y);
+ uint16 ofs = calcXY(x, y);
for (uint16 i = 0; i < l; i++) {
target[ofs] = egaColor;
ofs += EGA_BYTES_PER_LINE;
}
- if (target == ega_screen)
- ega_blitToScreen(x, y, 1, l);
+ if (target == SCREENBUFFER)
+ blitToScreen(x, y, 1, l);
}
void EGARenderer::drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) {
byte egaColor = cga_to_ega_color[color & 0x03];
- uint16 ofs = ega_CalcXY(x, y);
+ uint16 ofs = calcXY(x, y);
memset(target + ofs, egaColor, l);
- if (target == ega_screen)
- ega_blitToScreen(x, y, l, 1);
+ if (target == SCREENBUFFER)
+ blitToScreen(x, y, l, 1);
}
uint16 EGARenderer::drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) {
@@ -499,15 +411,15 @@ uint16 EGARenderer::drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uin
}
uint16 totalW = (l + 2) * 4;
- if (target == ega_screen)
- ega_blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, totalW, 1);
+ if (target == SCREENBUFFER)
+ blitToScreen(oofs % EGA_BYTES_PER_LINE, oofs / EGA_BYTES_PER_LINE, totalW, 1);
return oofs + EGA_BYTES_PER_LINE;
}
void EGARenderer::printChar(byte c, byte *target) {
byte *font = carpc_data + c * g_vm->_fontHeight;
- uint16 ofs = ega_CalcXY_p(char_draw_coords_x, char_draw_coords_y);
+ uint16 ofs = calcXY_p(char_draw_coords_x, char_draw_coords_y);
for (uint16 row = 0; row < (uint16)g_vm->_fontHeight; row++) {
byte bits = char_xlat_table[*font++];
@@ -520,8 +432,8 @@ void EGARenderer::printChar(byte c, byte *target) {
char_draw_coords_x++;
- if (target == ega_screen)
- ega_blitToScreen((char_draw_coords_x - 1) * g_vm->_fontWidth,
+ if (target == SCREENBUFFER)
+ blitToScreen((char_draw_coords_x - 1) * g_vm->_fontWidth,
char_draw_coords_y,
g_vm->_fontWidth, g_vm->_fontHeight);
}
@@ -576,8 +488,8 @@ void EGARenderer::traceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *so
if (e2 > -abh) { err -= abh; x0 += ddx; }
if (e2 < abw) { err += abw; y0 += ddy; }
}
- if (target == ega_screen)
- ega_blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
+ if (target == SCREENBUFFER)
+ blitToScreen(0, 0, EGA_WIDTH, EGA_HEIGHT);
}
void EGARenderer::zoomImage(byte *pixels, byte w, byte h, byte /*nw*/, byte /*nh*/, byte *target, uint16 ofs) {
@@ -589,7 +501,51 @@ void EGARenderer::animZoomIn(byte *pixels, byte w, byte h, byte *target, uint16
}
void EGARenderer::zoomInplaceXY(byte *pixels, byte w, byte h, byte /*nw*/, byte /*nh*/, uint16 x, uint16 y, byte *target) {
- blit(pixels, w, w, h, target, ega_CalcXY_p(x, y));
+ blit(pixels, w, w, h, target, calcXY_p(x, y));
+}
+
+void EGARenderer::drawSprite(byte *sprite, byte *screen, uint16 ofs) {
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
+ blitSprite((byte *)surf->getPixels(), surf->pitch, surf->w / 4, surf->h, screen, ofs);
+}
+
+void EGARenderer::drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) {
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
+ blitSpriteFlip((byte *)surf->getPixels(), surf->pitch, surf->w / 4, surf->h, screen, ofs);
+}
+
+byte *EGARenderer::loadSprit(byte index) {
+ return reinterpret_cast<byte *>(ega_sprit_res->getSprite(index));
+}
+
+byte *EGARenderer::loadPersSprit(byte index) {
+ return reinterpret_cast<byte *>(ega_perso_res->getSprite(index));
+}
+
+void EGARenderer::backupAndShowSprite(byte index, byte x, byte y) {
+ byte *sprite = loadSprit(index);
+ uint16 ofs = calcXY_p(x, y);
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(sprite);
+ backupImage(SCREENBUFFER, ofs, surf->w / 4, surf->h, scratch_mem2);
+ drawSprite(sprite, SCREENBUFFER, ofs);
+}
+
+void EGARenderer::animLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) {
+ uint16 i;
+ uint16 epw = pw * 4;
+ pixels += epw * (h - 1);
+ for (i = 1; i <= h; i++) {
+ blitAndWait(pixels, pw, w, i, screen, ofs);
+ pixels -= epw;
+ }
+}
+
+void EGARenderer::animLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) {
+ uint16 i;
+ for (i = 1; i <= h; i++) {
+ blitAndWait(pixels, pw, w, i, screen, calcXY_p(x, y));
+ y -= 1;
+ }
}
} // End of namespace Chamber
diff --git a/engines/chamber/ega.h b/engines/chamber/ega.h
index 37aaf351e5e..9d3d7f5050a 100644
--- a/engines/chamber/ega.h
+++ b/engines/chamber/ega.h
@@ -37,57 +37,11 @@ namespace Chamber {
// Planar background: 4 planes à 8000 bytes
#define EGA_PLANAR_SIZE (EGA_WIDTH / 8 * EGA_HEIGHT) // 8000 bytes per plane
-extern byte *ega_screen; // aliases CGA_SCREENBUFFER (frontbuffer)
extern byte *ega_backbuffer; // aliases backbuffer
-// Standard EGA 16-color palette (RGB, used for screen and cursor)
-extern const byte EGA_PALETTE[16 * 3];
-
// CGA palette 1 high-intensity â EGA color index mapping
extern const byte cga_to_ega_color[4];
-// --- screen management ---
-void ega_switchToGraphicsMode();
-void ega_blitToScreen(int16 x, int16 y, int16 w, int16 h);
-void ega_BackBufferToRealFull();
-void ega_RealBufferToBackFull();
-void ega_SwapRealBackBuffer();
-
-// --- offset helpers ---
-uint16 ega_CalcXY(uint16 x, uint16 y);
-uint16 ega_CalcXY_p(uint16 x, uint16 y);
-
-// --- memory / blit ---
-void ega_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
-void ega_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
-byte *ega_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer);
-void ega_RestoreImage(byte *buffer, byte *target);
-void ega_RefreshImageData(byte *buffer);
-void ega_RestoreBackupImage(byte *target);
-
-void ega_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void ega_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void ega_Fill(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void ega_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
-void ega_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs);
-
-// --- sprite blitters ---
-// EGA sprites are decoded to CLUT8 (1 byte/pixel); pixel 0 = transparent
-void ega_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void ega_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
-void ega_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask);
-
-void ega_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs);
-
-// --- draw primitives ---
-void ega_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
-void ega_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
-uint16 ega_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs);
-
-void ega_PrintChar(byte c, byte *target);
-
// --- resource loader ---
Graphics::Surface *ega_loadFond(const char *filename);
diff --git a/engines/chamber/input.cpp b/engines/chamber/input.cpp
index 714dbf58a4d..13fc7a2c822 100644
--- a/engines/chamber/input.cpp
+++ b/engines/chamber/input.cpp
@@ -189,7 +189,7 @@ int16 askQuitGame(void) {
}
}
}
- g_vm->_renderer->copyScreenBlock(backbuffer, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, frontbuffer, CalcXY_p(draw_x, draw_y));
+ g_vm->_renderer->copyScreenBlock(backbuffer, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, frontbuffer, g_vm->_renderer->calcXY_p(draw_x, draw_y));
keymapper->getKeymap("quit-dialog")->setEnabled(false);
keymapper->getKeymap("chamber-default")->setEnabled(true);
diff --git a/engines/chamber/invent.cpp b/engines/chamber/invent.cpp
index 9fea7ba147a..c44785a8cc4 100644
--- a/engines/chamber/invent.cpp
+++ b/engines/chamber/invent.cpp
@@ -79,13 +79,13 @@ void drawInventoryBox(uint16 filtermask, uint16 filtervalue) {
continue;
if (count == 0) {
/*once first valid item found, draw the box*/
- g_vm->_renderer->fillAndWait(inv_bgcolor, 64 / 4, 64, CGA_SCREENBUFFER, CalcXY_p(232 / 4, 56));
+ g_vm->_renderer->fillAndWait(inv_bgcolor, 64 / 4, 64, SCREENBUFFER, g_vm->_renderer->calcXY_p(232 / 4, 56));
playSound(20);
}
inventory_spots[count].name = inventory_items[i].name;
inventory_spots[count].command = inventory_items[i].command;
inventory_spots[count].itemidx = i + 1;
- drawSpriteN(inventory_items[i].sprite, inventory_spots[count].sx, inventory_spots[count].sy, CGA_SCREENBUFFER);
+ drawSpriteN(inventory_items[i].sprite, inventory_spots[count].sx, inventory_spots[count].sy, SCREENBUFFER);
count++;
}
inv_count = count;
@@ -111,10 +111,10 @@ void checkInventoryItemHover(byte count) {
void openInventory(uint16 filtermask, uint16 filtervalue) {
the_command = 0;
- cga_BackupImageReal(CalcXY_p(232 / 4, 56), 64 / 4, 64);
+ cga_BackupImageReal(g_vm->_renderer->calcXY_p(232 / 4, 56), 64 / 4, 64);
drawInventoryBox(filtermask, filtervalue);
if (inv_count != 0) {
- selectCursor(CURSOR_FINGER);
+ g_vm->_renderer->selectCursor(CURSOR_FINGER);
processInput();
do {
pollInput();
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index f13856d3d87..eef6b1ed4f4 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -143,11 +143,11 @@ void gameLoop(byte *target) {
the_command = 0;
if (isCursorInRect(&room_bounds_rect)) {
- selectCursor(CURSOR_TARGET);
+ g_vm->_renderer->selectCursor(CURSOR_TARGET);
command_hint = 100;
selectSpotCursor();
} else {
- selectCursor(CURSOR_FINGER);
+ g_vm->_renderer->selectCursor(CURSOR_FINGER);
object_hint = 117;
checkMenuCommandHover();
}
diff --git a/engines/chamber/menu.cpp b/engines/chamber/menu.cpp
index 85653292fd3..efff10a0273 100644
--- a/engines/chamber/menu.cpp
+++ b/engines/chamber/menu.cpp
@@ -109,7 +109,7 @@ void actionsMenu(byte **pinfo) {
y = act_menu_y;
/*menu sprite*/
- backupAndShowSprite(0, x, y);
+ g_vm->_renderer->backupAndShowSprite(0, x, y);
playSound(18);
choices = *((*pinfo)++);
@@ -131,9 +131,9 @@ void actionsMenu(byte **pinfo) {
act_dot_rects_end = act_dot_rects + numchoices + 1;
for (i = 0; i < numchoices; i++)
- drawSpriteN(1, act_dot_rects[i].sx, act_dot_rects[i].sy, CGA_SCREENBUFFER);
+ drawSpriteN(1, act_dot_rects[i].sx, act_dot_rects[i].sy, SCREENBUFFER);
- selectCursor(CURSOR_FINGER);
+ g_vm->_renderer->selectCursor(CURSOR_FINGER);
processInput();
choice = 0;
@@ -157,23 +157,23 @@ void actionsMenu(byte **pinfo) {
if (command_hint != last_command_hint)
drawCommandHint(); /*to backbuffer*/
- drawHintsAndCursor(CGA_SCREENBUFFER);
+ drawHintsAndCursor(SCREENBUFFER);
} while (buttons == 0);
- undrawCursor(CGA_SCREENBUFFER);
+ undrawCursor(SCREENBUFFER);
if (the_command != 0xFFFF) {
playSound(19);
waitVBlank();
/*draw dot explosion animation*/
- drawSpriteN(24, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
+ drawSpriteN(24, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
- drawSpriteN(2, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
+ drawSpriteN(2, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
- drawSpriteN(25, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
+ drawSpriteN(25, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
}
- g_vm->_renderer->restoreBackupImage(CGA_SCREENBUFFER);
+ g_vm->_renderer->restoreBackupImage(SCREENBUFFER);
*pinfo += numchoices * 3;
}
@@ -192,7 +192,7 @@ void menuLoop(byte spotmask, byte spotvalue) {
}
void processMenu(void) {
- selectCursor(CURSOR_BODY);
+ g_vm->_renderer->selectCursor(CURSOR_BODY);
menuLoop(SPOTFLG_80 | SPOTFLG_20 | SPOTFLG_10 | SPOTFLG_8, SPOTFLG_80 | SPOTFLG_10);
}
diff --git a/engines/chamber/module.mk b/engines/chamber/module.mk
index b319bbdf63e..bb54a94e06a 100644
--- a/engines/chamber/module.mk
+++ b/engines/chamber/module.mk
@@ -5,11 +5,11 @@ MODULE_OBJS := \
bkbuff.o \
cga.o \
chamber.o \
- ega.o \
- ega_resource.o \
cursor.o \
decompr.o \
dialog.o \
+ ega.o \
+ ega_resource.o \
ifgm.o \
input.o \
invent.o \
diff --git a/engines/chamber/portrait.cpp b/engines/chamber/portrait.cpp
index ed1111c82a1..8e56711ffc1 100644
--- a/engines/chamber/portrait.cpp
+++ b/engines/chamber/portrait.cpp
@@ -27,6 +27,7 @@
#include "chamber/room.h"
#include "chamber/cga.h"
#include "chamber/ega.h"
+#include "chamber/renderer.h"
#include "chamber/ega_resource.h"
#include "chamber/script.h"
#include "chamber/dialog.h"
@@ -141,7 +142,7 @@ byte *loadPortrait(byte **pinfo, byte *end) {
buffer = sprit_load_buffer + 2 + 2 + (flags & 0x3FFF);
pitch = cur_frame_width;
- sprite = loadPersSprit(index);
+ sprite = g_vm->_renderer->loadPersSprit(index);
sprw = *sprite++;
sprh = *sprite++;
@@ -238,17 +239,20 @@ static byte *ega_loadPortrait(byte **pinfo, byte *end) {
return sprit_load_buffer + 2;
}
-byte *loadPortraitWithFrame(byte index) {
+byte *CGARenderer::loadPortraitWithFrame(byte index) {
byte *pinfo, *end;
pinfo = seekToEntry(icone_data, index, &end);
- if (g_vm->_videoMode == Common::kRenderEGA) {
- ega_makePortraitFrame(*pinfo++, sprit_load_buffer + 2);
- return ega_loadPortrait(&pinfo, end);
- }
makePortraitFrame(*pinfo++, sprit_load_buffer + 2);
return loadPortrait(&pinfo, end);
}
+byte *EGARenderer::loadPortraitWithFrame(byte index) {
+ byte *pinfo, *end;
+ pinfo = seekToEntry(icone_data, index, &end);
+ ega_makePortraitFrame(*pinfo++, sprit_load_buffer + 2);
+ return ega_loadPortrait(&pinfo, end);
+}
+
#define STATIC_ANIMS_MAX 24
@@ -333,10 +337,10 @@ void drawBoxAroundSpot(void) {
w *= g_vm->_screenPPB;
}
- g_vm->_renderer->drawVLine(x, y, h - 1, 0, CGA_SCREENBUFFER);
- g_vm->_renderer->drawHLine(x, y, w - 1, 0, CGA_SCREENBUFFER);
- g_vm->_renderer->drawVLine(x + w - 1, y, h - 1, 0, CGA_SCREENBUFFER);
- g_vm->_renderer->drawHLine(x, y + h - 1, w - 1, 0, CGA_SCREENBUFFER);
+ g_vm->_renderer->drawVLine(x, y, h - 1, 0, SCREENBUFFER);
+ g_vm->_renderer->drawHLine(x, y, w - 1, 0, SCREENBUFFER);
+ g_vm->_renderer->drawVLine(x + w - 1, y, h - 1, 0, SCREENBUFFER);
+ g_vm->_renderer->drawHLine(x, y + h - 1, w - 1, 0, SCREENBUFFER);
g_vm->_renderer->refreshImageData(*spot_sprite);
}
@@ -363,11 +367,11 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
cur_image_coords_x = xx;
cur_image_coords_y = yy;
cur_image_idx = index;
- image = loadPortraitWithFrame(index - 1);
+ image = g_vm->_renderer->loadPortraitWithFrame(index - 1);
cur_image_size_h = *image++;
cur_image_size_w = *image++;
cur_image_pixels = image;
- cur_image_offs = CalcXY_p(cur_image_coords_x, cur_image_coords_y);
+ cur_image_offs = g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y);
addDirtyRect(DirtyRectSprite, cur_image_coords_x, cur_image_coords_y, cur_image_size_w, cur_image_size_h, cur_image_offs);
/*TODO: remove and use only globals?*/
@@ -377,7 +381,7 @@ int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
*height = cur_image_size_h;
if (right_button) {
- g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, SCREENBUFFER, cur_image_offs);
return 0;
}
@@ -441,7 +445,7 @@ void animPortrait(byte layer, byte index, byte delay) {
uint16 offs;
byte portrait = *ani++;
- loadPortraitWithFrame(portrait - 1);
+ g_vm->_renderer->loadPortraitWithFrame(portrait - 1);
if (*ani == 0xFF) {
ani++;
if (g_vm->_videoMode == Common::kRenderEGA)
@@ -451,7 +455,7 @@ void animPortrait(byte layer, byte index, byte delay) {
}
getDirtyRectAndSetSprite(layer, &kind, &x, &y, &width, &height, &offs);
waitVBlank();
- g_vm->_renderer->blitAndWait(cur_image_pixels, width, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, width, width, height, SCREENBUFFER, offs);
waitVBlankTimer();
if (delay) {
if (ani[-1] == 37) { /*TODO: what is it?*/
diff --git a/engines/chamber/print.cpp b/engines/chamber/print.cpp
index 168d1e73a1d..e16ce3484e5 100644
--- a/engines/chamber/print.cpp
+++ b/engines/chamber/print.cpp
@@ -257,7 +257,7 @@ void drawMessage(byte *msg, byte *target) {
draw_x = x;
draw_y = y;
- cga_BackupImageReal(CalcXY_p(x, y), char_draw_max_width + 2, char_draw_max_height); /*backup orig. screen data*/
+ cga_BackupImageReal(g_vm->_renderer->calcXY_p(x, y), char_draw_max_width + 2, char_draw_max_height); /*backup orig. screen data*/
cga_DrawTextBox(msg, target); /*draw box with text*/
promptWait(); /*wait keypress*/
g_vm->_renderer->restoreBackupImage(target); /*restore screen data*/
diff --git a/engines/chamber/renderer.h b/engines/chamber/renderer.h
index 993130a5588..3c8fbb2d17d 100644
--- a/engines/chamber/renderer.h
+++ b/engines/chamber/renderer.h
@@ -32,6 +32,7 @@ public:
virtual void switchToGraphicsMode() = 0;
virtual void colorSelect(byte csel) = 0;
+ virtual void selectCursor(uint16 num) = 0;
virtual void blitToScreen(int16 x, int16 y, int16 w, int16 h) = 0;
virtual void blitToScreen(int16 ofs, int16 w, int16 h) = 0;
@@ -59,6 +60,12 @@ public:
virtual void blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) = 0;
virtual void blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
virtual void blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) = 0;
+ virtual void drawSprite(byte *sprite, byte *screen, uint16 ofs) = 0;
+ virtual void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) = 0;
+ virtual byte *loadSprit(byte index) = 0;
+ virtual byte *loadPersSprit(byte index) = 0;
+ virtual void backupAndShowSprite(byte index, byte x, byte y) = 0;
+ virtual byte *loadPortraitWithFrame(byte index) = 0;
virtual void drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) = 0;
virtual void drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) = 0;
@@ -67,6 +74,8 @@ public:
virtual void animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
virtual void animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void animLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) = 0;
+ virtual void animLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) = 0;
virtual void hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
virtual void hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) = 0;
@@ -85,6 +94,7 @@ class CGARenderer : public Renderer {
public:
void switchToGraphicsMode() override;
void colorSelect(byte csel) override;
+ void selectCursor(uint16 num) override;
void blitToScreen(int16 x, int16 y, int16 w, int16 h) override;
void blitToScreen(int16 ofs, int16 w, int16 h) override;
uint16 calcXY(uint16 x, uint16 y) override;
@@ -107,12 +117,20 @@ public:
void blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) override;
void blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
void blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) override;
+ void drawSprite(byte *sprite, byte *screen, uint16 ofs) override;
+ void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) override;
+ byte *loadSprit(byte index) override;
+ byte *loadPersSprit(byte index) override;
+ void backupAndShowSprite(byte index, byte x, byte y) override;
+ byte *loadPortraitWithFrame(byte index) override;
void drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
void drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
uint16 drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) override;
void printChar(byte c, byte *target) override;
void animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
void animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void animLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void animLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) override;
void hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
void hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
void hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
@@ -128,6 +146,7 @@ class EGARenderer : public Renderer {
public:
void switchToGraphicsMode() override;
void colorSelect(byte csel) override;
+ void selectCursor(uint16 num) override;
void blitToScreen(int16 x, int16 y, int16 w, int16 h) override;
void blitToScreen(int16 ofs, int16 w, int16 h) override;
uint16 calcXY(uint16 x, uint16 y) override;
@@ -150,12 +169,20 @@ public:
void blitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask) override;
void blitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
void blitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs) override;
+ void drawSprite(byte *sprite, byte *screen, uint16 ofs) override;
+ void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs) override;
+ byte *loadSprit(byte index) override;
+ byte *loadPersSprit(byte index) override;
+ void backupAndShowSprite(byte index, byte x, byte y) override;
+ byte *loadPortraitWithFrame(byte index) override;
void drawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
void drawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target) override;
uint16 drawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs) override;
void printChar(byte c, byte *target) override;
void animLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
void animLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void animLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs) override;
+ void animLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y) override;
void hideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
void hideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
void hideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs) override;
diff --git a/engines/chamber/resdata.h b/engines/chamber/resdata.h
index bd3992fd26c..75b3d527f6c 100644
--- a/engines/chamber/resdata.h
+++ b/engines/chamber/resdata.h
@@ -27,7 +27,7 @@
namespace Chamber {
typedef struct ResEntry_t {
- char name[16];
+ char name[8 + 1 + 3 + 1];
void *buffer;
} ResEntry_t;
diff --git a/engines/chamber/room.cpp b/engines/chamber/room.cpp
index 6e9cc7970ab..7c1e341b55f 100644
--- a/engines/chamber/room.cpp
+++ b/engines/chamber/room.cpp
@@ -479,7 +479,7 @@ void initRoomDoorInfo(byte index) {
info->layer[i].width = w;
info->layer[i].height = h;
info->layer[i].pixels = (byte *)surf->getPixels();
- info->layer[i].offs = CalcXY_p(ox, y);
+ info->layer[i].offs = g_vm->_renderer->calcXY_p(ox, y);
aptr += 3;
}
@@ -516,7 +516,7 @@ void initRoomDoorInfo(byte index) {
info->layer[i].width = w;
info->layer[i].height = h;
info->layer[i].pixels = sprite + 2;
- info->layer[i].offs = CalcXY_p(x, y);
+ info->layer[i].offs = g_vm->_renderer->calcXY_p(x, y);
aptr += 3;
}
@@ -524,7 +524,7 @@ void initRoomDoorInfo(byte index) {
info->width = bounds.ex - bounds.sx;
info->height = bounds.ey - bounds.sy;
- info->offs = CalcXY_p(bounds.sx, bounds.sy);
+ info->offs = g_vm->_renderer->calcXY_p(bounds.sx, bounds.sy);
}
/*
@@ -849,11 +849,11 @@ void drawRoomStaticObject(byte *aptr, byte *rx, byte *ry, byte *rw, byte *rh) {
arpla_y_step >>= 1;
}
- uint16 ofs = CalcXY_p(drawx, y);
+ uint16 ofs = g_vm->_renderer->calcXY_p(drawx, y);
if (aptr[1] & 0x80)
- ega_BlitSpriteFlip(pixels, pitch, w, h, backbuffer, ofs);
+ g_vm->_renderer->blitSpriteFlip(pixels, pitch, wcga, h, backbuffer, ofs);
else
- ega_BlitSprite(pixels, pitch, w, h, backbuffer, ofs);
+ g_vm->_renderer->blitSprite(pixels, pitch, wcga, h, backbuffer, ofs);
return;
}
@@ -896,9 +896,9 @@ void drawRoomStaticObject(byte *aptr, byte *rx, byte *ry, byte *rw, byte *rh) {
/*TODO: check if this results in any glitches in Who Will Be Saved*/
if (aptr[1] & 0x80)
- g_vm->_renderer->blitSpriteFlip(sprite, pitch, w, h, backbuffer, CalcXY_p(x, y));
+ g_vm->_renderer->blitSpriteFlip(sprite, pitch, w, h, backbuffer, g_vm->_renderer->calcXY_p(x, y));
else
- g_vm->_renderer->blitSprite(sprite, pitch, w, h, backbuffer, CalcXY_p(x, y));
+ g_vm->_renderer->blitSprite(sprite, pitch, w, h, backbuffer, g_vm->_renderer->calcXY_p(x, y));
}
/*
@@ -999,7 +999,7 @@ void drawRoomItemsIndicator(void) {
break;
}
}
- drawSpriteN(spridx, 296 / 4, 14, CGA_SCREENBUFFER);
+ drawSpriteN(spridx, 296 / 4, 14, SCREENBUFFER);
drawSpriteN(spridx, 296 / 4, 14, backbuffer);
/*recalculate the number of zapstiks we have*/
@@ -1041,7 +1041,7 @@ void refreshZone(void) {
popDirtyRects(DirtyRectText);
if (!skip_zone_transition && !right_button)
- drawBackground(CGA_SCREENBUFFER, 1);
+ drawBackground(SCREENBUFFER, 1);
g_vm->_renderer->backBufferToRealFull();
@@ -1087,7 +1087,7 @@ Copy object hint from backbuffer to screen
void showObjectHint(byte *target) {
if (script_byte_vars.zone_index == 135)
return;
- g_vm->_renderer->copyScreenBlock(backbuffer, room_hint_bar_width + 2, 9, target, CalcXY_p(room_hint_bar_coords_x - 1, room_hint_bar_coords_y - 2));
+ g_vm->_renderer->copyScreenBlock(backbuffer, room_hint_bar_width + 2, 9, target, g_vm->_renderer->calcXY_p(room_hint_bar_coords_x - 1, room_hint_bar_coords_y - 2));
}
/*
@@ -1105,7 +1105,7 @@ void drawCommandHint(void) {
Copy command hint from backbuffer to screen
*/
void showCommandHint(byte *target) {
- g_vm->_renderer->copyScreenBlock(backbuffer, cmd_hint_bar_width + 2, 9, target, CalcXY_p(cmd_hint_bar_coords_x - 1, cmd_hint_bar_coords_y - 2));
+ g_vm->_renderer->copyScreenBlock(backbuffer, cmd_hint_bar_width + 2, 9, target, g_vm->_renderer->calcXY_p(cmd_hint_bar_coords_x - 1, cmd_hint_bar_coords_y - 2));
}
void loadLutinSprite(uint16 lutidx) {
@@ -1129,7 +1129,7 @@ void loadLutinSprite(uint16 lutidx) {
uint16 flags = *lutin_entry++;
flags |= (*lutin_entry++) << 8;
- Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(loadSprit(spridx));
+ Graphics::Surface *surf = reinterpret_cast<Graphics::Surface *>(g_vm->_renderer->loadSprit(spridx));
byte *src = (byte *)surf->getPixels();
uint16 sw = surf->w;
uint16 sh = surf->h;
@@ -1178,7 +1178,7 @@ void loadLutinSprite(uint16 lutidx) {
uint16 flags = *lutin_entry++;
flags |= (*lutin_entry++) << 8;
- byte *sprite = loadSprit(spridx);
+ byte *sprite = g_vm->_renderer->loadSprit(spridx);
byte sprw = *sprite++;
byte sprh = *sprite++;
@@ -1208,11 +1208,11 @@ static void egaDrawLutinComposite(uint16 lutidx, byte *target, uint16 baseOfs) {
uint16 yy = w ? (byteOfs / w) : 0;
uint16 xxBytes = w ? (byteOfs % w) : 0;
uint16 subOfs = baseOfs + yy * EGA_BYTES_PER_LINE + xxBytes * 4;
- byte *sprite = loadSprit(sub);
+ byte *sprite = g_vm->_renderer->loadSprit(sub);
if (flags & 0x8000)
- drawSpriteFlip(sprite, target, subOfs);
+ g_vm->_renderer->drawSpriteFlip(sprite, target, subOfs);
else
- drawSprite(sprite, target, subOfs);
+ g_vm->_renderer->drawSprite(sprite, target, subOfs);
}
}
@@ -1221,14 +1221,14 @@ Draw specific room's person idle sprite
*/
void drawCharacterSprite(byte spridx, byte x, byte y, byte *target) {
if (g_vm->_videoMode == Common::kRenderEGA) {
- egaDrawLutinComposite(spridx, target, CalcXY_p(x, y));
+ egaDrawLutinComposite(spridx, target, g_vm->_renderer->calcXY_p(x, y));
return;
}
lutin_mem = scratch_mem2;
loadLutinSprite(spridx);
- drawSprite(scratch_mem2, target, CalcXY_p(x, y));
+ g_vm->_renderer->drawSprite(scratch_mem2, target, g_vm->_renderer->calcXY_p(x, y));
}
/*
@@ -1245,7 +1245,7 @@ char drawZoneAniSprite(rect_t *rect, uint16 index, byte *target) {
spridx = la->sprites[la->phase];
la->phase = (la->phase + 1) % 8;
- zsprite_draw_ofs = CalcXY_p(rect->sx, rect->sy);
+ zsprite_draw_ofs = g_vm->_renderer->calcXY_p(rect->sx, rect->sy);
if (g_vm->_videoMode == Common::kRenderEGA) {
byte *entry, *entry_end;
@@ -1263,7 +1263,7 @@ char drawZoneAniSprite(rect_t *rect, uint16 index, byte *target) {
zsprite_w = scratch_mem2[0];
zsprite_h = scratch_mem2[1];
- drawSprite(scratch_mem2, target, zsprite_draw_ofs);
+ g_vm->_renderer->drawSprite(scratch_mem2, target, zsprite_draw_ofs);
return ~0;
}
@@ -1480,7 +1480,7 @@ uint16 getPuzzlSprite(byte index, byte x, byte y, uint16 *w, uint16 *h, uint16 *
Graphics::Surface *surf = ega_puzzl_res->getSprite(index);
*w = surf->w / 4;
*h = surf->h;
- *ofs = CalcXY_p(x, y);
+ *ofs = g_vm->_renderer->calcXY_p(x, y);
/*copy EGA pixel data into scratch_mem2+2 for blitScratchBackSprite*/
byte *dst = scratch_mem2 + 2;
for (int row = 0; row < surf->h; row++) {
@@ -1492,7 +1492,7 @@ uint16 getPuzzlSprite(byte index, byte x, byte y, uint16 *w, uint16 *h, uint16 *
byte *spr = loadPuzzlToScratch(index);
*w = spr[0];
*h = spr[1];
- *ofs = CalcXY_p(x, y);
+ *ofs = g_vm->_renderer->calcXY_p(x, y);
return 0; /*sprite offset in scratch buf*/
}
@@ -1652,10 +1652,10 @@ Open The Wall's right gate
TODO: move this to CGA?
*/
void theWallOpenRightDoor(byte x, byte y, byte width, byte height, byte limit) {
- uint16 offs = CalcXY_p(x + width - 2, y);
+ uint16 offs = g_vm->_renderer->calcXY_p(x + width - 2, y);
while (--width) {
- g_vm->_renderer->hideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToRight(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
if (width == limit)
return;
}
@@ -1681,10 +1681,10 @@ Open The Wall's left gate
TODO: move this to CGA?
*/
void theWallOpenLeftDoor(byte x, byte y, byte width, byte height, byte limit) {
- uint16 offs = CalcXY_p(x + 1, y);
+ uint16 offs = g_vm->_renderer->calcXY_p(x + 1, y);
while (--width) {
- g_vm->_renderer->hideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToLeft(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
if (width == limit)
return;
}
@@ -1752,11 +1752,11 @@ void theWallPhase1_DoorClose1(void) {
else
spr += cur_frame_width - 1;
cur_image_coords_x = 64 / 4;
- g_vm->_renderer->animLiftToRight(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToRight(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y));
spr = loadMursmSprite(1);
cur_image_coords_x = 220 / 4;
- g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1, cur_image_size_h, frontbuffer, g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y));
IFGM_StopSample();
@@ -1780,16 +1780,16 @@ void theWallPhase2_DoorClose2(void) {
spr += cur_frame_width - 1;
cur_image_coords_x = 64 / 4;
if (g_vm->_videoMode == Common::kRenderEGA)
- g_vm->_renderer->animLiftToRight(10, spr - 40, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToRight(10, spr - 40, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y));
else
- g_vm->_renderer->animLiftToRight(10, spr - 10, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y));
+ g_vm->_renderer->animLiftToRight(10, spr - 10, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y));
spr = loadMursmSprite(1);
cur_image_coords_x = 220 / 4;
if (g_vm->_videoMode == Common::kRenderEGA)
- g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 40);
+ g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y) - 40);
else
- g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, CalcXY_p(cur_image_coords_x, cur_image_coords_y) - 10);
+ g_vm->_renderer->animLiftToLeft(10, spr, cur_frame_width, 1 + 10, cur_image_size_h, frontbuffer, g_vm->_renderer->calcXY_p(cur_image_coords_x, cur_image_coords_y) - 10);
IFGM_PlaySample(30);
@@ -1805,26 +1805,26 @@ void drawTheWallDoors(void) {
case 102:
if (g_vm->_videoMode == Common::kRenderEGA) {
/* EGA buffer is 80 px wide; CGA +10 bytes = 40 EGA pixels */
- g_vm->_renderer->blit(loadMursmSprite(0) + 40, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(0) + 40, 20, 10, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(64 / 4, 32));
if (g_vm->getLanguage() == Common::EN_USA) {
- g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(184 / 4, 32));
} else {
- g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(180 / 4, 32));
}
} else {
- g_vm->_renderer->blit(loadMursmSprite(0) + 10, 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(0) + 10, 20, 10, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(64 / 4, 32));
if (g_vm->getLanguage() == Common::EN_USA) {
/*This fixes odd black patch on the right gate door*/
- g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(184 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(184 / 4, 32));
} else {
- g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, CGA_SCREENBUFFER, CalcXY_p(180 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1) , 20, 10, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(180 / 4, 32));
}
}
break;
case 95:
case 103:
- g_vm->_renderer->blit(loadMursmSprite(0), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(64 / 4, 32));
- g_vm->_renderer->blit(loadMursmSprite(1), 20, 20, 59, CGA_SCREENBUFFER, CalcXY_p(144 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(0), 20, 20, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(64 / 4, 32));
+ g_vm->_renderer->blit(loadMursmSprite(1), 20, 20, 59, SCREENBUFFER, g_vm->_renderer->calcXY_p(144 / 4, 32));
break;
}
}
@@ -1871,7 +1871,7 @@ Return current and next free buffer ptr
*/
byte *backupSpotImage(spot_t *spot, byte **spotback, byte *buffer) {
*spotback = buffer;
- buffer = g_vm->_renderer->backupImage(backbuffer, CalcXY_p(spot->sx, spot->sy), spot->ex - spot->sx, spot->ey - spot->sy, buffer);
+ buffer = g_vm->_renderer->backupImage(backbuffer, g_vm->_renderer->calcXY_p(spot->sx, spot->sy), spot->ex - spot->sx, spot->ey - spot->sy, buffer);
return buffer;
}
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 75c44de5295..6e0ddd59358 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -672,9 +672,9 @@ uint16 SCR_5_DrawPortraitLiftRight(void) {
/*TODO: use local args instead of globals*/
if (g_vm->_videoMode == Common::kRenderEGA)
- g_vm->_renderer->animLiftToRight(width, cur_image_pixels + width * 4 - 4, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
+ g_vm->_renderer->animLiftToRight(width, cur_image_pixels + width * 4 - 4, width, 1, height, SCREENBUFFER, g_vm->_renderer->calcXY_p(x, y));
else
- g_vm->_renderer->animLiftToRight(width, cur_image_pixels + width - 1, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x, y));
+ g_vm->_renderer->animLiftToRight(width, cur_image_pixels + width - 1, width, 1, height, SCREENBUFFER, g_vm->_renderer->calcXY_p(x, y));
return 0;
}
@@ -690,7 +690,7 @@ uint16 SCR_6_DrawPortraitLiftLeft(void) {
return 0;
/*TODO: use local args instead of globals*/
- g_vm->_renderer->animLiftToLeft(width, cur_image_pixels, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x + width - 1, y));
+ g_vm->_renderer->animLiftToLeft(width, cur_image_pixels, width, 1, height, SCREENBUFFER, g_vm->_renderer->calcXY_p(x + width - 1, y));
return 0;
}
@@ -706,7 +706,7 @@ uint16 SCR_7_DrawPortraitLiftDown(void) {
return 0;
/*TODO: use local args instead of globals*/
- cga_AnimLiftToDown(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->animLiftToDown(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, SCREENBUFFER, cur_image_offs);
return 0;
}
@@ -722,7 +722,7 @@ uint16 SCR_8_DrawPortraitLiftUp(void) {
return 0;
/*TODO: use local args instead of globals*/
- cga_AnimLiftToUp(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, x, y + height - 1);
+ g_vm->_renderer->animLiftToUp(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, SCREENBUFFER, x, y + height - 1);
return 0;
}
@@ -737,7 +737,7 @@ uint16 SCR_9_DrawPortrait(void) {
if (!drawPortrait(&script_ptr, &x, &y, &width, &height))
return 0;
- g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, SCREENBUFFER, cur_image_offs);
return 0;
}
@@ -794,7 +794,7 @@ uint16 SCR_B_DrawPortraitTwistEffect(void) {
if (!drawPortrait(&script_ptr, &x, &y, &width, &height))
return 0;
- offs = CalcXY_p(x, y);
+ offs = g_vm->_renderer->calcXY_p(x, y);
g_vm->_renderer->swapScreenRect(cur_image_pixels, width, height, backbuffer, offs);
twistDraw(x, y, width, height, backbuffer, frontbuffer);
@@ -845,7 +845,7 @@ uint16 SCR_C_DrawPortraitArcEffect(void) {
if (!drawPortrait(&script_ptr, &x, &y, &width, &height))
return 0;
- offs = CalcXY_p(x, y);
+ offs = g_vm->_renderer->calcXY_p(x, y);
g_vm->_renderer->swapScreenRect(cur_image_pixels, width, height, backbuffer, offs);
arcDraw(x, y, width, height, backbuffer, frontbuffer);
@@ -861,7 +861,7 @@ uint16 SCR_D_DrawPortraitDotEffect(void) {
//int16 i;
byte x, y, width, height;
uint16 offs, step = 17;
- byte *target = CGA_SCREENBUFFER;
+ byte *target = SCREENBUFFER;
script_ptr++;
@@ -871,7 +871,7 @@ uint16 SCR_D_DrawPortraitDotEffect(void) {
if (g_vm->_videoMode == Common::kRenderEGA) {
uint16 pw = width * 4;
cur_image_end = pw * height;
- uint16 baseOfs = ega_CalcXY_p(x, y);
+ uint16 baseOfs = g_vm->_renderer->calcXY_p(x, y);
int16 count = 0;
for (offs = 0; offs != cur_image_end;) {
uint16 px = offs % pw;
@@ -879,14 +879,14 @@ uint16 SCR_D_DrawPortraitDotEffect(void) {
target[baseOfs + py * EGA_BYTES_PER_LINE + px] = cur_image_pixels[offs];
if (count % 20 == 0)
- ega_blitToScreen(x * 4, y, pw, height);
+ g_vm->_renderer->blitToScreen(x * 4, y, pw, height);
offs += step;
if (offs > cur_image_end)
offs -= cur_image_end;
count++;
}
- ega_blitToScreen(x * 4, y, pw, height);
+ g_vm->_renderer->blitToScreen(x * 4, y, pw, height);
return 0;
}
@@ -901,7 +901,7 @@ uint16 SCR_D_DrawPortraitDotEffect(void) {
}
for (offs = 0; offs != cur_image_end;) {
- target[CalcXY_p(x + offs % cur_image_size_w, y + offs / cur_image_size_w)] = cur_image_pixels[offs]; // TODO check this
+ target[g_vm->_renderer->calcXY_p(x + offs % cur_image_size_w, y + offs / cur_image_size_w)] = cur_image_pixels[offs]; // TODO check this
if (count % 5 == 0)
g_vm->_renderer->blitToScreen(offs, g_vm->_screenPPB, 1);
@@ -985,7 +985,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
@@ -994,7 +994,7 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
if (g_vm->_videoMode == Common::kRenderEGA) {
offs += 4;
while (--width)
- g_vm->_renderer->hideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToLeft(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
offs -= 4;
uint16 ooffs = offs;
byte oh = height;
@@ -1002,15 +1002,15 @@ uint16 SCR_19_HidePortraitLiftLeft(void) {
memcpy(frontbuffer + offs, backbuffer + offs, 4);
offs += EGA_BYTES_PER_LINE;
}
- ega_blitToScreen(ooffs % EGA_BYTES_PER_LINE, ooffs / EGA_BYTES_PER_LINE, 4, oh);
+ g_vm->_renderer->blitToScreen(ooffs % EGA_BYTES_PER_LINE, ooffs / EGA_BYTES_PER_LINE, 4, oh);
return 0;
}
- /*offs = CalcXY_p(x + 1, y);*/
+ /*offs = g_vm->_renderer->calcXY_p(x + 1, y);*/
offs++;
while (--width) {
- g_vm->_renderer->hideScreenBlockLiftToLeft(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToLeft(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
}
offs--;
@@ -1046,16 +1046,16 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
/*TODO: This originally was done by reusing door sliding routine*/
if (g_vm->_videoMode == Common::kRenderEGA) {
- offs = CalcXY_p(x + width - 2, y);
+ offs = g_vm->_renderer->calcXY_p(x + width - 2, y);
while (--width)
- g_vm->_renderer->hideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToRight(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
offs += 4;
uint16 ooffs = offs;
byte oh = height;
@@ -1063,14 +1063,14 @@ uint16 SCR_1A_HidePortraitLiftRight(void) {
memcpy(frontbuffer + offs, backbuffer + offs, 4);
offs += EGA_BYTES_PER_LINE;
}
- ega_blitToScreen(ooffs % EGA_BYTES_PER_LINE, ooffs / EGA_BYTES_PER_LINE, 4, oh);
+ g_vm->_renderer->blitToScreen(ooffs % EGA_BYTES_PER_LINE, ooffs / EGA_BYTES_PER_LINE, 4, oh);
return 0;
}
- offs = CalcXY_p(x + width - 2, y);
+ offs = g_vm->_renderer->calcXY_p(x + width - 2, y);
while (--width) {
- g_vm->_renderer->hideScreenBlockLiftToRight(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToRight(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
}
offs++;
@@ -1106,19 +1106,19 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
if (g_vm->_videoMode == Common::kRenderEGA) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
- offs = CalcXY_p(x, y + 1);
+ offs = g_vm->_renderer->calcXY_p(x, y + 1);
while (--height) {
- g_vm->_renderer->hideScreenBlockLiftToUp(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToUp(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
}
/*hide topmost line*/
@@ -1126,7 +1126,7 @@ uint16 SCR_1B_HidePortraitLiftUp(void) {
offs ^= g_vm->_line_offset;
if ((offs & g_vm->_line_offset) != 0)
offs -= g_vm->_screenBPL;
- memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
+ memcpy(SCREENBUFFER + offs, backbuffer + offs, width);
g_vm->_renderer->blitToScreen(offs, width, 1);
return 0;
}
@@ -1147,19 +1147,19 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
if (g_vm->_videoMode == Common::kRenderEGA) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
- offs = CalcXY_p(x, y + height - 2);
+ offs = g_vm->_renderer->calcXY_p(x, y + height - 2);
while (--height) {
- g_vm->_renderer->hideScreenBlockLiftToDown(1, CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideScreenBlockLiftToDown(1, SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
}
/*hide bottommost line*/
@@ -1167,7 +1167,7 @@ uint16 SCR_1C_HidePortraitLiftDown(void) {
offs ^= g_vm->_line_offset;
if ((offs & g_vm->_line_offset) == 0)
offs += g_vm->_screenBPL;
- memcpy(CGA_SCREENBUFFER + offs, backbuffer + offs, width);
+ memcpy(SCREENBUFFER + offs, backbuffer + offs, width);
g_vm->_renderer->blitToScreen(offs, width, 1);
return 0;
}
@@ -1188,7 +1188,7 @@ uint16 SCR_1E_HidePortraitTwist(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
@@ -1212,7 +1212,7 @@ uint16 SCR_1F_HidePortraitArc(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
@@ -1236,7 +1236,7 @@ uint16 SCR_20_HidePortraitDots(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
@@ -1436,7 +1436,7 @@ void drawStars(star_t *stars, int16 iter, byte *target) {
}
if (g_vm->_videoMode == Common::kRenderEGA) {
- stars->ofs = ega_CalcXY_p(x, y);
+ stars->ofs = g_vm->_renderer->calcXY_p(x, y);
pixel = (stars->z < 0xE00) ? 15 : 8;
stars->pixel = pixel;
stars->mask = 0;
@@ -1633,7 +1633,7 @@ Display a static sprite in the room (to screen)
uint16 SCR_11_DrawRoomObject(void) {
byte x, y, w, h;
SCR_DrawRoomObjectBack(&x, &y, &w, &h);
- g_vm->_renderer->copyScreenBlock(backbuffer, w, h, frontbuffer, CalcXY_p(x, y));
+ g_vm->_renderer->copyScreenBlock(backbuffer, w, h, frontbuffer, g_vm->_renderer->calcXY_p(x, y));
return 0;
}
@@ -1794,7 +1794,7 @@ uint16 SCR_28_MenuLoop(void) {
mask = *script_ptr++;
value = *script_ptr++;
- selectCursor(cursor);
+ g_vm->_renderer->selectCursor(cursor);
menuLoop(mask, value);
@@ -1816,8 +1816,8 @@ uint16 SCR_2A_PopDialogRect(void) {
index = *script_ptr++;
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs); /*TODO: implicit target*/
- g_vm->_renderer->copyScreenBlock(backbuffer, 2, 21, CGA_SCREENBUFFER, offs = (x << 8) | y); /*TODO: implicit target*/
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs); /*TODO: implicit target*/
+ g_vm->_renderer->copyScreenBlock(backbuffer, 2, 21, SCREENBUFFER, offs = (x << 8) | y); /*TODO: implicit target*/
cur_dlg_index = 0;
@@ -1848,11 +1848,11 @@ uint16 SCR_22_HidePortraitShatter(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
- g_vm->_renderer->hideShatterFall(CGA_SCREENBUFFER, backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->hideShatterFall(SCREENBUFFER, backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
@@ -1872,11 +1872,11 @@ uint16 SCR_23_HidePortrait(void) {
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
}
@@ -1975,13 +1975,13 @@ uint16 SCR_30_Fight(void) {
player_image[1] = x;
player_image[2] = y;
if (drawPortrait(&image, &x, &y, &width, &height))
- g_vm->_renderer->animLiftToLeft(width, cur_image_pixels, width, 1, height, CGA_SCREENBUFFER, CalcXY_p(x + width - 1, y));
+ g_vm->_renderer->animLiftToLeft(width, cur_image_pixels, width, 1, height, SCREENBUFFER, g_vm->_renderer->calcXY_p(x + width - 1, y));
blinkToWhite();
if (pers->name != 44 && pers->name != 56 && pers->name != 51) { /*VORT, MONKEY, TURKEY*/
getDirtyRectAndFree(1, &kind, &x, &y, &width, &height, &offs);
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, CGA_SCREENBUFFER, offs);
+ g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
}
/*check fight outcome*/
@@ -2378,27 +2378,27 @@ uint16 SCR_45_DeProfundisRoomEntry(void) {
/*draw Platform*/
sprofs = getPuzzlSprite(3, 140 / 4, 174, &w, &h, &ofs);
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
/*draw Granite Monster*/
sprofs = getPuzzlSprite(119, 128 / 4, 94, &w, &h, &ofs);
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
promptWait();
for (; h; h--) {
waitVBlank();
waitVBlank();
- g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, SCREENBUFFER, ofs);
ofs ^= g_vm->_line_offset;
if ((ofs & g_vm->_line_offset) == 0)
ofs += g_vm->_screenBPL;
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
}
- g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, SCREENBUFFER, ofs);
return 0;
}
@@ -2422,12 +2422,12 @@ uint16 SCR_46_DeProfundisLowerHook(void) {
for (; y; y--) {
waitVBlank();
- g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, SCREENBUFFER, ofs);
h++;
sprofs -= 20 / 4 * 2;
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
}
return 0;
@@ -2458,7 +2458,7 @@ uint16 SCR_47_DeProfundisRiseMonster(void) {
h++;
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
}
return 0;
@@ -2481,14 +2481,14 @@ uint16 SCR_48_DeProfundisLowerMonster(void) {
for (; y; y--) {
waitVBlank();
- g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, SCREENBUFFER, ofs);
ofs ^= g_vm->_line_offset;
if ((ofs & g_vm->_line_offset) == 0)
ofs += g_vm->_screenBPL;
h--;
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
}
return 0;
@@ -2512,15 +2512,15 @@ uint16 SCR_49_DeProfundisRiseHook(void) {
for (; y; y--) {
waitVBlank();
- g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, SCREENBUFFER, ofs);
h--;
sprofs += 20 / 4 * 2;
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
}
- g_vm->_renderer->blitFromBackBuffer(w, 1, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, 1, SCREENBUFFER, ofs);
return 0;
}
@@ -2553,7 +2553,7 @@ uint16 SCR_65_DeProfundisMovePlatform(void) {
for (; y; y--) {
waitVBlank();
- g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, SCREENBUFFER, ofs);
ofs ^= g_vm->_line_offset;
if ((ofs & g_vm->_line_offset) == 0)
@@ -2561,11 +2561,11 @@ uint16 SCR_65_DeProfundisMovePlatform(void) {
h--;
- g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitScratchBackSprite(sprofs, w, h, SCREENBUFFER, ofs);
}
if (state)
- g_vm->_renderer->blitFromBackBuffer(w, h, CGA_SCREENBUFFER, ofs);
+ g_vm->_renderer->blitFromBackBuffer(w, h, SCREENBUFFER, ofs);
return 0;
}
@@ -3093,7 +3093,7 @@ uint16 SCR_14_DrawDesc(void) {
msg = seekToStringScr(desci_data, *script_ptr, &script_ptr);
script_ptr++;
- drawMessage(msg, CGA_SCREENBUFFER);
+ drawMessage(msg, SCREENBUFFER);
return 0;
}
@@ -3286,7 +3286,7 @@ uint16 SCR_6A_Unused(void) {
Open room's items inventory
*/
uint16 CMD_1_RoomObjects(void) {
- updateUndrawCursor(CGA_SCREENBUFFER);
+ updateUndrawCursor(SCREENBUFFER);
inv_bgcolor = 0xAA;
openInventory((0xFF << 8) | ITEMFLG_ROOM, (script_byte_vars.zone_area << 8) | ITEMFLG_ROOM);
return ScriptRerun;
@@ -3297,20 +3297,20 @@ Open Psi Powers menu
*/
uint16 CMD_2_PsiPowers(void) {
/*Psi powers bar*/
- backupAndShowSprite(3, 280 / 4, 40);
+ g_vm->_renderer->backupAndShowSprite(3, 280 / 4, 40);
processInput();
do {
pollInput();
- selectCursor(CURSOR_FINGER);
+ g_vm->_renderer->selectCursor(CURSOR_FINGER);
checkPsiCommandHover();
if (command_hint != 100)
command_hint += 109;
if (command_hint != last_command_hint)
drawCommandHint();
- drawHintsAndCursor(CGA_SCREENBUFFER);
+ drawHintsAndCursor(SCREENBUFFER);
} while (buttons == 0);
- undrawCursor(CGA_SCREENBUFFER);
- g_vm->_renderer->restoreBackupImage(CGA_SCREENBUFFER);
+ undrawCursor(SCREENBUFFER);
+ g_vm->_renderer->restoreBackupImage(SCREENBUFFER);
return ScriptRerun;
}
@@ -3318,7 +3318,7 @@ uint16 CMD_2_PsiPowers(void) {
Open normal inventory box
*/
uint16 CMD_3_Possessions(void) {
- updateUndrawCursor(CGA_SCREENBUFFER);
+ updateUndrawCursor(SCREENBUFFER);
inv_bgcolor = 0x55;
openInventory(ITEMFLG_OWNED, ITEMFLG_OWNED);
return ScriptRerun;
@@ -3343,7 +3343,7 @@ uint16 CMD_4_EnergyLevel(void) {
anim = 41 + (script_byte_vars.psy_energy / 16);
if (drawPortrait(&image, &x, &y, &width, &height)) {
- g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, SCREENBUFFER, cur_image_offs);
}
do {
@@ -3418,7 +3418,7 @@ uint16 CMD_8_Timer(void) {
byte *image = timer_image;
if (drawPortrait(&image, &x, &y, &width, &height)) {
- g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
+ g_vm->_renderer->blitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, SCREENBUFFER, cur_image_offs);
}
do {
@@ -3429,10 +3429,10 @@ uint16 CMD_8_Timer(void) {
char_draw_coords_y = 120;
waitVBlank();
- g_vm->_renderer->printChar(timer / (60 * 60) + 16, CGA_SCREENBUFFER);
- g_vm->_renderer->printChar((minutes & 1) ? 26 : 0, CGA_SCREENBUFFER); /*colon*/
- g_vm->_renderer->printChar(minutes / (60 * 10) + 16, CGA_SCREENBUFFER);
- g_vm->_renderer->printChar(minutes / 60 + 16, CGA_SCREENBUFFER);
+ g_vm->_renderer->printChar(timer / (60 * 60) + 16, SCREENBUFFER);
+ g_vm->_renderer->printChar((minutes & 1) ? 26 : 0, SCREENBUFFER); /*colon*/
+ g_vm->_renderer->printChar(minutes / (60 * 10) + 16, SCREENBUFFER);
+ g_vm->_renderer->printChar(minutes / 60 + 16, SCREENBUFFER);
pollInputButtonsOnly();
} while (buttons == 0);
@@ -3491,7 +3491,7 @@ void DrawStickyNet(void) {
w = room_bounds_rect.ex - x;
h = room_bounds_rect.ey - y;
- uint16 ofs = CalcXY_p(x, y);
+ uint16 ofs = g_vm->_renderer->calcXY_p(x, y);
/*16x30 is the net sprite size*/
@@ -3503,7 +3503,7 @@ void DrawStickyNet(void) {
int16 pitch = surf->pitch;
for (; h >= sprH; h -= sprH) {
for (int16 i = 0; i < w; i += sprW / 4)
- ega_BlitSprite(pixels, pitch, sprW, sprH, frontbuffer, ofs + i * 4);
+ g_vm->_renderer->blitSprite(pixels, pitch, sprW, sprH, frontbuffer, ofs + i * 4);
ofs += EGA_BYTES_PER_LINE * sprH;
}
return;
@@ -3513,7 +3513,7 @@ void DrawStickyNet(void) {
for (; h; h -= 30) {
int16 i;
for (i = 0; i < w; i += 16 / 4)
- drawSprite(sprite, frontbuffer, ofs + i);
+ g_vm->_renderer->drawSprite(sprite, frontbuffer, ofs + i);
ofs += g_vm->_screenBPL * 30 / 2;
}
}
@@ -3529,7 +3529,7 @@ uint16 CMD_B_PsiStickyFingers(void) {
backupScreenOfSpecialRoom();
DrawStickyNet();
- selectCursor(CURSOR_FLY);
+ g_vm->_renderer->selectCursor(CURSOR_FLY);
menuLoop(0, 0);
playSound(224);
g_vm->_renderer->backBufferToRealFull();
@@ -3621,7 +3621,7 @@ uint16 CMD_E_PsiZoneScan(void) {
IFGM_PlaySample(26);
- offs = CalcXY_p(room_bounds_rect.sx, room_bounds_rect.sy);
+ offs = g_vm->_renderer->calcXY_p(room_bounds_rect.sx, room_bounds_rect.sy);
w = room_bounds_rect.ex - room_bounds_rect.sx;
h = room_bounds_rect.ey - room_bounds_rect.sy;
@@ -3666,7 +3666,7 @@ uint16 CMD_F_PsiPsiShift(void) {
return ScriptRerun;
}
- selectCursor(CURSOR_GRAB);
+ g_vm->_renderer->selectCursor(CURSOR_GRAB);
menuLoop(0, 0);
backupScreenOfSpecialRoom();
playSound(25);
@@ -4487,7 +4487,7 @@ again:;
res = RunScript(templ_data + the_command);
break;
case 0x9000:
- drawMessage(seekToString(desci_data, cmd), CGA_SCREENBUFFER);
+ drawMessage(seekToString(desci_data, cmd), SCREENBUFFER);
break;
case 0xA000:
case 0xB000:
More information about the Scummvm-git-logs
mailing list