/* 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 <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);
	}
}
