[Scummvm-git-logs] scummvm master -> 61223eba5e2177e85a6461525d457e8cef18fe65
bluegr
noreply at scummvm.org
Thu May 14 16:00:23 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
61223eba5e SCUMM: Don't pack fonts < 8bpp
Commit: 61223eba5e2177e85a6461525d457e8cef18fe65
https://github.com/scummvm/scummvm/commit/61223eba5e2177e85a6461525d457e8cef18fe65
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-05-14T19:00:18+03:00
Commit Message:
SCUMM: Don't pack fonts < 8bpp
This partially reverts commit ea405356 which introduced a well meant
memory optimization for fonts which can be packed into small chunks but
on the other hand introduced a huge performance bottleneck because now
for every character three nested loops must be iterated.
This is visible in e.g. COMI's intro, as soon as Guybrush starts talking
with subtitles enabled, FPS falls into single digits numbers on Atari
(68060 at 66 MHz).
Changed paths:
engines/scumm/nut_renderer.cpp
engines/scumm/nut_renderer.h
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index 31420030686..40dabc98a64 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -30,9 +30,7 @@ namespace Scumm {
NutRenderer::NutRenderer(ScummEngine *vm, const char *filename) :
_vm(vm),
_numChars(0),
- _maxCharSize(0),
_fontHeight(0),
- _charBuffer(0),
_decodedData(0),
_2byteColorTable(0),
_2byteShadowXOffsetTable(0),
@@ -53,7 +51,6 @@ NutRenderer::NutRenderer(ScummEngine *vm, const char *filename) :
}
NutRenderer::~NutRenderer() {
- delete[] _charBuffer;
delete[] _decodedData;
delete[] _2byteColorTable;
}
@@ -62,8 +59,6 @@ void smushDecodeRLE(byte *dst, const byte *src, int left, int top, int width, in
void NutRenderer::codec1(byte *dst, const byte *src, int width, int height, int pitch) {
smushDecodeRLE(dst, src, 0, 0, width, height, pitch);
- for (int i = 0; i < width * height; i++)
- _paletteMap[dst[i]] = 1;
}
void NutRenderer::codec21(byte *dst, const byte *src, int width, int height, int pitch) {
@@ -88,9 +83,6 @@ void NutRenderer::codec21(byte *dst, const byte *src, int width, int height, int
// src bytes equal to 255 are replaced by 0 in dst
// src bytes equal to 1 are replaced by a color passed as an argument in the original function
// other src bytes values are copied as-is
- for (int i = 0; i < w; i++) {
- _paletteMap[src[i]] = 1;
- }
memcpy(dst, src, w);
dst += w;
src += w;
@@ -134,16 +126,11 @@ void NutRenderer::loadFont(const char *filename) {
uint32 decodedLength = 0;
int l;
- _paletteMap = new byte[256]();
-
for (l = 0; l < _numChars; l++) {
offset += READ_BE_UINT32(dataSrc + offset + 4) + 16;
int width = READ_LE_UINT16(dataSrc + offset + 14);
_fontHeight = READ_LE_UINT16(dataSrc + offset + 16);
- int size = width * _fontHeight;
- decodedLength += size;
- if (size > _maxCharSize)
- _maxCharSize = size;
+ decodedLength += width * _fontHeight;
}
debug(1, "NutRenderer::loadFont('%s') - decodedLength = %d", filename, decodedLength);
@@ -177,11 +164,9 @@ void NutRenderer::loadFont(const char *filename) {
// with a default color first.
if (codec == 44) {
memset(_chars[l].src, kSmush44TransparentColor, _chars[l].width * _chars[l].height);
- _paletteMap[kSmush44TransparentColor] = 1;
_chars[l].transparency = kSmush44TransparentColor;
} else {
memset(_chars[l].src, kDefaultTransparentColor, _chars[l].width * _chars[l].height);
- _paletteMap[kDefaultTransparentColor] = 1;
_chars[l].transparency = kDefaultTransparentColor;
}
@@ -199,80 +184,7 @@ void NutRenderer::loadFont(const char *filename) {
}
}
- // We have decoded the font. Now let's see if we can re-compress it to
- // a more compact format. Start by counting the number of colors.
-
- int numColors = 0;
- for (l = 0; l < 256; l++) {
- if (_paletteMap[l]) {
- if (numColors < ARRAYSIZE(_palette)) {
- _paletteMap[l] = numColors;
- _palette[numColors] = l;
- }
- numColors++;
- }
- }
-
- // Now _palette contains all the used colors, and _paletteMap maps the
- // real color to the palette index.
-
- if (numColors <= 2)
- _bpp = 1;
- else if (numColors <= 4)
- _bpp = 2;
- else if (numColors <= 16)
- _bpp = 4;
- else
- _bpp = 8;
-
- if (_bpp < 8) {
- int compressedLength = 0;
- for (l = 0; l < 256; l++) {
- compressedLength += (((_bpp * _chars[l].width + 7) / 8) * _chars[l].height);
- }
-
- debug(1, "NutRenderer::loadFont('%s') - compressedLength = %d (%d bpp)", filename, compressedLength, _bpp);
-
- byte *compressedData = new byte[compressedLength]();
-
- offset = 0;
-
- for (l = 0; l < 256; l++) {
- byte *src = _chars[l].src;
- byte *dst = compressedData + offset;
- int srcPitch = _chars[l].width;
- int dstPitch = (_bpp * _chars[l].width + 7) / 8;
-
- for (int h = 0; h < _chars[l].height; h++) {
- byte bit = 0x80;
- byte *nextDst = dst + dstPitch;
- for (int w = 0; w < srcPitch; w++) {
- byte color = _paletteMap[src[w]];
- for (int i = 0; i < _bpp; i++) {
- if (color & (1 << i))
- *dst |= bit;
- bit >>= 1;
- }
- if (!bit) {
- bit = 0x80;
- dst++;
- }
- }
- src += srcPitch;
- dst = nextDst;
- }
- _chars[l].src = compressedData + offset;
- offset += (dstPitch * _chars[l].height);
- }
-
- delete[] _decodedData;
- _decodedData = compressedData;
-
- _charBuffer = new byte[_maxCharSize];
- }
-
delete[] dataSrc;
- delete[] _paletteMap;
}
int NutRenderer::getCharWidth(byte c) const {
@@ -295,53 +207,10 @@ int NutRenderer::getCharHeight(byte c) const {
return _chars[c].height;
}
-byte *NutRenderer::unpackChar(byte c) {
- if (_bpp == 8)
- return _chars[c].src;
-
- byte *src = _chars[c].src;
- int pitch = (_bpp * _chars[c].width + 7) / 8;
-
- for (int ty = 0; ty < _chars[c].height; ty++) {
- for (int tx = 0; tx < _chars[c].width; tx++) {
- byte val;
- int offset;
- byte bit;
-
- switch (_bpp) {
- case 1:
- offset = tx / 8;
- bit = 0x80 >> (tx % 8);
- break;
- case 2:
- offset = tx / 4;
- bit = 0x80 >> (2 * (tx % 4));
- break;
- default:
- offset = tx / 2;
- bit = 0x80 >> (4 * (tx % 2));
- break;
- }
-
- val = 0;
-
- for (int i = 0; i < _bpp; i++) {
- if (src[offset] & (bit >> i))
- val |= (1 << i);
- }
-
- _charBuffer[ty * _chars[c].width + tx] = _palette[val];
- }
- src += pitch;
- }
-
- return _charBuffer;
-}
-
void NutRenderer::drawFrame(byte *dst, int c, int x, int y) {
const int width = MIN((int)_chars[c].width, _vm->_screenWidth - x);
const int height = MIN((int)_chars[c].height, _vm->_screenHeight - y);
- const byte *src = unpackChar(c);
+ const byte *src = _chars[c].src;
const int srcPitch = _chars[c].width;
byte bits = 0;
@@ -378,7 +247,7 @@ int NutRenderer::drawCharV7(byte *buffer, Common::Rect &clipRect, int x, int y,
int height = MIN((int)_chars[chr].height, clipRect.bottom - y);
int minX = x < clipRect.left ? clipRect.left - x : 0;
int minY = y < clipRect.top ? clipRect.top - y : 0;
- const byte *src = unpackChar(chr);
+ const byte *src = _chars[chr].src;
byte *dst = buffer + pitch * y + x;
if (width <= 0 || height <= 0)
diff --git a/engines/scumm/nut_renderer.h b/engines/scumm/nut_renderer.h
index 350071f7fc1..c17457b2dcb 100644
--- a/engines/scumm/nut_renderer.h
+++ b/engines/scumm/nut_renderer.h
@@ -40,14 +40,9 @@ protected:
ScummEngine *_vm;
int _numChars;
- int _maxCharSize;
int _fontHeight;
int _spacing;
- byte *_charBuffer;
byte *_decodedData;
- byte *_paletteMap;
- byte _bpp;
- byte _palette[16];
const int _direction;
const int8 *_2byteShadowXOffsetTable;
@@ -67,7 +62,6 @@ protected:
void codec21(byte *dst, const byte *src, int width, int height, int pitch);
void loadFont(const char *filename);
- byte *unpackChar(byte c);
public:
NutRenderer(ScummEngine *vm, const char *filename);
More information about the Scummvm-git-logs
mailing list