scummvm/devtools/create_glk/create_glk.cpp
2021-05-04 11:46:30 +03:00

293 lines
8.9 KiB
C++

/* 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 #3412 "TOOLS: MinGW tools building broken"
#ifdef main
#undef main
#endif // main
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 (int)(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);
}
}