/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ // Disable symbol overrides so that we can use system headers. #define FORBIDDEN_SYMBOL_ALLOW_ALL // HACK to allow building with the SDL backend on MinGW // see bug #1800764 "TOOLS: MinGW tools building broken" #ifdef main #undef main #endif // main #include #include #include #include "graphics/surface.h" #include "common/algorithm.h" #include "common/endian.h" const byte FONT[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x00, 0x00, 0x00, 0x20, 0xF8, 0xA0, 0xF8, 0x28, 0xF8, 0x20, 0x00, 0x90, 0x10, 0x20, 0x40, 0x80, 0x90, 0x00, 0x00, 0x40, 0xA0, 0x40, 0xA8, 0x90, 0x68, 0x00, 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x80, 0x80, 0x80, 0x40, 0x20, 0x00, 0x80, 0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00, 0x90, 0x60, 0xF0, 0x60, 0x90, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x10, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x90, 0x60, 0x00, 0x00, 0x40, 0xC0, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, 0x60, 0x90, 0x20, 0x40, 0x80, 0xF0, 0x00, 0x00, 0x60, 0x90, 0x20, 0x10, 0x90, 0x60, 0x00, 0x00, 0xA0, 0xA0, 0xF0, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x80, 0xE0, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x70, 0x80, 0xE0, 0x90, 0x90, 0x60, 0x00, 0x00, 0xF0, 0x10, 0x20, 0x40, 0x40, 0x40, 0x00, 0x00, 0x60, 0x90, 0x60, 0x90, 0x90, 0x60, 0x00, 0x00, 0x60, 0x90, 0x90, 0x70, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x20, 0x40, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x40, 0x80, 0x00, 0x00, 0x70, 0x88, 0x10, 0x20, 0x00, 0x20, 0x00, 0x00, 0x60, 0x90, 0xB0, 0xB0, 0x80, 0x70, 0x00, 0x00, 0x60, 0x90, 0x90, 0xF0, 0x90, 0x90, 0x00, 0x00, 0xE0, 0x90, 0xE0, 0x90, 0x90, 0xE0, 0x00, 0x00, 0x70, 0x80, 0x80, 0x80, 0x80, 0x70, 0x00, 0x00, 0xE0, 0x90, 0x90, 0x90, 0x90, 0xE0, 0x00, 0x00, 0xF0, 0x80, 0xE0, 0x80, 0x80, 0xF0, 0x00, 0x00, 0xF0, 0x80, 0xE0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x70, 0x80, 0x80, 0xB0, 0x90, 0x70, 0x00, 0x00, 0x90, 0x90, 0x90, 0xF0, 0x90, 0x90, 0x00, 0x00, 0xE0, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, 0x00, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x90, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF0, 0x00, 0x00, 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88, 0x00, 0x00, 0x90, 0xD0, 0xB0, 0x90, 0x90, 0x90, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x90, 0x60, 0x00, 0x00, 0xE0, 0x90, 0x90, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0xB0, 0x70, 0x18, 0x00, 0xE0, 0x90, 0x90, 0xE0, 0xC0, 0xB0, 0x00, 0x00, 0x70, 0x80, 0x60, 0x10, 0x90, 0x60, 0x00, 0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60, 0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, 0x00, 0x88, 0x88, 0x88, 0xA8, 0xD8, 0x88, 0x00, 0x00, 0x88, 0x50, 0x20, 0x20, 0x50, 0x88, 0x00, 0x00, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x10, 0x20, 0x40, 0x80, 0xF0, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x80, 0xC0, 0x00, 0x00, 0x80, 0x80, 0x40, 0x20, 0x10, 0x10, 0x00, 0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xC0, 0x00, 0x00, 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x80, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0xE0, 0xA0, 0xE0, 0x00, 0x00, 0x80, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x80, 0x80, 0x80, 0xE0, 0x00, 0x00, 0x20, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xA0, 0xE0, 0x80, 0xE0, 0x00, 0x00, 0x60, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0x20, 0xE0, 0x80, 0xE0, 0xA0, 0xA0, 0xA0, 0xA0, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0xC0, 0x80, 0xA0, 0xA0, 0xC0, 0xA0, 0xA0, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xF8, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0xE0, 0xA0, 0xA0, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0x80, 0x80, 0x00, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0x20, 0x20, 0x00, 0xE0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xE0, 0x80, 0xE0, 0x20, 0xE0, 0x00, 0x00, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0xE0, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0x40, 0x00, 0x00, 0x00, 0xA8, 0xA8, 0xA8, 0xA8, 0xF8, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0x40, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0xE0, 0x20, 0xE0, 0x00, 0xE0, 0x20, 0x40, 0x80, 0xE0, 0x00, 0x00, 0x20, 0x40, 0x40, 0x80, 0x40, 0x40, 0x20, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x40, 0x40, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x40, 0xA8, 0x10, 0x00, 0x00, 0x00 }; #define X_COUNT 32 #define CHAR_COUNT sizeof(FONT) / 8 #define Y_COUNT 3 #define CHAR_WIDTH 6 #define CHAR_HEIGHT 8 /** * Stream reader */ class MemoryReadStream { private: const byte *_ptr; public: MemoryReadStream(const byte *ptr) : _ptr(ptr) {} byte readByte() { return *_ptr++; } }; /** * Simple surface structure */ struct Surface { int _w; int _h; byte *_pixels; Surface(int w, int h) : _w(w), _h(h) { _pixels = new byte[w * h]; memset(_pixels, 0xff, w * h); } ~Surface() { delete[] _pixels; } Surface &operator=(const Surface &src) { assert(src._w == _w && src._h == _h); memcpy(_pixels, src._pixels, _w * _h); return *this; } byte *getBasePtr(int x, int y) { assert(y < _h); return _pixels + (y * _w) + x; } void decodeFont(MemoryReadStream &src); /** * Save to a BMP file */ void saveToFile(const char *filename); }; /** * File writing class */ class File { private: FILE *_f; public: File(const char *filename) { _f = fopen(filename, "wb"); } ~File() { fclose(_f); } void writeByte(byte v) { fwrite(&v, 1, 1, _f); } void writeUint16LE(uint16 v) { writeByte(v & 0xff); writeByte(v >> 8); } void writeUint32LE(uint32 v) { writeUint16LE(v & 0xffff); writeUint16LE(v >> 16); } void write(byte val, size_t count) { while (count-- > 0) writeByte(val); } void write(const byte *buf, size_t count) { fwrite(buf, 1, count, _f); } }; int main(int argc, char *argv[]) { MemoryReadStream src(FONT); Surface norm(X_COUNT * CHAR_WIDTH, Y_COUNT * CHAR_HEIGHT), surf(X_COUNT * CHAR_WIDTH, Y_COUNT * CHAR_HEIGHT); // Decode the normal font and write it out norm.decodeFont(src); norm.saveToFile("infocom6x8.bmp"); return 0; } void Surface::decodeFont(MemoryReadStream &src) { for (int charNum = 0; charNum < CHAR_COUNT; ++charNum) { int xs = (charNum % X_COUNT) * CHAR_WIDTH; int ys = (charNum / X_COUNT) * CHAR_HEIGHT; for (int y = 0; y < CHAR_HEIGHT; ++y) { byte *pDest = getBasePtr(xs, ys + y); byte bits = src.readByte(); for (int x = 0; x < CHAR_WIDTH; ++x, ++pDest, bits <<= 1) { if (bits & 0x80) { *pDest = 0; assert(x < CHAR_WIDTH); } } } } } void Surface::saveToFile(const char *filename) { File f(filename); f.writeByte('B'); f.writeByte('M'); f.writeUint32LE(0x436 + _w * _h + 2); // File size f.writeUint16LE(0); // Custom 1 f.writeUint16LE(0); // Custom 2 f.writeUint32LE(0x436); // Pixels offset f.writeUint32LE(40); // Info size f.writeUint32LE(_w); // Width f.writeUint32LE(_h); // Height f.writeUint16LE(1); // # Planes f.writeUint16LE(8); // Bits per pixel f.writeUint32LE(0); // Compression f.writeUint32LE(_w * _h); // Image size f.writeUint32LE(3790); // Pixels per meter X f.writeUint32LE(3800); // Pixels per meter Y f.writeUint32LE(0); // color count f.writeUint32LE(0); // important colors // Palette for (int idx = 0; idx < 256; ++idx) { f.write(idx, 3); f.writeByte(0); } // Write out each line from the bottom up for (int y = _h - 1; y >= 0; --y) { byte *lineP = getBasePtr(0, y); f.write(lineP, _w); } }