aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2009-08-09 22:46:43 +0000
committerJohannes Schickel2009-08-09 22:46:43 +0000
commit300297d557e0fbd75ccb503233159b1ad7445e05 (patch)
treeaef0e0236204f7ca0a60d995c24de2feb2f38308
parent518cb968b23bfb37cd1248c3a884d004a3309bba (diff)
downloadscummvm-rg350-300297d557e0fbd75ccb503233159b1ad7445e05.tar.gz
scummvm-rg350-300297d557e0fbd75ccb503233159b1ad7445e05.tar.bz2
scummvm-rg350-300297d557e0fbd75ccb503233159b1ad7445e05.zip
Add support for the font format used in Kyrandia 1 Amiga. (font colors are wrong though)
svn-id: r43187
-rw-r--r--engines/kyra/screen.cpp119
-rw-r--r--engines/kyra/screen.h34
2 files changed, 148 insertions, 5 deletions
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 2628ecdf65..e05e18d96f 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -949,8 +949,9 @@ bool Screen::loadFont(FontId fontId, const char *filename) {
Font *&fnt = _fonts[fontId];
if (!fnt) {
- // FIXME: add font support for Amiga version
- if (_vm->gameFlags().platform != Common::kPlatformAmiga)
+ if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+ fnt = new AMIGAFont();
+ else
fnt = new DOSFont();
assert(fnt);
@@ -1979,8 +1980,8 @@ void Screen::decodeFrameDeltaPage(uint8 *dst, const uint8 *src, int pitch, bool
wrapped_decodeFrameDeltaPage<false>(dst, src, pitch);
}
-void Screen::convertAmigaGfx(uint8 *data, int w, int h, int depth, bool wsa) {
- const int planeWidth = (w + 7) / 8;
+void Screen::convertAmigaGfx(uint8 *data, int w, int h, int depth, bool wsa, int bytesPerPlane) {
+ const int planeWidth = (bytesPerPlane == -1) ? (w + 7) / 8 : bytesPerPlane;
const int planeSize = planeWidth * h;
const uint imageSize = planeSize * depth;
@@ -3058,6 +3059,116 @@ void DOSFont::unload() {
_bitmapOffsets = 0;
}
+
+AMIGAFont::AMIGAFont() {
+ _width = _height = 0;
+ memset(_chars, 0, sizeof(_chars));
+}
+
+bool AMIGAFont::load(Common::SeekableReadStream &file) {
+ const uint16 dataSize = file.readUint16BE();
+ if (dataSize + 2 != file.size())
+ return false;
+
+ _width = file.readByte();
+ _height = file.readByte();
+
+ // Read the character definition offset table
+ uint16 offsets[ARRAYSIZE(_chars)];
+ for (int i = 0; i < ARRAYSIZE(_chars); ++i)
+ offsets[i] = file.readUint16BE() + 4;
+
+ if (file.err())
+ return false;
+
+ for (int i = 0; i < ARRAYSIZE(_chars); ++i) {
+ file.seek(offsets[i], SEEK_SET);
+
+ _chars[i].yOffset = file.readByte();
+ _chars[i].xOffset = file.readByte();
+ _chars[i].width = file.readByte();
+ file.readByte(); // unused
+
+ // If the y offset is 255, then the character
+ // does not have any bitmap representation
+ if (_chars[i].yOffset != 255) {
+ Character::Graphics &g = _chars[i].graphics;
+
+ g.width = file.readUint16BE();
+ g.height = file.readUint16BE();
+
+ int depth = file.readByte();
+ int specialWidth = file.readByte();
+ int flags = file.readByte();
+ int bytesPerPlane = file.readByte();
+
+ assert(depth != 0 && specialWidth == 0 && flags == 0 && bytesPerPlane != 0);
+
+ // Allocate a temporary buffer to store the plane data
+ const int planesSize = bytesPerPlane * g.height * depth;
+ uint8 *tempData = new uint8[MAX(g.width * g.height, planesSize)];
+ assert(tempData);
+
+ file.read(tempData, planesSize);
+
+ // Convert the plane based graphics to our graphic format
+ Screen::convertAmigaGfx(tempData, g.width, g.height, depth, false, bytesPerPlane);
+
+ // Create a buffer perfectly fitting the character
+ g.bitmap = new uint8[g.width * g.height];
+ assert(g.bitmap);
+
+ memcpy(g.bitmap, tempData, g.width * g.height);
+ delete[] tempData;
+ }
+
+ if (file.err())
+ return false;
+ }
+
+ return !file.err();
+}
+
+int AMIGAFont::getCharWidth(uint8 c) const {
+ if (c >= 255)
+ return 0;
+ return _chars[c].width;
+}
+
+void AMIGAFont::drawChar(uint8 c, byte *dst, int pitch) const {
+ if (c >= 255)
+ return;
+
+ if (_chars[c].yOffset == 255)
+ return;
+
+ dst += _chars[c].yOffset * pitch;
+ dst += _chars[c].xOffset;
+
+ pitch -= _chars[c].graphics.width;
+
+ const uint8 *src = _chars[c].graphics.bitmap;
+ assert(src);
+
+ for (int y = 0; y < _chars[c].graphics.height; ++y) {
+ for (int x = 0; x < _chars[c].graphics.width; ++x) {
+ if (*src)
+ *dst = *src;
+ ++src;
+ ++dst;
+ }
+
+ dst += pitch;
+ }
+}
+
+void AMIGAFont::unload() {
+ _width = _height = 0;
+ for (int i = 0; i < ARRAYSIZE(_chars); ++i)
+ delete[] _chars[i].graphics.bitmap;
+ memset(_chars, 0, sizeof(_chars));
+}
+
#pragma mark -
Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) {
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 8455e5a8c4..f947d2b9a9 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -135,6 +135,38 @@ private:
};
/**
+ * Implementation of the Font interface for AMIGA fonts.
+ */
+class AMIGAFont : public Font {
+public:
+ AMIGAFont();
+ ~AMIGAFont() { unload(); }
+
+ bool load(Common::SeekableReadStream &file);
+ int getHeight() const { return _height; }
+ int getWidth() const { return _width; }
+ int getCharWidth(uint8 c) const;
+ void setColorMap(const uint8 *src) {}
+ void drawChar(uint8 c, byte *dst, int pitch) const;
+
+private:
+ void unload();
+
+ int _width, _height;
+
+ struct Character {
+ uint8 yOffset, xOffset, width;
+
+ struct Graphics {
+ uint16 width, height;
+ uint8 *bitmap;
+ } graphics;
+ };
+
+ Character _chars[255];
+};
+
+/**
* A class that manages KYRA palettes.
*
* This class stores the palette data as VGA RGB internally.
@@ -409,7 +441,7 @@ public:
static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false);
static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor);
- static void convertAmigaGfx(uint8 *data, int w, int h, int depth = 5, bool wsa = false);
+ static void convertAmigaGfx(uint8 *data, int w, int h, int depth = 5, bool wsa = false, int bytesPerPlane = -1);
static void convertAmigaMsc(uint8 *data);
protected: