[Scummvm-git-logs] scummvm master -> 33894ae5045be959280dec14c124d66fdbc84ce6
bluegr
noreply at scummvm.org
Mon Apr 13 14:10:39 UTC 2026
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
635d855848 AGOS: PN Amiga improvements and quick save/load
aeb3751590 AGOS: Simplify PN Amiga width handling
0629e6e220 AGOS: Back out of quicksave changes, swallow input instead
33894ae504 AGOS: Move topaz 9 double height draw from AGOS to amigafont
Commit: 635d8558484924f39e06e8cf15a6fccf25a2d520
https://github.com/scummvm/scummvm/commit/635d8558484924f39e06e8cf15a6fccf25a2d520
Author: Robert Megone (robert.megone at gmail.com)
Date: 2026-04-13T17:10:32+03:00
Commit Message:
AGOS: PN Amiga improvements and quick save/load
Changed paths:
engines/agos/agos.cpp
engines/agos/agos.h
engines/agos/charset-fontdata.cpp
engines/agos/charset.cpp
engines/agos/cursor.cpp
engines/agos/gfx.cpp
engines/agos/input_pn.cpp
engines/agos/pn.cpp
engines/agos/saveload.cpp
engines/agos/script_pn.cpp
engines/agos/string_pn.cpp
engines/agos/window.cpp
graphics/fonts/amigafont.cpp
graphics/fonts/amigafont.h
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index b04b4c230d8..0ef6a06a1c2 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -38,6 +38,7 @@
#include "graphics/surface.h"
#include "graphics/sjis.h"
+#include "graphics/fonts/amigafont.h"
#include "audio/mididrv.h"
@@ -312,6 +313,7 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
_curWindow = 0;
_textWindow = nullptr;
+ _pnAmigaFont = nullptr;
_subjectItem = nullptr;
_objectItem = nullptr;
@@ -412,6 +414,7 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
_vgaFrozenBase = nullptr;
_vgaRealBase = nullptr;
_zoneBuffers = nullptr;
+ _pnAmigaUiVisible = false;
_curVgaFile1 = nullptr;
_curVgaFile2 = nullptr;
@@ -612,11 +615,15 @@ Common::Error AGOSEngine::init() {
_screenHeight = 480;
} else {
_screenWidth = 320;
- _screenHeight = 200;
+ _screenHeight = isPnAmiga() ? 240 : 200;
}
_internalWidth = _screenWidth;
_internalHeight = _screenHeight;
+ if (isPnAmiga()) {
+ _internalWidth = 640;
+ _internalHeight = 480;
+ }
if (getPlatform() == Common::kPlatformPC98) {
_internalWidth <<= 1;
@@ -665,11 +672,16 @@ Common::Error AGOSEngine::init() {
_backGroundBuf = new Graphics::Surface();
_backGroundBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
- if (getGameType() == GType_FF || getGameType() == GType_PP || (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformPC98)) {
+ if (getGameType() == GType_FF || getGameType() == GType_PP ||
+ (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformPC98) || isPnAmiga()) {
_backBuf = new Graphics::Surface();
_backBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
+ memset(_backBuf->getPixels(), 0, _backBuf->pitch * _backBuf->h);
_scaleBuf = new Graphics::Surface();
- _scaleBuf->create(_internalWidth, _internalHeight, Graphics::PixelFormat::createFormatCLUT8());
+ const uint16 scaleWidth = isPnAmiga() ? 640 : _internalWidth;
+ const uint16 scaleHeight = isPnAmiga() ? _screenHeight : _internalHeight;
+ _scaleBuf->create(scaleWidth, scaleHeight, Graphics::PixelFormat::createFormatCLUT8());
+ memset(_scaleBuf->getPixels(), 0, _scaleBuf->pitch * _scaleBuf->h);
}
if (getGameType() == GType_SIMON2) {
@@ -963,10 +975,111 @@ void AGOSEngine::setupGame() {
if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST) {
_videoWindows[9] = 75;
}
+ if (isPnAmiga()) {
+ _videoWindows[3] = 134;
+ _videoWindows[7] = 134;
+ _videoWindows[11] = 134;
+ _videoWindows[15] = 240;
+ if (_pnAmigaFont == nullptr)
+ _pnAmigaFont = new Graphics::AmigaFont(Graphics::AmigaFont::kTopaz9Builtin);
+ }
+}
+
+
+bool AGOSEngine::isPnAmiga() const {
+ return getGameType() == GType_PN && getPlatform() == Common::kPlatformAmiga;
+}
+
+bool AGOSEngine::usePnAmigaDoubleHeightTopaz() const {
+ return ConfMan.hasKey("pn_amiga_doubleheight_font") && ConfMan.getBool("pn_amiga_doubleheight_font");
}
+const Graphics::AmigaFont *AGOSEngine::getPnAmigaFont() const {
+ return _pnAmigaFont;
+}
+
+uint16 AGOSEngine::getPnAmigaGlyphAdvance(byte chr) const {
+ const Graphics::AmigaFont *font = getPnAmigaFont();
+ if (font == nullptr)
+ return 0;
+ if (chr == 128 || chr == 129)
+ return font->getCharAdvanceWidth(' ');
+ if (chr < font->getLoChar() || chr > font->getHiChar())
+ return 0;
+
+ return font->getCharAdvanceWidth(chr);
+}
+
+uint16 AGOSEngine::getPnAmigaGlyphRenderWidth(byte chr) const {
+ const Graphics::AmigaFont *font = getPnAmigaFont();
+ if (font == nullptr)
+ return 0;
+ if (chr == 128 && isPnAmiga())
+ chr = '_';
+ if (chr == 128 || chr == 129)
+ return getPnAmigaGlyphAdvance(' ');
+ if (chr < font->getLoChar() || chr > font->getHiChar())
+ return 0;
+
+ return font->getCharRenderWidth(chr);
+}
+
+uint16 AGOSEngine::getPnAmigaGlyphHeight() const {
+ const Graphics::AmigaFont *font = getPnAmigaFont();
+ const uint16 rawHeight = font ? font->getFontHeight() : 9;
+ return usePnAmigaDoubleHeightTopaz() ? rawHeight * 2 : rawHeight;
+}
+
+void AGOSEngine::ensurePnAmigaTextPlanes() {
+ if (!isPnAmiga())
+ return;
+ const WindowBlock *mainWindow = _windowArray[0];
+ const WindowBlock *inputWindow = _windowArray[2];
+ if (mainWindow == nullptr || inputWindow == nullptr)
+ return;
+
+ const uint16 mainWidth = getPnAmigaTextPlaneWidth(mainWindow);
+ const uint16 mainHeight = getPnAmigaWindowInteriorHeight(mainWindow);
+ const uint16 inputWidth = getPnAmigaTextPlaneWidth(inputWindow);
+ const uint16 inputHeight = getPnAmigaWindowInteriorHeight(inputWindow);
+
+ if (_pnAmigaMainTextPlane.pixels == nullptr || _pnAmigaMainTextPlane.width != mainWidth || _pnAmigaMainTextPlane.height != mainHeight) {
+ delete[] _pnAmigaMainTextPlane.pixels;
+ _pnAmigaMainTextPlane.width = mainWidth;
+ _pnAmigaMainTextPlane.height = mainHeight;
+ _pnAmigaMainTextPlane.pixels = new byte[mainWidth * mainHeight];
+ memset(_pnAmigaMainTextPlane.pixels, 0, mainWidth * mainHeight);
+ }
+
+ if (_pnAmigaInputTextPlane.pixels == nullptr || _pnAmigaInputTextPlane.width != inputWidth || _pnAmigaInputTextPlane.height != inputHeight) {
+ delete[] _pnAmigaInputTextPlane.pixels;
+ _pnAmigaInputTextPlane.width = inputWidth;
+ _pnAmigaInputTextPlane.height = inputHeight;
+ _pnAmigaInputTextPlane.pixels = new byte[inputWidth * inputHeight];
+ memset(_pnAmigaInputTextPlane.pixels, 0, inputWidth * inputHeight);
+ }
+}
+
+AGOSEngine::PnAmigaTextPlane *AGOSEngine::getPnAmigaTextPlane(const WindowBlock *window) {
+ if (isPnAmigaMainTextWindow(window))
+ return &_pnAmigaMainTextPlane;
+ if (isPnAmigaInputWindow(window))
+ return &_pnAmigaInputTextPlane;
+ return nullptr;
+}
+
+const AGOSEngine::PnAmigaTextPlane *AGOSEngine::getPnAmigaTextPlane(const WindowBlock *window) const {
+ if (isPnAmigaMainTextWindow(window))
+ return &_pnAmigaMainTextPlane;
+ if (isPnAmigaInputWindow(window))
+ return &_pnAmigaInputTextPlane;
+ return nullptr;
+}
+
+
AGOSEngine::~AGOSEngine() {
_system->getAudioCDManager()->stop();
+ delete _pnAmigaFont;
for (uint i = 0; i < _itemHeap.size(); i++) {
delete[] _itemHeap[i];
@@ -984,6 +1097,8 @@ AGOSEngine::~AGOSEngine() {
free(_roomsList);
free(_roomStates);
free(_stringTabPtr);
+ delete[] _pnAmigaMainTextPlane.pixels;
+ delete[] _pnAmigaInputTextPlane.pixels;
free(_strippedTxtMem);
free(_tblList);
free(_textMem);
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 2a25cdf2163..fc054b3cbb8 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -62,6 +62,7 @@ class SeekableReadStream;
namespace Graphics {
struct Surface;
class FontSJIS;
+class AmigaFont;
}
namespace Audio {
@@ -540,6 +541,20 @@ protected:
VgaTimerEntry *_nextVgaTimerToProcess;
+ struct PnAmigaTextPlane {
+ byte *pixels;
+ uint16 width, height;
+ PnAmigaTextPlane() : pixels(nullptr), width(0), height(0) {}
+ };
+
+ enum {
+ kPnAmigaTextStartX = 2,
+ kPnAmigaLowresWidth = 320,
+ kPnAmigaMainTextTop = 136,
+ kPnAmigaInputTop = 224,
+ kPnAmigaTextPlaneWidth = 552
+ };
+
uint8 _opcode177Var1, _opcode177Var2;
uint8 _opcode178Var1, _opcode178Var2;
@@ -561,6 +576,10 @@ protected:
WindowBlock *_dummyWindow;
WindowBlock *_windowArray[80];
+ Graphics::AmigaFont *_pnAmigaFont;
+ bool _pnAmigaUiVisible;
+ PnAmigaTextPlane _pnAmigaMainTextPlane;
+ PnAmigaTextPlane _pnAmigaInputTextPlane;
byte _fcsData1[8];
bool _fcsData2[8];
@@ -702,6 +721,27 @@ protected:
void decompressData(const char *srcName, byte *dst, uint32 offset, uint32 srcSize, uint32 dstSize);
void decompressPN(Common::Stack<uint32> &dataList, uint8 *&dataOut, int &dataOutSize);
void drawPnSqueezedChar(WindowBlock *window, uint x, uint y, byte chr);
+ bool isPnAmiga() const;
+ bool isPnAmigaMainTextWindow(const WindowBlock *window) const;
+ bool isPnAmigaInputWindow(const WindowBlock *window) const;
+ bool isPnAmigaTextWindow(const WindowBlock *window) const;
+ const Graphics::AmigaFont *getPnAmigaFont() const;
+ uint16 getPnAmigaWindowInteriorHeight(const WindowBlock *window) const;
+ uint16 getPnAmigaTextPlaneWidth(const WindowBlock *window) const;
+ uint16 getPnAmigaTextLineStep() const;
+ uint16 getPnAmigaGlyphAdvance(byte chr) const;
+ uint16 getPnAmigaGlyphRenderWidth(byte chr) const;
+ uint16 getPnAmigaGlyphHeight() const;
+ bool usePnAmigaDoubleHeightTopaz() const;
+ void ensurePnAmigaTextPlanes();
+ PnAmigaTextPlane *getPnAmigaTextPlane(const WindowBlock *window);
+ const PnAmigaTextPlane *getPnAmigaTextPlane(const WindowBlock *window) const;
+ void clearPnAmigaTextPlane(WindowBlock *window);
+ void compositePnAmigaTextPlane(WindowBlock *window);
+ void scrollPnAmigaTextPlane(WindowBlock *window);
+ void drawPnAmigaTopazChar(WindowBlock *window, byte chr);
+ void drawPnAmigaTextWindowBorders();
+
void loadOffsets(const char *filename, int number, uint32 &file, uint32 &offset, uint32 &compressedSize, uint32 &size);
void loadSound(uint16 sound, int16 pan, int16 vol, uint16 type);
void playSfx(uint16 sound, uint16 freq, uint16 flags, bool digitalOnly = false, bool midiOnly = false);
@@ -1412,6 +1452,7 @@ public:
void setupGame() override;
void setupOpcodes() override;
void setupVideoOpcodes(VgaOpcodeProc *op) override;
+ void quickLoadOrSave() override;
void windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) override;
void saveInventoryPalette();
void applyInventoryPalette();
diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp
index 868d297efd5..14fa4cee8ee 100644
--- a/engines/agos/charset-fontdata.cpp
+++ b/engines/agos/charset-fontdata.cpp
@@ -28,6 +28,7 @@
#include "graphics/surface.h"
#include "graphics/sjis.h"
+#include "graphics/fonts/amigafont.h"
namespace AGOS {
@@ -3060,6 +3061,80 @@ static inline void pnSqueezeGlyph8Rows(const byte *src8, byte *dst8) {
dst8[i] = pnSqueezeRow(src8[i], anyBit1SetAcrossGlyph);
}
+static void drawPnAmigaDoubleHeightTopazChar(const Graphics::AmigaFont *font, Graphics::Surface *dst, byte chr, int x, int y, byte color) {
+ enum {
+ kPnAmigaTopazScratchWidth = 16,
+ kPnAmigaTopazScratchHeight = 16
+ };
+
+ const int glyphWidth = font->getCharRenderWidth(chr);
+ const int rawHeight = font->getFontHeight();
+ const int drawOffset = font->getCharDrawOffset(chr);
+ const int glyphLeft = MIN<int>(0, drawOffset);
+ const int glyphOriginX = drawOffset - glyphLeft;
+ if (glyphWidth <= 0 || rawHeight <= 0)
+ return;
+ assert(glyphWidth <= kPnAmigaTopazScratchWidth);
+ assert(rawHeight <= kPnAmigaTopazScratchHeight);
+
+ byte glyphPixels[kPnAmigaTopazScratchWidth * kPnAmigaTopazScratchHeight];
+ memset(glyphPixels, 0, sizeof(glyphPixels));
+
+ Graphics::Surface glyphSurface;
+ glyphSurface.init(glyphWidth, rawHeight, glyphWidth, glyphPixels, Graphics::PixelFormat::createFormatCLUT8());
+ font->drawChar(&glyphSurface, chr, glyphOriginX, 0, 1);
+
+ for (int srcY = 0; srcY < rawHeight; ++srcY) {
+ for (int srcX = 0; srcX < glyphWidth; ++srcX) {
+ if (glyphPixels[srcY * glyphWidth + srcX] == 0)
+ continue;
+
+ const int dstX = x + glyphLeft + srcX;
+ if (dstX < 0 || dstX >= dst->w)
+ continue;
+
+ for (int repeat = 0; repeat < 2; ++repeat) {
+ const int dstY = y + srcY * 2 + repeat;
+ if (dstY >= 0 && dstY < dst->h)
+ *(byte *)dst->getBasePtr(dstX, dstY) = color;
+ }
+ }
+ }
+}
+
+void AGOSEngine::drawPnAmigaTopazChar(WindowBlock *window, byte chr) {
+ PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
+ if (plane == nullptr || plane->pixels == nullptr)
+ return;
+
+ Graphics::Surface surface;
+ surface.init(plane->width, plane->height, plane->width, plane->pixels, Graphics::PixelFormat::createFormatCLUT8());
+
+ const int x = window->textColumn;
+ const int y = window->textRow;
+ const int glyphWidth = getPnAmigaGlyphAdvance(' ');
+ const int fontHeight = getPnAmigaGlyphHeight();
+ if (chr == 128 && isPnAmigaInputWindow(window)) {
+ chr = '_';
+ }
+
+ if (chr == 128 || chr == 129) {
+ surface.fillRect(Common::Rect(x, y, x + glyphWidth, y + fontHeight), window->textColor);
+ return;
+ }
+
+ const Graphics::AmigaFont *font = getPnAmigaFont();
+ if (font == nullptr)
+ return;
+ if (chr < font->getLoChar() || chr > font->getHiChar())
+ return;
+
+ if (usePnAmigaDoubleHeightTopaz())
+ drawPnAmigaDoubleHeightTopazChar(font, &surface, chr, x, y, window->textColor);
+ else
+ font->drawChar(&surface, chr, x + font->getCharDrawOffset(chr), y, window->textColor);
+}
+
void AGOSEngine::drawPnSqueezedChar(WindowBlock *window, uint x, uint y, byte chr) {
const byte *src;
byte color, *dst;
@@ -3103,6 +3178,15 @@ void AGOSEngine::drawPnSqueezedChar(WindowBlock *window, uint x, uint y, byte ch
}
void AGOSEngine_PN::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
+ if (isPnAmigaTextWindow(window)) {
+ (void)x;
+ (void)y;
+ _videoLockOut |= 0x8000;
+ drawPnAmigaTopazChar(window, chr);
+ compositePnAmigaTextPlane(window);
+ _videoLockOut &= ~0x8000;
+ return;
+ }
_videoLockOut |= 0x8000;
drawPnSqueezedChar(window, x, y, chr);
_videoLockOut &= ~0x8000;
diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp
index 05451427c00..de1ccee14ec 100644
--- a/engines/agos/charset.cpp
+++ b/engines/agos/charset.cpp
@@ -134,6 +134,10 @@ void AGOSEngine::justifyStart() {
} else {
_printCharCurPos = _textWindow->textLength;
_printCharMaxPos = _textWindow->textMaxLength;
+ if (isPnAmigaTextWindow(_textWindow)) {
+ _printCharCurPos = _textWindow->textColumn;
+ _printCharMaxPos = getPnAmigaTextPlaneWidth(_textWindow);
+ }
}
_printCharPixelCount = 0;
_numLettersToPrint = 0;
@@ -141,6 +145,8 @@ void AGOSEngine::justifyStart() {
}
void AGOSEngine::justifyOutPut(byte chr) {
+ const bool pnAmigaText = isPnAmigaTextWindow(_textWindow);
+
if (chr == 12) {
_numLettersToPrint = 0;
_printCharCurPos = 0;
@@ -154,6 +160,10 @@ void AGOSEngine::justifyOutPut(byte chr) {
doOutput(_lettersToPrintBuf, 1);
} else if (chr == 0 || chr == ' ' || chr == 10) {
bool fit;
+ int16 separatorWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? getFeebleFontSize(chr) : 1;
+
+ if (pnAmigaText && chr == ' ')
+ separatorWidth = getPnAmigaGlyphAdvance(chr);
if (getGameType() == GType_FF || getGameType() == GType_PP) {
fit = _printCharMaxPos - _printCharCurPos > _printCharPixelCount;
@@ -166,14 +176,14 @@ void AGOSEngine::justifyOutPut(byte chr) {
doOutput(_lettersToPrintBuf, _numLettersToPrint);
if (_printCharCurPos == _printCharMaxPos) {
- _printCharCurPos = 0;
+ _printCharCurPos = pnAmigaText ? kPnAmigaTextStartX : 0;
} else {
if (chr)
doOutput(&chr, 1);
if (chr == 10)
- _printCharCurPos = 0;
+ _printCharCurPos = pnAmigaText ? kPnAmigaTextStartX : 0;
else if (chr != 0)
- _printCharCurPos += (getGameType() == GType_FF || getGameType() == GType_PP) ? getFeebleFontSize(chr) : 1;
+ _printCharCurPos += separatorWidth;
}
} else {
const byte newline_character = 10;
@@ -182,17 +192,23 @@ void AGOSEngine::justifyOutPut(byte chr) {
doOutput(_lettersToPrintBuf, _numLettersToPrint);
if (chr == ' ') {
doOutput(&chr, 1);
- _printCharCurPos += (getGameType() == GType_FF || getGameType() == GType_PP) ? getFeebleFontSize(chr) : 1;
+ _printCharCurPos += separatorWidth;
} else {
doOutput(&chr, 1);
- _printCharCurPos = 0;
+ _printCharCurPos = pnAmigaText ? kPnAmigaTextStartX : 0;
}
}
_numLettersToPrint = 0;
_printCharPixelCount = 0;
} else {
+ int16 charWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? getFeebleFontSize(chr) : 1;
+
_lettersToPrintBuf[_numLettersToPrint++] = chr;
- _printCharPixelCount += (getGameType() == GType_FF || getGameType() == GType_PP) ? getFeebleFontSize(chr) : 1;
+
+ if (pnAmigaText)
+ charWidth = getPnAmigaGlyphAdvance(chr);
+
+ _printCharPixelCount += charWidth;
}
}
@@ -221,6 +237,37 @@ void AGOSEngine::windowPutChar(WindowBlock *window, byte c, byte b) {
byte width = 6;
byte textColumnWidth = 8;
+ if (isPnAmigaTextWindow(window)) {
+ ensurePnAmigaTextPlanes();
+ if (c == 12) {
+ clearWindow(window);
+ } else if (c == 13 || c == 10) {
+ windowNewLine(window);
+ } else if ((c == 1 || c == 8) && window->textColumn > kPnAmigaTextStartX) {
+ window->textColumn = MAX<int16>(kPnAmigaTextStartX, window->textColumn - (int16)getPnAmigaGlyphAdvance(' '));
+ } else if (c >= 32) {
+ const PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
+ const uint16 advance = getPnAmigaGlyphAdvance(c);
+ const uint16 renderWidth = getPnAmigaGlyphRenderWidth(c);
+ const uint16 cursorWidth = isPnAmigaInputWindow(window) ? getPnAmigaGlyphRenderWidth('_') : 0;
+ const uint16 drawWidth = isPnAmigaInputWindow(window) ? MAX<uint16>(renderWidth, advance + cursorWidth) : renderWidth;
+ if (plane == nullptr)
+ return;
+ if (advance == 0 && renderWidth == 0)
+ return;
+ if (window->textColumn + drawWidth > plane->width) {
+ if (isPnAmigaInputWindow(window))
+ return;
+ windowNewLine(window);
+ }
+ drawPnAmigaTopazChar(window, c);
+ compositePnAmigaTextPlane(window);
+ window->textColumn += advance;
+ window->textLength++;
+ }
+ return;
+ }
+
if (c == 12) {
clearWindow(window);
} else if (c == 13 || c == 10) {
@@ -333,6 +380,23 @@ void AGOSEngine_Feeble::windowNewLine(WindowBlock *window) {
#endif
void AGOSEngine::windowNewLine(WindowBlock *window) {
+ if (isPnAmigaTextWindow(window)) {
+ window->textColumn = kPnAmigaTextStartX;
+ window->textLength = 0;
+ if (isPnAmigaInputWindow(window)) {
+ clearPnAmigaTextPlane(window);
+ const int16 top = ((int16)getPnAmigaWindowInteriorHeight(window) - (int16)getPnAmigaGlyphHeight()) / 2;
+ window->textRow = MAX((int16)0, top);
+ compositePnAmigaTextPlane(window);
+ return;
+ }
+ window->textRow += getPnAmigaTextLineStep();
+ if (window->textRow + getPnAmigaGlyphHeight() > (int16)getPnAmigaWindowInteriorHeight(window) - 2) {
+ scrollPnAmigaTextPlane(window);
+ window->textRow -= getPnAmigaTextLineStep();
+ }
+ return;
+ }
window->textColumn = 0;
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
window->textLength = 0;
@@ -356,6 +420,10 @@ void AGOSEngine::windowNewLine(WindowBlock *window) {
}
void AGOSEngine::windowScroll(WindowBlock *window) {
+ if (isPnAmigaTextWindow(window)) {
+ scrollPnAmigaTextPlane(window);
+ return;
+ }
_videoLockOut |= 0x8000;
if (window->height != 1) {
diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp
index 9b4374de908..31019c5fc75 100644
--- a/engines/agos/cursor.cpp
+++ b/engines/agos/cursor.cpp
@@ -177,6 +177,23 @@ static const byte _amiga_handInfo[16 * 16] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF
};
+static void scaleCursor2x(const byte *src, int srcWidth, int srcHeight, byte *dst, int dstWidth) {
+ for (int y = 0; y < srcHeight; ++y) {
+ byte *dstRow1 = dst + (y * 2) * dstWidth;
+ byte *dstRow2 = dstRow1 + dstWidth;
+ const byte *srcRow = src + y * srcWidth;
+
+ for (int x = 0; x < srcWidth; ++x) {
+ const byte pixel = srcRow[x];
+ const int dstX = x * 2;
+ dstRow1[dstX] = pixel;
+ dstRow1[dstX + 1] = pixel;
+ dstRow2[dstX] = pixel;
+ dstRow2[dstX + 1] = pixel;
+ }
+ }
+}
+
static const byte _simon2_cursors[10][256] = {
// cross hair
{ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xec,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
@@ -529,6 +546,10 @@ void AGOSEngine_PN::handleMouseMoved() {
CursorMan.showMouse(true);
_mouse = _eventMan->getMousePos();
+ if (isPnAmiga()) {
+ _mouse.x >>= 1;
+ _mouse.y >>= 1;
+ }
if (_leftClick == true) {
_leftClick = false;
@@ -847,7 +868,7 @@ void AGOSEngine::initMouse() {
_maxCursorWidth = 16;
_maxCursorHeight = 16;
- if (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) {
+ if ((getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) || isPnAmiga()) {
_maxCursorWidth <<= 1;
_maxCursorHeight <<= 1;
}
@@ -873,7 +894,13 @@ void AGOSEngine::drawMousePointer() {
}
CursorMan.replaceCursorPalette(_amiga_mousePalettePN, 0, ARRAYSIZE(_amiga_mousePalettePN) / 3);
- CursorMan.replaceCursor(cursor, 16, 16, 0, 0, 0xFF);
+ if (_maxCursorWidth == 32 && _maxCursorHeight == 32) {
+ memset(_mouseData, 0xFF, _maxCursorWidth * _maxCursorHeight);
+ scaleCursor2x(cursor, 16, 16, _mouseData, _maxCursorWidth);
+ CursorMan.replaceCursor(_mouseData, _maxCursorWidth, _maxCursorHeight, 0, 0, 0xFF);
+ } else {
+ CursorMan.replaceCursor(cursor, 16, 16, 0, 0, 0xFF);
+ }
return;
}
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 2870b9be681..22e21d7de03 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -1088,7 +1088,9 @@ void AGOSEngine::verticalScroll(VC10_state *state) {
}
Graphics::Surface *AGOSEngine::getBackendSurface() const {
- return (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) ? _backBuf : _system->lockScreen();
+ if ((getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) || isPnAmiga())
+ return _backBuf;
+ return _system->lockScreen();
}
void AGOSEngine::updateBackendSurface(Common::Rect *area) const {
@@ -1137,6 +1139,42 @@ void AGOSEngine::updateBackendSurface(Common::Rect *area) const {
dst10 += dst1Pitch;
dst11 += dst1Pitch;
}
+ } else if (isPnAmiga()) {
+ int x = 0;
+ int y = 0;
+ int w = _screenWidth;
+ int h = _screenHeight;
+
+ if (area) {
+ x = area->left;
+ y = area->top;
+ w = area->width();
+ h = area->height();
+ }
+
+ Graphics::Surface *screen = _system->lockScreen();
+ for (int row = y; row < y + h; ++row) {
+ const int dstRow = row << 1;
+ const bool usePnAmigaTextPane = _pnAmigaUiVisible && row >= 136;
+ if (!usePnAmigaTextPane) {
+ const byte *src = (const byte *)_backBuf->getBasePtr(x, row);
+ byte *dst0 = (byte *)screen->getBasePtr(x << 1, dstRow);
+ byte *dst1 = (byte *)screen->getBasePtr(x << 1, dstRow + 1);
+ for (int i = 0; i < w; ++i) {
+ const uint8 v = *src++;
+ *dst0++ = v;
+ *dst0++ = v;
+ *dst1++ = v;
+ *dst1++ = v;
+ }
+ } else {
+ const byte *src = (const byte *)_scaleBuf->getBasePtr(x << 1, row);
+ byte *dst0 = (byte *)screen->getBasePtr(x << 1, dstRow);
+ byte *dst1 = (byte *)screen->getBasePtr(x << 1, dstRow + 1);
+ memcpy(dst0, src, w << 1);
+ memcpy(dst1, src, w << 1);
+ }
+ }
}
_system->unlockScreen();
@@ -1606,7 +1644,41 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
}
// Personal Nightmare specific
+void AGOSEngine::drawPnAmigaTextWindowBorders() {
+ if (_scaleBuf == nullptr)
+ return;
+
+ Graphics::Surface *screen = _scaleBuf;
+ const byte color = 14;
+ byte *dst = (byte *)screen->getBasePtr(0, 136);
+ memset(dst, color, screen->w);
+ dst = (byte *)screen->getBasePtr(0, 223);
+ memset(dst, color, screen->w);
+ dst = (byte *)screen->getBasePtr(0, 136);
+ for (int y = 136; y <= 223; ++y) {
+ dst[0] = color;
+ dst[screen->w - 1] = color;
+ dst += screen->pitch;
+ }
+ dst = (byte *)screen->getBasePtr(0, 224);
+ memset(dst, color, screen->w);
+ dst = (byte *)screen->getBasePtr(0, 239);
+ memset(dst, color, screen->w);
+ dst = (byte *)screen->getBasePtr(0, 224);
+ for (int y = 224; y <= 239; ++y) {
+ dst[0] = color;
+ dst[screen->w - 1] = color;
+ dst += screen->pitch;
+ }
+ Common::Rect dirtyRect(0, 136, 320, _screenHeight);
+ updateBackendSurface(&dirtyRect);
+}
+
void AGOSEngine::drawEdging() {
+ if (isPnAmiga()) {
+ drawPnAmigaTextWindowBorders();
+ return;
+ }
byte *dst;
uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
diff --git a/engines/agos/input_pn.cpp b/engines/agos/input_pn.cpp
index a078f0b569e..ac0840888b7 100644
--- a/engines/agos/input_pn.cpp
+++ b/engines/agos/input_pn.cpp
@@ -22,6 +22,9 @@
#include "agos/agos.h"
#include "agos/intern.h"
+#include "graphics/fonts/amigafont.h"
+#include "graphics/surface.h"
+
namespace AGOS {
void AGOSEngine_PN::clearInputLine() {
@@ -70,7 +73,9 @@ void AGOSEngine_PN::handleKeyboard() {
if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE || _keyPressed.keycode == Common::KEYCODE_RETURN) {
chr = _keyPressed.keycode;
addChar(chr);
- } else if (!(_videoLockOut & 0x10)) {
+ } else if (!(_videoLockOut & 0x10) &&
+ !_keyPressed.hasFlags(Common::KBD_CTRL) &&
+ !_keyPressed.hasFlags(Common::KBD_ALT)) {
chr = _keyPressed.ascii;
if (chr >= 32)
addChar(chr);
@@ -97,8 +102,13 @@ void AGOSEngine_PN::interact(char *buffer, uint8 size) {
_intputCounter = 0;
_inputMax = size;
_inputWindow = _windowArray[_curWindow];
- windowPutChar(_inputWindow, 128);
- windowPutChar(_inputWindow, 8);
+ if (isPnAmigaInputWindow(_inputWindow)) {
+ drawPnAmigaTopazChar(_inputWindow, 128);
+ compositePnAmigaTextPlane(_inputWindow);
+ } else {
+ windowPutChar(_inputWindow, 128);
+ windowPutChar(_inputWindow, 8);
+ }
_inputting = true;
_inputReady = true;
}
@@ -125,9 +135,41 @@ void AGOSEngine_PN::addChar(uint8 chr) {
windowPutChar(_inputWindow, 13);
} else if (chr == 8 && _intputCounter) {
clearCursor(_inputWindow);
- windowPutChar(_inputWindow, 8);
- windowPutChar(_inputWindow, 128);
- windowPutChar(_inputWindow, 8);
+ if (isPnAmigaInputWindow(_inputWindow)) {
+ const byte deletedChar = _keyboardBuffer[_intputCounter - 1];
+ const Graphics::AmigaFont *font = getPnAmigaFont();
+ const uint16 advance = getPnAmigaGlyphAdvance(deletedChar);
+ byte metricChar = deletedChar;
+ int16 drawOffset = 0;
+ uint16 inkWidth = 0;
+
+ if (metricChar == 128)
+ metricChar = '_';
+ if (metricChar == 128 || metricChar == 129) {
+ inkWidth = getPnAmigaGlyphAdvance(' ');
+ } else if (font != nullptr && metricChar >= font->getLoChar() && metricChar <= font->getHiChar()) {
+ drawOffset = font->getCharDrawOffset(metricChar);
+ inkWidth = font->getCharInkWidth(metricChar);
+ }
+
+ _inputWindow->textColumn = MAX<int16>(kPnAmigaTextStartX, _inputWindow->textColumn - (int16)advance);
+
+ PnAmigaTextPlane *plane = getPnAmigaTextPlane(_inputWindow);
+ if (plane != nullptr && plane->pixels != nullptr) {
+ Graphics::Surface surface;
+ surface.init(plane->width, plane->height, plane->width, plane->pixels, Graphics::PixelFormat::createFormatCLUT8());
+ const int16 clearLeft = CLIP<int16>(_inputWindow->textColumn + drawOffset, 0, plane->width);
+ const int16 clearRight = CLIP<int16>(clearLeft + (int16)inkWidth, 0, plane->width);
+ surface.fillRect(Common::Rect(clearLeft, _inputWindow->textRow,
+ clearRight, _inputWindow->textRow + getPnAmigaGlyphHeight()), _inputWindow->fillColor);
+ drawPnAmigaTopazChar(_inputWindow, 128);
+ compositePnAmigaTextPlane(_inputWindow);
+ }
+ } else {
+ windowPutChar(_inputWindow, 8);
+ windowPutChar(_inputWindow, 128);
+ windowPutChar(_inputWindow, 8);
+ }
_keyboardBuffer[--_intputCounter] = 0;
} else if (chr >= 32 && _intputCounter < _inputMax) {
@@ -135,12 +177,38 @@ void AGOSEngine_PN::addChar(uint8 chr) {
clearCursor(_inputWindow);
windowPutChar(_inputWindow, chr);
- windowPutChar(_inputWindow, 128);
- windowPutChar(_inputWindow, 8);
+ if (isPnAmigaInputWindow(_inputWindow)) {
+ drawPnAmigaTopazChar(_inputWindow, 128);
+ compositePnAmigaTextPlane(_inputWindow);
+ } else {
+ windowPutChar(_inputWindow, 128);
+ windowPutChar(_inputWindow, 8);
+ }
}
}
void AGOSEngine_PN::clearCursor(WindowBlock *window) {
+ if (isPnAmigaInputWindow(window)) {
+ const Graphics::AmigaFont *font = getPnAmigaFont();
+ PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
+ if (plane != nullptr && plane->pixels != nullptr) {
+ Graphics::Surface surface;
+ surface.init(plane->width, plane->height, plane->width, plane->pixels, Graphics::PixelFormat::createFormatCLUT8());
+ int16 drawOffset = 0;
+ uint16 inkWidth = getPnAmigaGlyphAdvance(' ');
+ if (font != nullptr && '_' >= font->getLoChar() && '_' <= font->getHiChar()) {
+ drawOffset = font->getCharDrawOffset('_');
+ inkWidth = font->getCharInkWidth('_');
+ }
+ const int16 cursorLeft = CLIP<int16>(window->textColumn + drawOffset, 0, plane->width);
+ const int16 cursorRight = CLIP<int16>(cursorLeft + (int16)inkWidth, 0, plane->width);
+ surface.fillRect(Common::Rect(cursorLeft, window->textRow,
+ cursorRight, window->textRow + getPnAmigaGlyphHeight()), window->fillColor);
+ compositePnAmigaTextPlane(window);
+ }
+ return;
+ }
+
byte oldTextColor = window->textColor;
window->textColor = window->fillColor;
diff --git a/engines/agos/pn.cpp b/engines/agos/pn.cpp
index bb4b973c782..62988db18d9 100644
--- a/engines/agos/pn.cpp
+++ b/engines/agos/pn.cpp
@@ -130,13 +130,21 @@ Common::Error AGOSEngine_PN::go() {
_paletteFlag = 1;
}
- _inputWindow = _windowArray[2] = openWindow(0, 192, 40, 1, 1, 0, 15);
- _textWindow = _windowArray[0] = openWindow(1, 136, 38, 6, 1, 0, 15);
+ if (isPnAmiga())
+ _pnAmigaUiVisible = false;
+
+ _inputWindow = _windowArray[2] = openWindow(0, isPnAmiga() ? 224 : 192, 40, 1, 1, 0, isPnAmiga() ? 14 : 15);
+ _textWindow = _windowArray[0] = openWindow(isPnAmiga() ? 0 : 1, 136, isPnAmiga() ? 40 : 38, isPnAmiga() ? 5 : 6, 1, 0, isPnAmiga() ? 14 : 15);
if (getFeatures() & GF_DEMO) {
demoSeq();
} else {
introSeq();
+ if (isPnAmiga()) {
+ _pnAmigaUiVisible = true;
+ clearWindow(_windowArray[0]);
+ clearWindow(_windowArray[2]);
+ }
processor();
}
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index 9161fc54fab..b45ca0e8b3a 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -117,6 +117,55 @@ void AGOSEngine_Feeble::quickLoadOrSave() {
}
#endif
+void AGOSEngine_PN::quickLoadOrSave() {
+ Common::U32String buf;
+ const Common::String filename = genSaveName(_saveLoadSlot);
+ const byte requestedType = _saveLoadType;
+ bool success = false;
+
+ if (requestedType == 2) {
+ Common::InSaveFile *in = _saveFileMan->openForLoading(filename);
+ if (in == nullptr) {
+ buf = Common::U32String::format(_("Failed to load saved game from file:\n\n%s"), filename.c_str());
+ } else {
+ delete in;
+ const int numParams = _dataBase[getlong(_quickptr[6] + 3 * 267)];
+ if (numParams == 0) {
+ addstack(-1);
+ for (int i = 24; i < 32; ++i)
+ _variableArray[i] = 0;
+
+ setposition(267, 0);
+ success = (doline(1) != 0);
+ }
+ if (!success)
+ buf = Common::U32String::format(_("Failed to load saved game from file:\n\n%s"), filename.c_str());
+ }
+ } else if (requestedType == 1) {
+ memset(_saveFile, 0, sizeof(_saveFile));
+ for (uint i = 0; i < 8 && _saveLoadName[i] != 0; ++i)
+ _saveFile[i] = _saveLoadName[i];
+
+ success = (saveFile(filename) != 0);
+ if (!success)
+ buf = Common::U32String::format(_("Failed to save game to file:\n\n%s"), filename.c_str());
+ } else {
+ _saveLoadType = 0;
+ return;
+ }
+
+ if (!success) {
+ GUI::MessageDialog dialog(buf);
+ dialog.runModal();
+ } else if (requestedType == 1) {
+ buf = Common::U32String::format(_("Successfully saved game in file:\n\n%s"), filename.c_str());
+ GUI::TimedMessageDialog dialog(buf, 1500);
+ dialog.runModal();
+ }
+
+ _saveLoadType = 0;
+}
+
// The function uses segments of code from the original game scripts
// to allow quick loading and saving, but isn't perfect.
//
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index 3e1e01f675b..0a4f05f8bd6 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -266,7 +266,11 @@ void AGOSEngine_PN::opn_opcode15() {
pcf((unsigned char)254);
_curWindow = x;
- _xofs = (8 * _windowArray[_curWindow]->textLength) / 6 + 1;
+ WindowBlock *window = _windowArray[_curWindow];
+ if (isPnAmigaTextWindow(window))
+ _xofs = window->textColumn;
+ else
+ _xofs = (8 * window->textLength) / 6 + 1;
setScriptReturn(true);
}
@@ -380,9 +384,18 @@ void AGOSEngine_PN::opn_opcode31() {
switch (a) {
case 0:
- getFilename();
- slot = matchSaveGame(_saveFile, countSaveGames());
- bf = genSaveName(slot);
+ if (_saveLoadType == 2) {
+ memset(_saveFile, 0, sizeof(_saveFile));
+ for (uint i = 0; i < 8 && _saveLoadName[i] != 0; ++i)
+ _saveFile[i] = _saveLoadName[i];
+ slot = _saveLoadSlot;
+ bf = genSaveName(slot);
+ _saveLoadType = 0;
+ } else {
+ getFilename();
+ slot = matchSaveGame(_saveFile, countSaveGames());
+ bf = genSaveName(slot);
+ }
break;
case 1:
bf = "pn.sav";
@@ -419,12 +432,20 @@ void AGOSEngine_PN::opn_opcode32() {
uint16 curSlot = countSaveGames();
switch (a) {
case 0:
- getFilename();
- slot = matchSaveGame(_saveFile, curSlot);
- if (slot != -1)
- bf = genSaveName(slot);
- else
- bf = genSaveName(curSlot);
+ if (_saveLoadType == 1) {
+ memset(_saveFile, 0, sizeof(_saveFile));
+ for (uint i = 0; i < 8 && _saveLoadName[i] != 0; ++i)
+ _saveFile[i] = _saveLoadName[i];
+ bf = genSaveName(_saveLoadSlot);
+ _saveLoadType = 0;
+ } else {
+ getFilename();
+ slot = matchSaveGame(_saveFile, curSlot);
+ if (slot != -1)
+ bf = genSaveName(slot);
+ else
+ bf = genSaveName(curSlot);
+ }
break;
case 1:
bf = "pn.sav";
@@ -755,7 +776,7 @@ int AGOSEngine_PN::inventoryOn(int val) {
int AGOSEngine_PN::inventoryOff() {
if (_videoLockOut & 0x10) {
- _windowArray[2]->textColor = 15;
+ _windowArray[2]->textColor = isPnAmiga() ? 14 : 15;
restoreBlock(48, 2, 272, 130);
diff --git a/engines/agos/string_pn.cpp b/engines/agos/string_pn.cpp
index e974ae551f6..23caf11e239 100644
--- a/engines/agos/string_pn.cpp
+++ b/engines/agos/string_pn.cpp
@@ -124,6 +124,8 @@ void AGOSEngine_PN::pcl(const char *s) {
}
void AGOSEngine_PN::pcf(uint8 ch) {
+ WindowBlock *window = _windowArray[_curWindow];
+ const bool usePnAmigaWrap = isPnAmigaTextWindow(window);
int ct = 0;
if (ch == '[')
ch = '\n';
@@ -131,9 +133,62 @@ void AGOSEngine_PN::pcf(uint8 ch) {
return; /* Trap any C EOS chrs */
if (ch == 255) {
_bp = 0;
- _xofs = 0;
+ _xofs = usePnAmigaWrap ? window->textColumn : 0;
return; /* pcf(255) initializes the routine */
} /* pcf(254) flushes its working _buffer */
+
+ if (usePnAmigaWrap) {
+ const int wrapLimit = (int)getPnAmigaTextPlaneWidth(window);
+ int pendingWidth = 0;
+
+ _xofs = window->textColumn;
+ if (ch != 254) {
+ pendingWidth = 0;
+ for (int i = 0; i < _bp; ++i) {
+ const byte bufferedChar = (byte)_buffer[i];
+ if (bufferedChar >= 32)
+ pendingWidth += getPnAmigaGlyphAdvance(bufferedChar);
+ }
+ if ((ch != 32) || (pendingWidth + _xofs != wrapLimit))
+ _buffer[_bp++] = ch;
+ }
+ if ((ch != 254) && (!Common::isSpace(ch)) && (_bp < 60))
+ return;
+
+ pendingWidth = 0;
+ for (int i = 0; i < _bp; ++i) {
+ const byte bufferedChar = (byte)_buffer[i];
+ if (bufferedChar >= 32)
+ pendingWidth += getPnAmigaGlyphAdvance(bufferedChar);
+ }
+ if (pendingWidth + _xofs > wrapLimit && _bp > 0 && _buffer[_bp - 1] == ' ') {
+ const int trimmedWidth = pendingWidth - getPnAmigaGlyphAdvance(' ');
+ if (trimmedWidth + _xofs <= wrapLimit) {
+ _buffer[_bp - 1] = 0;
+ pcl(_buffer);
+ windowPutChar(window, '\n');
+ _sb[0] = '\0';
+ _bp = 0;
+ _xofs = kPnAmigaTextStartX;
+ return;
+ }
+ }
+ if (pendingWidth + _xofs > wrapLimit) {
+ pcl("\n");
+ if (_buffer[0] == ' ')
+ ct = 1;
+ _xofs = kPnAmigaTextStartX;
+ }
+ _buffer[_bp] = 0;
+ pcl(_buffer + ct);
+ if (ch == '\n')
+ _xofs = kPnAmigaTextStartX;
+ else
+ _xofs = window->textColumn;
+ _bp = 0;
+ return;
+ }
+
if (ch != 254) {
if ((ch != 32) || (_bp + _xofs != 50))
_buffer[_bp++] = ch;
diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp
index 15475838d56..2871bb9d594 100644
--- a/engines/agos/window.cpp
+++ b/engines/agos/window.cpp
@@ -41,6 +41,45 @@ uint AGOSEngine::getWindowNum(WindowBlock *window) {
return 0; // for compilers that don't support NORETURN
}
+bool AGOSEngine::isPnAmigaMainTextWindow(const WindowBlock *window) const {
+ return window != nullptr && isPnAmiga() && window->x == 0 && window->width == 40 && window->y == kPnAmigaMainTextTop;
+}
+
+bool AGOSEngine::isPnAmigaInputWindow(const WindowBlock *window) const {
+ return window != nullptr && isPnAmiga() && window->x == 0 && window->width == 40 && window->y == kPnAmigaInputTop;
+}
+
+bool AGOSEngine::isPnAmigaTextWindow(const WindowBlock *window) const {
+ return isPnAmigaMainTextWindow(window) || isPnAmigaInputWindow(window);
+}
+
+uint16 AGOSEngine::getPnAmigaWindowInteriorHeight(const WindowBlock *window) const {
+ if (window == nullptr)
+ return 0;
+
+ uint16 pixelHeight = window->height * 8;
+ if (window->x == 0 && window->width == 40 && window->y == 136)
+ pixelHeight = 88;
+ else if (window->x == 0 && window->width == 40 && window->y == 224)
+ pixelHeight = 16;
+ return (pixelHeight > 2) ? pixelHeight - 2 : 0;
+}
+
+uint16 AGOSEngine::getPnAmigaTextPlaneWidth(const WindowBlock *window) const {
+ if (window == nullptr)
+ return 0;
+
+ if (isPnAmigaTextWindow(window))
+ return kPnAmigaTextPlaneWidth;
+ return window->width * 16 - 2;
+}
+
+uint16 AGOSEngine::getPnAmigaTextLineStep() const {
+ if (usePnAmigaDoubleHeightTopaz())
+ return getPnAmigaGlyphHeight();
+ return 9;
+}
+
WindowBlock *AGOSEngine::openWindow(uint x, uint y, uint w, uint h, uint flags, uint fillColor, uint textColor) {
WindowBlock *window;
@@ -67,6 +106,8 @@ WindowBlock *AGOSEngine::openWindow(uint x, uint y, uint w, uint h, uint flags,
// Characters are 6 pixels (except Japanese: when downscaled, 1-byte characters are 4 pixels, 2-byte characters are 8 pixels)
if (getGameType() == GType_ELVIRA2)
window->textMaxLength = (window->width * 8 - 4) / 6;
+ else if (isPnAmigaTextWindow(window))
+ window->textMaxLength = getPnAmigaTextPlaneWidth(window) / getPnAmigaGlyphAdvance(' ');
else if (getGameType() == GType_PN)
window->textMaxLength = window->width * 8 / 6 + 1;
else if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformPC98)
@@ -119,6 +160,61 @@ void AGOSEngine::clearWindow(WindowBlock *window) {
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
window->textLength = 0;
window->scrollY = 0;
+
+ if (isPnAmigaTextWindow(window)) {
+ window->textColumn = kPnAmigaTextStartX;
+ clearPnAmigaTextPlane(window);
+ if (isPnAmigaInputWindow(window)) {
+ const int16 top = ((int16)getPnAmigaWindowInteriorHeight(window) - (int16)getPnAmigaGlyphHeight()) / 2;
+ window->textRow = MAX((int16)0, top);
+ }
+ compositePnAmigaTextPlane(window);
+ }
+}
+
+void AGOSEngine::clearPnAmigaTextPlane(WindowBlock *window) {
+ ensurePnAmigaTextPlanes();
+ PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
+ if (plane == nullptr || plane->pixels == nullptr)
+ return;
+ memset(plane->pixels, window->fillColor, plane->width * plane->height);
+}
+
+void AGOSEngine::compositePnAmigaTextPlane(WindowBlock *window) {
+ const PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
+ if (plane == nullptr || plane->pixels == nullptr || _scaleBuf == nullptr)
+ return;
+
+ Graphics::Surface *screen = _scaleBuf;
+ const uint16 dstLeft = window->x * 16 + 1;
+ const uint16 dstTop = window->y + 1;
+ const uint16 dstWidth = MIN<uint16>(getPnAmigaTextPlaneWidth(window), plane->width);
+ const uint16 dstHeight = MIN<uint16>(getPnAmigaWindowInteriorHeight(window), plane->height);
+
+ for (uint16 y = 0; y < dstHeight; ++y) {
+ byte *dst = (byte *)screen->getBasePtr(dstLeft, dstTop + y);
+ const byte *src = plane->pixels + y * plane->width;
+ memcpy(dst, src, dstWidth);
+ }
+
+ Common::Rect dirtyRect(0, 136, 320, _screenHeight);
+ updateBackendSurface(&dirtyRect);
+}
+
+void AGOSEngine::scrollPnAmigaTextPlane(WindowBlock *window) {
+ PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
+ if (plane == nullptr || plane->pixels == nullptr)
+ return;
+
+ const uint16 step = getPnAmigaTextLineStep();
+ if (plane->height > step) {
+ memmove(plane->pixels, plane->pixels + plane->width * step, plane->width * (plane->height - step));
+ memset(plane->pixels + plane->width * (plane->height - step), window->fillColor, plane->width * step);
+ } else {
+ memset(plane->pixels, window->fillColor, plane->width * plane->height);
+ }
+
+ compositePnAmigaTextPlane(window);
}
#ifdef ENABLE_AGOS2
@@ -144,6 +240,30 @@ void AGOSEngine_Feeble::colorWindow(WindowBlock *window) {
void AGOSEngine::colorWindow(WindowBlock *window) {
uint16 y, h;
+ uint16 x, w;
+
+ if (isPnAmigaTextWindow(window)) {
+ x = window->x * 16 + 1;
+ y = window->y + 1;
+ w = window->width * 16 - 2;
+ h = getPnAmigaWindowInteriorHeight(window);
+ _videoLockOut |= 0x8000;
+
+ Graphics::Surface *screen = _scaleBuf;
+ byte *dst = (byte *)screen->getBasePtr(x, y);
+
+ do {
+ memset(dst, window->fillColor, w);
+ dst += screen->pitch;
+ } while (--h);
+
+ Common::Rect dirtyRect(0, 136, kPnAmigaLowresWidth, _screenHeight);
+ updateBackendSurface(&dirtyRect);
+
+ _videoLockOut &= ~0x8000;
+ drawPnAmigaTextWindowBorders();
+ return;
+ }
y = window->y;
h = window->height * 8;
@@ -202,6 +322,13 @@ void AGOSEngine::resetWindow(WindowBlock *window) {
void AGOSEngine::restoreWindow(WindowBlock *window) {
_videoLockOut |= 0x8000;
+ if (isPnAmigaTextWindow(window)) {
+ _videoLockOut &= ~0x8000;
+ colorWindow(window);
+ compositePnAmigaTextPlane(window);
+ return;
+ }
+
if (getGameType() == GType_FF || getGameType() == GType_PP) {
restoreBlock(window->x, window->y, window->x + window->width, window->y + window->height);
} else if (getGameType() == GType_SIMON2) {
@@ -290,8 +417,14 @@ void AGOSEngine::waitWindow(WindowBlock *window) {
HitArea *ha;
const char *message;
- window->textColumn = (window->width / 2) - 3;
- window->textRow = window->height - 1;
+ if (isPnAmigaTextWindow(window)) {
+ const uint16 buttonWidth = getPnAmigaGlyphAdvance(' ') * 6;
+ window->textColumn = MAX<int16>((int16)kPnAmigaTextStartX, ((int16)getPnAmigaTextPlaneWidth(window) - (int16)buttonWidth) / 2);
+ window->textRow = MAX<int16>(0, (int16)getPnAmigaWindowInteriorHeight(window) - (int16)getPnAmigaGlyphHeight());
+ } else {
+ window->textColumn = (window->width / 2) - 3;
+ window->textRow = window->height - 1;
+ }
window->textLength = 0;
_forceAscii = true;
@@ -301,10 +434,16 @@ void AGOSEngine::waitWindow(WindowBlock *window) {
_forceAscii = false;
ha = findEmptyHitArea();
- ha->x = (window->width / 2 + window->x - 3) * 8;
- ha->y = window->height * 8 + window->y - 8;
- ha->width = 48;
- ha->height = 8;
+ if (isPnAmigaTextWindow(window)) {
+ ha->x = window->x * 8 + window->textColumn / 2;
+ ha->y = window->y + getPnAmigaWindowInteriorHeight(window) + 2 - getPnAmigaGlyphHeight();
+ ha->width = getPnAmigaGlyphAdvance(' ') * 3;
+ } else {
+ ha->x = (window->width / 2 + window->x - 3) * 8;
+ ha->y = window->height * 8 + window->y - 8;
+ ha->width = 48;
+ }
+ ha->height = isPnAmiga() ? getPnAmigaGlyphHeight() : 8;
ha->flags = kBFBoxInUse;
ha->id = 0x7FFF;
ha->priority = 999;
diff --git a/graphics/fonts/amigafont.cpp b/graphics/fonts/amigafont.cpp
index 9911fb80961..d464f48282e 100644
--- a/graphics/fonts/amigafont.cpp
+++ b/graphics/fonts/amigafont.cpp
@@ -194,6 +194,107 @@ static const byte amigaTopazFont[2600] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf2
};
+// Topaz 9
+static const byte amigaTopaz9Font[] = {
+ 0x00, 0x09, 0x08, 0x41, 0x00, 0x0a, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x20, 0x7f, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x52, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x04, 0x82, 0x00, 0x00, 0x05, 0x42,
+ 0x6c, 0xd9, 0x86, 0x00, 0x3c, 0x67, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x18, 0xf9, 0xf0, 0xf7,
+ 0xf3, 0xdf, 0xdf, 0x3e, 0x00, 0xc0, 0x30, 0xf9, 0xf8, 0x63, 0xf8, 0xfb, 0xf3, 0xff, 0xfc, 0xfb,
+ 0x1f, 0xe1, 0xf8, 0xfe, 0x20, 0x70, 0xcf, 0x3f, 0x8f, 0x3f, 0x8f, 0xbf, 0xf1, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xff, 0xfe, 0x07, 0x8c, 0x00, 0x60, 0x0e, 0x00, 0x01, 0xc0, 0x0f, 0x00, 0x70, 0x30, 0x3e,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0,
+ 0xe6, 0x1e, 0xfc, 0xd9, 0x9f, 0xe3, 0x66, 0x6c, 0x33, 0x30, 0xc0, 0x00, 0x01, 0xb1, 0xb9, 0x8f,
+ 0x19, 0xb6, 0x06, 0x18, 0xf1, 0xe3, 0xd9, 0x80, 0x19, 0x8f, 0x0c, 0xf1, 0x8d, 0x8d, 0x99, 0x8d,
+ 0x8d, 0x8f, 0x19, 0x80, 0xd8, 0xd8, 0x30, 0xf8, 0xd9, 0x98, 0xd9, 0x98, 0xd8, 0xe6, 0x71, 0xe1,
+ 0xe1, 0xb3, 0x61, 0xe3, 0x63, 0x01, 0x9e, 0x00, 0x60, 0x06, 0x00, 0x00, 0xc0, 0x19, 0x80, 0x30,
+ 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x19, 0x99, 0x9c, 0x78, 0xf0, 0x3f, 0xf0, 0x66, 0x64, 0xd8, 0x19, 0xe0, 0xc0, 0x00, 0x03, 0x33,
+ 0x98, 0x0c, 0x1b, 0x37, 0xec, 0x00, 0xf1, 0xe3, 0xdb, 0x3f, 0xcc, 0x0f, 0x3c, 0xf1, 0x8f, 0x01,
+ 0x8d, 0x81, 0x83, 0x03, 0x19, 0x80, 0xd9, 0x98, 0x39, 0xfc, 0xf0, 0xd8, 0xf0, 0xd8, 0xdc, 0x06,
+ 0x31, 0xb3, 0x61, 0x9e, 0x33, 0x46, 0x61, 0x81, 0xb3, 0x00, 0x37, 0xc6, 0xe7, 0xce, 0xcf, 0x98,
+ 0x3d, 0xb7, 0x70, 0x76, 0x36, 0xc6, 0xfc, 0xfb, 0x79, 0xf7, 0xb9, 0xff, 0xd8, 0xd8, 0x78, 0x78,
+ 0xf0, 0xff, 0x99, 0x98, 0x01, 0xe0, 0x60, 0x19, 0x9f, 0x0c, 0x7b, 0x18, 0x1f, 0xff, 0xf8, 0xff,
+ 0x06, 0x3f, 0x98, 0x38, 0xf6, 0x30, 0x3f, 0xc1, 0x9f, 0x3f, 0x06, 0x00, 0x06, 0x3b, 0x6d, 0x99,
+ 0xfb, 0x01, 0x8d, 0xf1, 0xf3, 0x1f, 0xf9, 0x80, 0xdf, 0x18, 0x3f, 0xf6, 0xf0, 0xdf, 0xb0, 0xdf,
+ 0x87, 0x06, 0x31, 0xb3, 0x6d, 0x8c, 0x1e, 0x0c, 0x60, 0xc1, 0xe1, 0x80, 0x00, 0x67, 0x3c, 0x79,
+ 0xd8, 0xfc, 0x63, 0x39, 0xb0, 0x36, 0x66, 0xef, 0xc7, 0x8d, 0x8f, 0x19, 0xcf, 0x03, 0x18, 0xd8,
+ 0x7b, 0x6d, 0xb0, 0xe3, 0x71, 0x8e, 0x01, 0x86, 0x60, 0x3f, 0xc1, 0x98, 0xce, 0x18, 0x19, 0xe0,
+ 0xc0, 0x00, 0x0c, 0x39, 0x98, 0xc0, 0x1f, 0xf8, 0x3c, 0x63, 0x31, 0x83, 0x03, 0x00, 0x0c, 0x63,
+ 0x3d, 0xf9, 0x8f, 0x01, 0x8d, 0x81, 0x83, 0x0f, 0x19, 0x98, 0xd9, 0x98, 0x76, 0xf3, 0xf0, 0xd8,
+ 0x30, 0xd9, 0x81, 0xc6, 0x31, 0x9e, 0x7f, 0x9e, 0x0c, 0x18, 0xe0, 0x61, 0x80, 0x00, 0x03, 0xe6,
+ 0x3c, 0x18, 0xdf, 0xd8, 0x63, 0x31, 0xb0, 0x37, 0xc6, 0xdb, 0xc7, 0x8d, 0x8f, 0x19, 0x8d, 0xf3,
+ 0x18, 0xcc, 0xdb, 0x67, 0x19, 0x8e, 0x19, 0x98, 0x00, 0x1f, 0x00, 0x19, 0xbf, 0x33, 0xc6, 0x0c,
+ 0x33, 0x30, 0xc3, 0x00, 0xd8, 0x31, 0x99, 0x8f, 0x18, 0x36, 0x3c, 0x66, 0x31, 0x86, 0xd9, 0xbf,
+ 0xd8, 0x03, 0x03, 0x0d, 0x8d, 0x8d, 0x99, 0x8d, 0x81, 0x8f, 0x19, 0x98, 0xd8, 0xd8, 0xf0, 0xf1,
+ 0xd9, 0x98, 0x19, 0x98, 0xd8, 0xc6, 0x31, 0x9e, 0x73, 0xb3, 0x0c, 0x31, 0xe0, 0x31, 0x80, 0x00,
+ 0x0c, 0x66, 0x3c, 0x78, 0xd8, 0x18, 0x3e, 0x31, 0xb0, 0x36, 0x66, 0xc3, 0xc7, 0x8d, 0xf9, 0xf9,
+ 0x80, 0x1b, 0x38, 0xc7, 0x8c, 0xcd, 0x8f, 0x18, 0x99, 0x98, 0x00, 0x79, 0x60, 0x19, 0x8c, 0x63,
+ 0x7b, 0x07, 0xe0, 0x00, 0x03, 0x00, 0xf0, 0x1f, 0x7f, 0xfd, 0xf0, 0xfb, 0xe7, 0xc6, 0x1f, 0x3c,
+ 0xd8, 0xc0, 0x30, 0x61, 0xf3, 0x0f, 0xf8, 0xfb, 0xf3, 0xff, 0xe0, 0xff, 0x1f, 0xef, 0xb8, 0xff,
+ 0xf0, 0xf0, 0xcf, 0x3e, 0x0f, 0xb8, 0x6f, 0x8f, 0x1f, 0x8c, 0x61, 0xe1, 0x9e, 0x7f, 0xf8, 0x1f,
+ 0x80, 0x00, 0x07, 0xb3, 0xe7, 0xcf, 0x6f, 0xbc, 0x03, 0x71, 0xfe, 0x3e, 0x3f, 0xc3, 0xc6, 0xf9,
+ 0x80, 0x1b, 0xc3, 0xf1, 0xcf, 0x63, 0x0c, 0xd8, 0xc6, 0x3f, 0x8f, 0xf0, 0x01, 0xe0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x03, 0xe0, 0x00, 0x00,
+ 0x00, 0x03, 0xc0, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, 0x0a,
+ 0x00, 0x08, 0x00, 0x12, 0x00, 0x07, 0x00, 0x19, 0x00, 0x07, 0x00, 0x20, 0x00, 0x08, 0x00, 0x28,
+ 0x00, 0x03, 0x00, 0x2b, 0x00, 0x05, 0x00, 0x30, 0x00, 0x05, 0x00, 0x35, 0x00, 0x08, 0x00, 0x3d,
+ 0x00, 0x08, 0x00, 0x45, 0x00, 0x03, 0x00, 0x48, 0x00, 0x08, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52,
+ 0x00, 0x08, 0x00, 0x5a, 0x00, 0x07, 0x00, 0x61, 0x00, 0x06, 0x00, 0x67, 0x00, 0x07, 0x00, 0x6e,
+ 0x00, 0x07, 0x00, 0x75, 0x00, 0x08, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x84, 0x00, 0x07, 0x00, 0x8b,
+ 0x00, 0x07, 0x00, 0x92, 0x00, 0x07, 0x00, 0x99, 0x00, 0x07, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2,
+ 0x00, 0x03, 0x00, 0xa5, 0x00, 0x05, 0x00, 0xaa, 0x00, 0x08, 0x00, 0xb2, 0x00, 0x05, 0x00, 0xb7,
+ 0x00, 0x07, 0x00, 0xbe, 0x00, 0x08, 0x00, 0xc6, 0x00, 0x08, 0x00, 0xce, 0x00, 0x08, 0x00, 0xd6,
+ 0x00, 0x08, 0x00, 0xde, 0x00, 0x08, 0x00, 0xe6, 0x00, 0x08, 0x00, 0xee, 0x00, 0x08, 0x00, 0xf6,
+ 0x00, 0x08, 0x00, 0xfe, 0x00, 0x07, 0x01, 0x05, 0x00, 0x06, 0x01, 0x0b, 0x00, 0x07, 0x01, 0x12,
+ 0x00, 0x08, 0x01, 0x1a, 0x00, 0x08, 0x01, 0x22, 0x00, 0x08, 0x01, 0x2a, 0x00, 0x08, 0x01, 0x32,
+ 0x00, 0x08, 0x01, 0x3a, 0x00, 0x08, 0x01, 0x42, 0x00, 0x08, 0x01, 0x4a, 0x00, 0x09, 0x01, 0x53,
+ 0x00, 0x07, 0x01, 0x5a, 0x00, 0x08, 0x01, 0x62, 0x00, 0x07, 0x01, 0x69, 0x00, 0x08, 0x01, 0x71,
+ 0x00, 0x08, 0x01, 0x79, 0x00, 0x08, 0x01, 0x81, 0x00, 0x08, 0x01, 0x89, 0x00, 0x08, 0x01, 0x91,
+ 0x00, 0x04, 0x01, 0x95, 0x00, 0x08, 0x01, 0x9d, 0x00, 0x04, 0x01, 0xa1, 0x00, 0x08, 0x01, 0xa9,
+ 0x00, 0x08, 0x01, 0xb1, 0x00, 0x03, 0x01, 0xb4, 0x00, 0x08, 0x01, 0xbc, 0x00, 0x08, 0x01, 0xc4,
+ 0x00, 0x07, 0x01, 0xcb, 0x00, 0x08, 0x01, 0xd3, 0x00, 0x07, 0x01, 0xda, 0x00, 0x07, 0x01, 0xe1,
+ 0x00, 0x08, 0x01, 0xe9, 0x00, 0x08, 0x01, 0xf1, 0x00, 0x04, 0x01, 0xf5, 0x00, 0x07, 0x01, 0xfc,
+ 0x00, 0x08, 0x02, 0x04, 0x00, 0x04, 0x02, 0x08, 0x00, 0x08, 0x02, 0x10, 0x00, 0x07, 0x02, 0x17,
+ 0x00, 0x07, 0x02, 0x1e, 0x00, 0x08, 0x02, 0x26, 0x00, 0x08, 0x02, 0x2e, 0x00, 0x08, 0x02, 0x36,
+ 0x00, 0x07, 0x02, 0x3d, 0x00, 0x06, 0x02, 0x43, 0x00, 0x08, 0x02, 0x4b, 0x00, 0x08, 0x02, 0x53,
+ 0x00, 0x08, 0x02, 0x5b, 0x00, 0x07, 0x02, 0x62, 0x00, 0x08, 0x02, 0x6a, 0x00, 0x07, 0x02, 0x71,
+ 0x00, 0x06, 0x02, 0x77, 0x00, 0x02, 0x02, 0x79, 0x00, 0x06, 0x02, 0x7f, 0x00, 0x08, 0x02, 0x87,
+ 0x00, 0x08, 0x00, 0x0a, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09,
+ 0x00, 0x07, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x07, 0x00, 0x09, 0x00, 0x06,
+ 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08,
+ 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07,
+ 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09,
+ 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09,
+ 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x09, 0x00, 0x08, 0x00, 0x09,
+ 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x00, 0x09,
+ 0x00, 0x09, 0x00, 0x06, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08,
+ 0x00, 0x09, 0x00, 0x09, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x07, 0x00, 0x09, 0x00, 0x08,
+ 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x07, 0x00, 0x09, 0x00, 0x09,
+ 0x00, 0x09, 0x00, 0x08, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x06, 0x00, 0x08, 0x00, 0x09,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01,
+ 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03,
+ 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01,
+ 0x00, 0x01,
+};
+
AmigaFont::AmigaFont(Common::SeekableReadStream *stream) {
Common::SeekableReadStream *tmp;
if (!stream) {
@@ -243,10 +344,63 @@ AmigaFont::AmigaFont(Common::SeekableReadStream *stream) {
}
}
+AmigaFont::AmigaFont(Topaz9Builtin)
+ : _font(nullptr), _data(nullptr), _charData(nullptr), _charLoc(nullptr), _charSpace(nullptr), _charKern(nullptr),
+ _cp(nullptr), _pitch(0), _maxCharWidth(0) {
+ initFromData(amigaTopaz9Font, sizeof(amigaTopaz9Font), 0);
+}
+
AmigaFont::~AmigaFont() {
free(_data);
}
+void AmigaFont::initFromData(const byte *data, uint32 dataSize, uint32 fontOffset) {
+ _data = (byte *)malloc(dataSize);
+ memcpy(_data, data, dataSize);
+
+ _font = (AmigaDiskFont *)(_data + fontOffset);
+ _font->_ySize = FROM_BE_16(_font->_ySize);
+ _font->_xSize = FROM_BE_16(_font->_xSize);
+ _font->_baseline = FROM_BE_16(_font->_baseline);
+ _font->_modulo = FROM_BE_16(_font->_modulo);
+
+ _charLoc = (CharLoc *)(_data + FROM_BE_32(_font->_charLoc));
+ _charData = _data + FROM_BE_32(_font->_charData);
+
+ _charSpace = nullptr;
+ _charKern = nullptr;
+ _cp = nullptr;
+ _pitch = 0;
+
+ if (_font->_charSpace != 0)
+ _charSpace = (uint16 *)(_data + FROM_BE_32(_font->_charSpace));
+ if (_font->_charKern != 0)
+ _charKern = (uint16 *)(_data + FROM_BE_32(_font->_charKern));
+
+ _maxCharWidth = _font->_xSize;
+ if (_charSpace) {
+ _maxCharWidth = FROM_BE_16(_charSpace[0]);
+ for (int i = _font->_hiChar - _font->_loChar; i > 0; --i) {
+ const int width = FROM_BE_16(_charSpace[i]);
+ if (_maxCharWidth < width)
+ _maxCharWidth = width;
+ }
+ }
+}
+
+bool AmigaFont::isProportional() const {
+ static constexpr byte kAmigaFpfProportional = 0x20;
+ return (_font->_flags & kAmigaFpfProportional) != 0;
+}
+
+int16 AmigaFont::getCharSpace(byte c) const {
+ return (_charSpace == nullptr) ? _font->_xSize : FROM_BE_16(_charSpace[c]);
+}
+
+int16 AmigaFont::getCharKern(byte c) const {
+ return (_charKern == nullptr) ? 0 : FROM_BE_16(_charKern[c]);
+}
+
int AmigaFont::getFontHeight() const {
return _font->_ySize;
}
@@ -271,6 +425,36 @@ uint16 AmigaFont::getOffset(byte c) const {
return FROM_BE_16(_charLoc[c]._offset);
}
+int AmigaFont::getCharAdvanceWidth(uint32 chr) const {
+ const byte mapped = mapChar(chr);
+ return isProportional() ? getCharSpace(mapped) : _font->_xSize;
+}
+
+int AmigaFont::getCharDrawOffset(uint32 chr) const {
+ return getCharKern(mapChar(chr));
+}
+
+int AmigaFont::getCharInkWidth(uint32 chr) const {
+ return getPixels(mapChar(chr));
+}
+
+int AmigaFont::getCharRenderWidth(uint32 chr) const {
+ const int drawOffset = getCharDrawOffset(chr);
+ const int inkWidth = getCharInkWidth(chr);
+ const int advance = getCharAdvanceWidth(chr);
+ int renderWidth = inkWidth;
+
+ if (drawOffset > 0)
+ renderWidth += drawOffset;
+ else if (drawOffset < 0)
+ renderWidth -= drawOffset;
+
+ if (renderWidth < advance)
+ renderWidth = advance;
+
+ return renderWidth;
+}
+
uint32 AmigaFont::mapChar(uint32 c) const {
if (c < _font->_loChar || c > _font->_hiChar)
error("character '%c (%x)' not supported by font", c, c);
diff --git a/graphics/fonts/amigafont.h b/graphics/fonts/amigafont.h
index da917c8ce45..8f4b1672c30 100644
--- a/graphics/fonts/amigafont.h
+++ b/graphics/fonts/amigafont.h
@@ -56,6 +56,12 @@ class AmigaFont : public Font {
};
#include "common/pack-end.h"
+public:
+ enum Topaz9Builtin {
+ kTopaz9Builtin
+ };
+
+private:
AmigaDiskFont *_font;
byte *_data;
byte *_charData;
@@ -68,6 +74,10 @@ class AmigaFont : public Font {
int _maxCharWidth;
private:
+ void initFromData(const byte *data, uint32 dataSize, uint32 fontOffset);
+ bool isProportional() const;
+ int16 getCharSpace(byte c) const;
+ int16 getCharKern(byte c) const;
uint16 getPixels(byte c) const;
uint16 getOffset(byte c) const;
@@ -81,16 +91,21 @@ public:
* Topaz font is used.
*/
AmigaFont(Common::SeekableReadStream *stream = NULL);
+ AmigaFont(Topaz9Builtin);
virtual ~AmigaFont();
virtual int getFontHeight() const;
virtual int getCharWidth(uint32 chr) const;
virtual int getMaxCharWidth() const;
virtual int getKerningOffset(uint32 left, uint32 right) const;
+ int getCharAdvanceWidth(uint32 chr) const;
+ int getCharDrawOffset(uint32 chr) const;
+ int getCharInkWidth(uint32 chr) const;
+ int getCharRenderWidth(uint32 chr) const;
virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
- int getLoChar() { return _font->_loChar; }
- int getHiChar() { return _font->_hiChar; }
+ int getLoChar() const { return _font->_loChar; }
+ int getHiChar() const { return _font->_hiChar; }
};
} // End of namespace Graphics
Commit: aeb375159061ce07b7820303f8e70d18b41a9c9b
https://github.com/scummvm/scummvm/commit/aeb375159061ce07b7820303f8e70d18b41a9c9b
Author: Robert Megone (robert.megone at gmail.com)
Date: 2026-04-13T17:10:32+03:00
Commit Message:
AGOS: Simplify PN Amiga width handling
Changed paths:
engines/agos/agos.cpp
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 0ef6a06a1c2..56d8aa01f18 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -678,9 +678,7 @@ Common::Error AGOSEngine::init() {
_backBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
memset(_backBuf->getPixels(), 0, _backBuf->pitch * _backBuf->h);
_scaleBuf = new Graphics::Surface();
- const uint16 scaleWidth = isPnAmiga() ? 640 : _internalWidth;
- const uint16 scaleHeight = isPnAmiga() ? _screenHeight : _internalHeight;
- _scaleBuf->create(scaleWidth, scaleHeight, Graphics::PixelFormat::createFormatCLUT8());
+ _scaleBuf->create(_internalWidth, isPnAmiga() ? _screenHeight : _internalHeight, Graphics::PixelFormat::createFormatCLUT8());
memset(_scaleBuf->getPixels(), 0, _scaleBuf->pitch * _scaleBuf->h);
}
Commit: 0629e6e22026a3ff7bf98df44f8336841df02190
https://github.com/scummvm/scummvm/commit/0629e6e22026a3ff7bf98df44f8336841df02190
Author: Robert Megone (robert.megone at gmail.com)
Date: 2026-04-13T17:10:32+03:00
Commit Message:
AGOS: Back out of quicksave changes, swallow input instead
Changed paths:
engines/agos/agos.h
engines/agos/event.cpp
engines/agos/saveload.cpp
engines/agos/script_pn.cpp
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index fc054b3cbb8..f4ba808cea7 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -1452,7 +1452,6 @@ public:
void setupGame() override;
void setupOpcodes() override;
void setupVideoOpcodes(VgaOpcodeProc *op) override;
- void quickLoadOrSave() override;
void windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) override;
void saveInventoryPalette();
void applyInventoryPalette();
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index d145cb0febc..b1b84baf9c0 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -490,6 +490,9 @@ void AGOSEngine::delay(uint amount) {
if (event.kbd.keycode >= Common::KEYCODE_0 && event.kbd.keycode <= Common::KEYCODE_9
&& (event.kbd.hasFlags(Common::KBD_ALT) ||
event.kbd.hasFlags(Common::KBD_CTRL))) {
+ if (getGameType() == GType_PN)
+ break;
+
_saveLoadSlot = event.kbd.keycode - Common::KEYCODE_0;
// There is no save slot 0
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index b45ca0e8b3a..9161fc54fab 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -117,55 +117,6 @@ void AGOSEngine_Feeble::quickLoadOrSave() {
}
#endif
-void AGOSEngine_PN::quickLoadOrSave() {
- Common::U32String buf;
- const Common::String filename = genSaveName(_saveLoadSlot);
- const byte requestedType = _saveLoadType;
- bool success = false;
-
- if (requestedType == 2) {
- Common::InSaveFile *in = _saveFileMan->openForLoading(filename);
- if (in == nullptr) {
- buf = Common::U32String::format(_("Failed to load saved game from file:\n\n%s"), filename.c_str());
- } else {
- delete in;
- const int numParams = _dataBase[getlong(_quickptr[6] + 3 * 267)];
- if (numParams == 0) {
- addstack(-1);
- for (int i = 24; i < 32; ++i)
- _variableArray[i] = 0;
-
- setposition(267, 0);
- success = (doline(1) != 0);
- }
- if (!success)
- buf = Common::U32String::format(_("Failed to load saved game from file:\n\n%s"), filename.c_str());
- }
- } else if (requestedType == 1) {
- memset(_saveFile, 0, sizeof(_saveFile));
- for (uint i = 0; i < 8 && _saveLoadName[i] != 0; ++i)
- _saveFile[i] = _saveLoadName[i];
-
- success = (saveFile(filename) != 0);
- if (!success)
- buf = Common::U32String::format(_("Failed to save game to file:\n\n%s"), filename.c_str());
- } else {
- _saveLoadType = 0;
- return;
- }
-
- if (!success) {
- GUI::MessageDialog dialog(buf);
- dialog.runModal();
- } else if (requestedType == 1) {
- buf = Common::U32String::format(_("Successfully saved game in file:\n\n%s"), filename.c_str());
- GUI::TimedMessageDialog dialog(buf, 1500);
- dialog.runModal();
- }
-
- _saveLoadType = 0;
-}
-
// The function uses segments of code from the original game scripts
// to allow quick loading and saving, but isn't perfect.
//
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index 0a4f05f8bd6..90ee4f66f33 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -384,18 +384,9 @@ void AGOSEngine_PN::opn_opcode31() {
switch (a) {
case 0:
- if (_saveLoadType == 2) {
- memset(_saveFile, 0, sizeof(_saveFile));
- for (uint i = 0; i < 8 && _saveLoadName[i] != 0; ++i)
- _saveFile[i] = _saveLoadName[i];
- slot = _saveLoadSlot;
- bf = genSaveName(slot);
- _saveLoadType = 0;
- } else {
- getFilename();
- slot = matchSaveGame(_saveFile, countSaveGames());
- bf = genSaveName(slot);
- }
+ getFilename();
+ slot = matchSaveGame(_saveFile, countSaveGames());
+ bf = genSaveName(slot);
break;
case 1:
bf = "pn.sav";
@@ -432,20 +423,12 @@ void AGOSEngine_PN::opn_opcode32() {
uint16 curSlot = countSaveGames();
switch (a) {
case 0:
- if (_saveLoadType == 1) {
- memset(_saveFile, 0, sizeof(_saveFile));
- for (uint i = 0; i < 8 && _saveLoadName[i] != 0; ++i)
- _saveFile[i] = _saveLoadName[i];
- bf = genSaveName(_saveLoadSlot);
- _saveLoadType = 0;
- } else {
- getFilename();
- slot = matchSaveGame(_saveFile, curSlot);
- if (slot != -1)
- bf = genSaveName(slot);
- else
- bf = genSaveName(curSlot);
- }
+ getFilename();
+ slot = matchSaveGame(_saveFile, curSlot);
+ if (slot != -1)
+ bf = genSaveName(slot);
+ else
+ bf = genSaveName(curSlot);
break;
case 1:
bf = "pn.sav";
Commit: 33894ae5045be959280dec14c124d66fdbc84ce6
https://github.com/scummvm/scummvm/commit/33894ae5045be959280dec14c124d66fdbc84ce6
Author: Robert Megone (robert.megone at gmail.com)
Date: 2026-04-13T17:10:32+03:00
Commit Message:
AGOS: Move topaz 9 double height draw from AGOS to amigafont
Changed paths:
engines/agos/charset-fontdata.cpp
graphics/fonts/amigafont.cpp
graphics/fonts/amigafont.h
diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp
index 14fa4cee8ee..4a350757b77 100644
--- a/engines/agos/charset-fontdata.cpp
+++ b/engines/agos/charset-fontdata.cpp
@@ -3061,47 +3061,6 @@ static inline void pnSqueezeGlyph8Rows(const byte *src8, byte *dst8) {
dst8[i] = pnSqueezeRow(src8[i], anyBit1SetAcrossGlyph);
}
-static void drawPnAmigaDoubleHeightTopazChar(const Graphics::AmigaFont *font, Graphics::Surface *dst, byte chr, int x, int y, byte color) {
- enum {
- kPnAmigaTopazScratchWidth = 16,
- kPnAmigaTopazScratchHeight = 16
- };
-
- const int glyphWidth = font->getCharRenderWidth(chr);
- const int rawHeight = font->getFontHeight();
- const int drawOffset = font->getCharDrawOffset(chr);
- const int glyphLeft = MIN<int>(0, drawOffset);
- const int glyphOriginX = drawOffset - glyphLeft;
- if (glyphWidth <= 0 || rawHeight <= 0)
- return;
- assert(glyphWidth <= kPnAmigaTopazScratchWidth);
- assert(rawHeight <= kPnAmigaTopazScratchHeight);
-
- byte glyphPixels[kPnAmigaTopazScratchWidth * kPnAmigaTopazScratchHeight];
- memset(glyphPixels, 0, sizeof(glyphPixels));
-
- Graphics::Surface glyphSurface;
- glyphSurface.init(glyphWidth, rawHeight, glyphWidth, glyphPixels, Graphics::PixelFormat::createFormatCLUT8());
- font->drawChar(&glyphSurface, chr, glyphOriginX, 0, 1);
-
- for (int srcY = 0; srcY < rawHeight; ++srcY) {
- for (int srcX = 0; srcX < glyphWidth; ++srcX) {
- if (glyphPixels[srcY * glyphWidth + srcX] == 0)
- continue;
-
- const int dstX = x + glyphLeft + srcX;
- if (dstX < 0 || dstX >= dst->w)
- continue;
-
- for (int repeat = 0; repeat < 2; ++repeat) {
- const int dstY = y + srcY * 2 + repeat;
- if (dstY >= 0 && dstY < dst->h)
- *(byte *)dst->getBasePtr(dstX, dstY) = color;
- }
- }
- }
-}
-
void AGOSEngine::drawPnAmigaTopazChar(WindowBlock *window, byte chr) {
PnAmigaTextPlane *plane = getPnAmigaTextPlane(window);
if (plane == nullptr || plane->pixels == nullptr)
@@ -3130,7 +3089,7 @@ void AGOSEngine::drawPnAmigaTopazChar(WindowBlock *window, byte chr) {
return;
if (usePnAmigaDoubleHeightTopaz())
- drawPnAmigaDoubleHeightTopazChar(font, &surface, chr, x, y, window->textColor);
+ font->drawCharDoubleHeight(&surface, chr, x, y, window->textColor);
else
font->drawChar(&surface, chr, x + font->getCharDrawOffset(chr), y, window->textColor);
}
diff --git a/graphics/fonts/amigafont.cpp b/graphics/fonts/amigafont.cpp
index d464f48282e..7a07ca226d1 100644
--- a/graphics/fonts/amigafont.cpp
+++ b/graphics/fonts/amigafont.cpp
@@ -27,8 +27,9 @@
namespace Graphics {
+// Topaz 8
// For the data source and license look into gui/themes/fonts/topaz in ScummVM distribution
-static const byte amigaTopazFont[2600] = {
+static const byte amigaTopaz8Font[2600] = {
0x00, 0x00, 0x03, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x03, 0xe9, 0x00, 0x00, 0x02, 0x79,
0x70, 0xff, 0x4e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
@@ -298,7 +299,7 @@ static const byte amigaTopaz9Font[] = {
AmigaFont::AmigaFont(Common::SeekableReadStream *stream) {
Common::SeekableReadStream *tmp;
if (!stream) {
- tmp = new Common::MemoryReadStream(amigaTopazFont, sizeof(amigaTopazFont), DisposeAfterUse::NO);
+ tmp = new Common::MemoryReadStream(amigaTopaz8Font, sizeof(amigaTopaz8Font), DisposeAfterUse::NO);
} else {
tmp = stream;
}
@@ -497,6 +498,47 @@ void drawCharIntern(byte *ptr, uint32 pitch, int num, int bitOffset, byte *charD
}
}
+void AmigaFont::drawCharDoubleHeight(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ enum {
+ kAmigaFontScratchWidth = 16,
+ kAmigaFontScratchHeight = 16
+ };
+
+ const int glyphWidth = getCharRenderWidth(chr);
+ const int rawHeight = getFontHeight();
+ const int drawOffset = getCharDrawOffset(chr);
+ const int glyphLeft = MIN<int>(0, drawOffset);
+ const int glyphOriginX = drawOffset - glyphLeft;
+ if (glyphWidth <= 0 || rawHeight <= 0)
+ return;
+ assert(glyphWidth <= kAmigaFontScratchWidth);
+ assert(rawHeight <= kAmigaFontScratchHeight);
+
+ byte glyphPixels[kAmigaFontScratchWidth * kAmigaFontScratchHeight];
+ memset(glyphPixels, 0, sizeof(glyphPixels));
+
+ Surface glyphSurface;
+ glyphSurface.init(glyphWidth, rawHeight, glyphWidth, glyphPixels, PixelFormat::createFormatCLUT8());
+ drawChar(&glyphSurface, chr, glyphOriginX, 0, 1);
+
+ for (int srcY = 0; srcY < rawHeight; ++srcY) {
+ for (int srcX = 0; srcX < glyphWidth; ++srcX) {
+ if (glyphPixels[srcY * glyphWidth + srcX] == 0)
+ continue;
+
+ const int dstX = x + glyphLeft + srcX;
+ if (dstX < 0 || dstX >= dst->w)
+ continue;
+
+ for (int repeat = 0; repeat < 2; ++repeat) {
+ const int dstY = y + srcY * 2 + repeat;
+ if (dstY >= 0 && dstY < dst->h)
+ *(byte *)dst->getBasePtr(dstX, dstY) = color;
+ }
+ }
+ }
+}
+
void AmigaFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
chr = mapChar(chr);
diff --git a/graphics/fonts/amigafont.h b/graphics/fonts/amigafont.h
index 8f4b1672c30..c5dc7dac7f6 100644
--- a/graphics/fonts/amigafont.h
+++ b/graphics/fonts/amigafont.h
@@ -88,7 +88,7 @@ public:
* Create font in Amiga format.
*
* @param stream Stream with the font data. If NULL, then the built-in
- * Topaz font is used.
+ * Topaz 8 font is used.
*/
AmigaFont(Common::SeekableReadStream *stream = NULL);
AmigaFont(Topaz9Builtin);
@@ -102,6 +102,7 @@ public:
int getCharDrawOffset(uint32 chr) const;
int getCharInkWidth(uint32 chr) const;
int getCharRenderWidth(uint32 chr) const;
+ void drawCharDoubleHeight(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
int getLoChar() const { return _font->_loChar; }
More information about the Scummvm-git-logs
mailing list