aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2010-12-30 05:04:04 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2010-12-30 05:04:04 +0100
commite465a280b562cf0ed4ab136e240437f6574189f8 (patch)
treeceb1f90df5dd15630c98f28b418aa1c475836799
downloadvirtualosc-e465a280b562cf0ed4ab136e240437f6574189f8.tar.gz
old Virtual OSC Controller project exported from SVN working copy
unfortunately the repository is long gone, so is its history working and tested for: * POSIX/gcc (Linux, Windows Cygwin, OS/2 EMX) * Open Watcom C (native OS/2 and Windows)
-rw-r--r--AUTHORS0
l---------COPYING1
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.watcom45
-rw-r--r--NEWS0
-rw-r--r--README0
-rw-r--r--configure.ac60
-rw-r--r--expat_watcom/Makefile.watcom116
-rw-r--r--expat_watcom/expat_external.h117
-rw-r--r--samples/sample.xml25
-rw-r--r--samples/simple_osc.pd33
-rw-r--r--samples/simple_osc.xml16
-rw-r--r--src/Makefile.am5
-rw-r--r--src/OSC-client.c496
-rw-r--r--src/OSC-client.h197
-rw-r--r--src/biosfont.h.cpp750
-rw-r--r--src/controller.c553
-rw-r--r--src/controller.h55
-rw-r--r--src/controls.c190
-rw-r--r--src/controls.h113
-rw-r--r--src/fontface.c3101
-rw-r--r--src/fontface.h12
-rw-r--r--src/graphics.c175
-rw-r--r--src/graphics.h37
-rw-r--r--src/osc.c312
-rw-r--r--src/osc.h61
-rw-r--r--src/xml.c378
-rw-r--r--src/xml.h9
29 files changed, 6860 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AUTHORS
diff --git a/COPYING b/COPYING
new file mode 120000
index 0000000..0b6cbf8
--- /dev/null
+++ b/COPYING
@@ -0,0 +1 @@
+/usr/share/automake-1.10/COPYING \ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..6b75694
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,3 @@
+
+SUBDIRS = src
+
diff --git a/Makefile.watcom b/Makefile.watcom
new file mode 100644
index 0000000..0434bb8
--- /dev/null
+++ b/Makefile.watcom
@@ -0,0 +1,45 @@
+# Virtual OSC Controller
+# Open Watcom Makefile
+
+ccl = owcc
+
+exeext = .exe
+dllext = .dll
+objext = .obj
+libext = .lib
+
+sdl = c:\prg\libsdl
+incl += -I$(sdl)\include\SDL
+libs += $(sdl)\SDL\sdl12$libext
+# ^ adapt to your SDL configuration
+
+expat = c:\prg\expat-2.0.1
+incl += -I$(expat)\lib
+libs += $(expat)\lib\expat$libext
+
+optimization = -mtune=i386 -g3 -O0
+# ^ adapt to your system architecture etc.
+cflags = -std=c99 -mthreads -fno-short-enum -mregparm=0 $optimization
+#lflags = -s
+# ^ adapt to your needs
+
+defs = -DOSC_NOBUNDLES
+#defs += -DPACKAGE_VERSION="1.0"
+
+manifest = src\controller.c src\xml.c src\graphics.c src\controls.c &
+ src\fontface.c src\OSC-client.c src\osc.c
+objects = $(manifest:.c=$objext)
+
+all : controller$exeext .symbolic
+
+controller$exeext : $objects
+ $ccl $lflags -o $^@ $< $libs
+
+.c : src
+.c$objext:
+ $ccl $cflags $incl $defs -c -o $^@ $[@
+
+clean: .symbolic
+ @for %i in ($objects controller$exeext) do &
+ @if exist %i del %i
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..fc0fea9
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,60 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT([Virtual OSC Controller], [dev])
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([src/controller.c])
+AC_CONFIG_HEADERS([config.h])
+
+# Checks for programs.
+AC_PROG_CC(gcc cc owcc)
+AC_PROG_CC_C_O
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+# Checks for libraries.
+AC_CHECK_LIB(expat, XML_ParserCreate, , [
+ AC_MSG_ERROR([Required libexpat is missing!])
+])
+
+# libSDL depends on sdl-config script
+AC_CHECK_PROG(SDL_CONFIG, sdl-config, sdl-config)
+if test x$SDL_CONFIG = x; then
+ AC_MSG_ERROR([Required sdl-config script is missing! libSDL cannot be configured.])
+fi
+
+CFLAGS="$CFLAGS `$SDL_CONFIG --cflags`"
+LIBS="$LIBS `$SDL_CONFIG --libs`"
+AC_DEFINE(HAVE_LIBSDL, , [We've got libSDL])
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/select.h unistd.h])
+
+AC_CHECK_HEADERS([expat.h], , [
+ AC_MSG_ERROR([Required libexpat headers are missing!])
+])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(in_addr_t, [
+ AC_DEFINE([HAVE_IN_ADDR_T], , [netinet/in.h defines in_addr_t type])
+], , [
+ #include <netinet/in.h>
+])
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS([atexit gethostbyname memset socket strcasecmp strchr strdup strrchr strtoul])
+
+# Arbitrary defines
+AC_DEFINE([OSC_NOBUNDLES], , [Don't include OSC bundle support in OSC-client.c])
+
+AC_CONFIG_FILES([Makefile src/Makefile])
+AC_OUTPUT
+
diff --git a/expat_watcom/Makefile.watcom b/expat_watcom/Makefile.watcom
new file mode 100644
index 0000000..329d0b0
--- /dev/null
+++ b/expat_watcom/Makefile.watcom
@@ -0,0 +1,116 @@
+# libexpat Open Watcom Makefile (tested with libexpat 2.0.1)
+# creates expat.dll and expat.lib import library
+# watcomconfig.h - if provided - may contain additional macro definitions
+
+ccl = owcc
+link = wlink
+strip = wstrip
+libman = wlib
+
+exeext = .exe
+dllext = .dll
+objext = .obj
+libext = .lib
+
+incl =
+
+optimization = -O3 -mtune=i386
+# ^ adapt to your system architecture etc.
+cflags = -shared -std=c99 -fno-short-enum $optimization
+lstats = sys OS2V2_DLL
+# ^ adapt to your system target
+
+defs = -DHAVE_MEMMOVE -DHAVE_BCOPY -DHAVE_GETPAGESIZE -DHAVE_MMAP -DSTDC_HEADERS
+#defs += -DXML_DTD -DXML_NS
+# ^ unrem to enable DTD parsing and XML namespaces
+
+manifest = xmlparse.c xmltok.c xmlrole.c
+objects = $(manifest:.c=$objext)
+
+exports = &
+ XML_SetElementDeclHandler &
+ XML_SetAttlistDeclHandler &
+ XML_SetXmlDeclHandler &
+ XML_ParserCreate &
+ XML_ParserCreateNS &
+ XML_ParserCreate_MM &
+ XML_ParserReset &
+ XML_SetEntityDeclHandler &
+ XML_SetElementHandler &
+ XML_SetStartElementHandler &
+ XML_SetEndElementHandler &
+ XML_SetCharacterDataHandler &
+ XML_SetProcessingInstructionHandler &
+ XML_SetCommentHandler &
+ XML_SetCdataSectionHandler &
+ XML_SetStartCdataSectionHandler &
+ XML_SetEndCdataSectionHandler &
+ XML_SetDefaultHandler &
+ XML_SetDefaultHandlerExpand &
+ XML_SetDoctypeDeclHandler &
+ XML_SetStartDoctypeDeclHandler &
+ XML_SetEndDoctypeDeclHandler &
+ XML_SetUnparsedEntityDeclHandler &
+ XML_SetNotationDeclHandler &
+ XML_SetNamespaceDeclHandler &
+ XML_SetStartNamespaceDeclHandler &
+ XML_SetEndNamespaceDeclHandler &
+ XML_SetNotStandaloneHandler &
+ XML_SetExternalEntityRefHandler &
+ XML_SetExternalEntityRefHandlerArg &
+ XML_SetSkippedEntityHandler &
+ XML_SetUnknownEncodingHandler &
+ XML_DefaultCurrent &
+ XML_SetReturnNSTriplet &
+ XML_SetUserData &
+ XML_SetEncoding &
+ XML_UseParserAsHandlerArg &
+ XML_UseForeignDTD &
+ XML_SetBase &
+ XML_GetBase &
+ XML_GetSpecifiedAttributeCount &
+ XML_GetIdAttributeIndex &
+ XML_Parse &
+ XML_GetBuffer &
+ XML_ParseBuffer &
+ XML_StopParser &
+ XML_ResumeParser &
+ XML_GetParsingStatus &
+ XML_ExternalEntityParserCreate &
+ XML_SetParamEntityParsing &
+ XML_GetErrorCode &
+ XML_GetCurrentLineNumber &
+ XML_GetCurrentColumnNumber &
+ XML_GetCurrentByteIndex &
+ XML_GetCurrentByteCount &
+ XML_GetInputContext &
+ XML_FreeContentModel &
+ XML_MemMalloc &
+ XML_MemRealloc &
+ XML_MemFree &
+ XML_ParserFree &
+ XML_ErrorString &
+ XML_ExpatVersion &
+ XML_ExpatVersionInfo &
+ XML_GetFeatureList
+
+all : watcomconfig.h expat$libext .symbolic
+
+watcomconfig.h:
+ touch $^@
+
+expat$libext : expat$dllext
+ $libman -n -b $^@ +$[@
+
+expat$dllext : $objects
+ $link $lstats n $^@ f {$<} exp {$exports}
+ $strip -n $^@
+# ^ rem to disable debugging symbol stripping
+
+.c$objext:
+ $ccl $cflags $incl $defs -c -o $^@ $[@
+
+clean: .symbolic
+ @for %i in ($objects expat$dllext expat$libext) do &
+ @if exist %i del %i
+
diff --git a/expat_watcom/expat_external.h b/expat_watcom/expat_external.h
new file mode 100644
index 0000000..9961799
--- /dev/null
+++ b/expat_watcom/expat_external.h
@@ -0,0 +1,117 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_External_INCLUDED
+#define Expat_External_INCLUDED 1
+
+/* External API definitions */
+
+#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+#define XML_USE_MSC_EXTENSIONS 1
+#endif
+
+/* Expat tries very hard to make the API boundary very specifically
+ defined. There are two macros defined to control this boundary;
+ each of these can be defined before including this header to
+ achieve some different behavior, but doing so it not recommended or
+ tested frequently.
+
+ XMLCALL - The calling convention to use for all calls across the
+ "library boundary." This will default to cdecl, and
+ try really hard to tell the compiler that's what we
+ want.
+
+ XMLIMPORT - Whatever magic is needed to note that a function is
+ to be imported from a dynamically loaded library
+ (.dll, .so, or .sl, depending on your platform).
+
+ The XMLCALL macro was added in Expat 1.95.7. The only one which is
+ expected to be directly useful in client code is XMLCALL.
+
+ Note that on at least some Unix versions, the Expat library must be
+ compiled with the cdecl calling convention as the default since
+ system headers may assume the cdecl convention.
+*/
+#ifndef XMLCALL
+#if defined(_MSC_VER)
+#define XMLCALL __cdecl
+#elif defined(__WATCOMC__) && defined(__OS2__)
+#define XMLCALL __syscall
+#elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
+#define XMLCALL __attribute__((cdecl))
+#else
+/* For any platform which uses this definition and supports more than
+ one calling convention, we need to extend this definition to
+ declare the convention used on that platform, if it's possible to
+ do so.
+
+ If this is the case for your platform, please file a bug report
+ with information on how to identify your platform via the C
+ pre-processor and how to specify the same calling convention as the
+ platform's malloc() implementation.
+*/
+#define XMLCALL
+#endif
+#endif /* not defined XMLCALL */
+
+
+#if !defined(XML_STATIC) && !defined(XMLIMPORT)
+#ifndef XML_BUILDING_EXPAT
+/* using Expat from an application */
+
+#ifdef XML_USE_MSC_EXTENSIONS
+#define XMLIMPORT __declspec(dllimport)
+#endif
+
+#endif
+#endif /* not defined XML_STATIC */
+
+
+/* If we didn't define it above, define it away: */
+#ifndef XMLIMPORT
+#define XMLIMPORT
+#endif
+
+
+#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_UNICODE
+#endif
+
+#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
+#ifdef XML_UNICODE_WCHAR_T
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+#else
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE_WCHAR_T */
+#else /* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE */
+
+#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
+#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+typedef __int64 XML_Index;
+typedef unsigned __int64 XML_Size;
+#else
+typedef long long XML_Index;
+typedef unsigned long long XML_Size;
+#endif
+#else
+typedef long XML_Index;
+typedef unsigned long XML_Size;
+#endif /* XML_LARGE_SIZE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_External_INCLUDED */
diff --git a/samples/sample.xml b/samples/sample.xml
new file mode 100644
index 0000000..71758d2
--- /dev/null
+++ b/samples/sample.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<interface>
+ <tab label="Tab 1">
+ <slider type="set" geo="9.76 16.67 3.91 66.67" max="100"
+ step="10" label="Slider 1" showValue="true"
+ OSCAddress="/slider1">100</slider>
+
+ <slider type="relative" geo="19.53 16.67 3.91 66.67"
+ color="white" max="100"
+ OSCAddress="/slider2">23</slider>
+
+ <slider geo="29.3 16.67 3.91 66.67" color="red green"
+ max="128" step="4" label="Slider 3">100</slider>
+
+ <slider geo="39.06 16.67 3.91 66.67" color="red green"
+ max="100" label="S4" showValue="true">23</slider>
+
+ <switch geo="48.83 16.67 6.84 8.33" label="SW1">true</switch>
+
+ <button geo="48.83 33.33 6.84 8.33" color="yellow"
+ OSCAddress="/button"/>
+ </tab>
+</interface>
+
diff --git a/samples/simple_osc.pd b/samples/simple_osc.pd
new file mode 100644
index 0000000..3e2e981
--- /dev/null
+++ b/samples/simple_osc.pd
@@ -0,0 +1,33 @@
+#N canvas 0 0 338 368 10;
+#X obj 47 32 dumpOSC 77777;
+#X obj 135 99 print;
+#X obj 247 164 print;
+#X obj 47 69 OSCroute /osc;
+#X obj 47 129 OSCroute /pitch /volume /mute;
+#X floatatom 47 160 5 0 0 0 - - -;
+#X floatatom 113 160 5 0 0 0 - - -;
+#X obj 47 193 osc~;
+#X obj 113 193 dbtorms;
+#X obj 47 234 *~;
+#X obj 48 283 *~;
+#X obj 48 321 dac~;
+#X obj 180 193 * -1;
+#X obj 180 222 + 1;
+#X floatatom 180 159 5 0 0 0 - - -;
+#X connect 0 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 1 1 0;
+#X connect 4 0 5 0;
+#X connect 4 1 6 0;
+#X connect 4 2 14 0;
+#X connect 4 3 2 0;
+#X connect 5 0 7 0;
+#X connect 6 0 8 0;
+#X connect 7 0 9 0;
+#X connect 8 0 9 1;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 10 0 11 1;
+#X connect 12 0 13 0;
+#X connect 13 0 10 1;
+#X connect 14 0 12 0;
diff --git a/samples/simple_osc.xml b/samples/simple_osc.xml
new file mode 100644
index 0000000..bdb2817
--- /dev/null
+++ b/samples/simple_osc.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<interface>
+ <tab label="Oscillator">
+ <slider type="set" geo="9.76 16.67 6 67"
+ min="100" max="1000" label="PITCH (Hz)" showValue="true"
+ OSCAddress="/osc/pitch">400</slider>
+
+ <slider geo="29.3 16.67 6 53" color="red green"
+ max="100" step="5" label="VOL (db)" showValue="true"
+ OSCAddress="/osc/volume">80</slider>
+
+ <switch geo="29.3 73 6 10" label="MUTE"
+ OSCAddress="/osc/mute">true</switch>
+ </tab>
+</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..eef69bb
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,5 @@
+
+bin_PROGRAMS = controller
+controller_SOURCES = controller.c xml.c graphics.c controls.c \
+ fontface.c OSC-client.c osc.c
+
diff --git a/src/OSC-client.c b/src/OSC-client.c
new file mode 100644
index 0000000..5976fb7
--- /dev/null
+++ b/src/OSC-client.c
@@ -0,0 +1,496 @@
+/*
+Written by Matt Wright, The Center for New Music and Audio Technologies,
+University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
+The Regents of the University of California (Regents).
+
+Permission to use, copy, modify, distribute, and distribute modified versions
+of this software and its documentation without fee and without a signed
+licensing agreement, is hereby granted, provided that the above copyright
+notice, this paragraph and the following two paragraphs appear in all copies,
+modifications, and distributions.
+
+IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
+OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*/
+
+
+/*
+ Author: Matt Wright
+ Version 2.2: Calls htonl in the right places 20000620
+ Version 2.3: Gets typed messages right.
+ Version 2.4: 031215: (re)added ChangeOutermostTimestamp(), htonl() OSX kludge
+ Version 2.4.1: Took extra CheckTypeTag() out of OSC_writeAddressAndTypes(), since OSC_writeAddress does it.
+
+ */
+
+/*
+ * slightly modified to make 'bundles' an optional feature
+ * TODO: extend it to support more types
+ */
+
+/* Here are the possible values of the state field: */
+
+#define EMPTY 0 /* Nothing written to packet yet */
+#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
+#define NEED_COUNT 2 /* Just opened a bundle; must write message name or
+ open another bundle */
+#define GET_ARGS 3 /* Getting arguments to a message. If we see a message
+ name or a bundle open/close then the current message
+ will end. */
+#define DONE 4 /* All open bundles have been closed, so can't write
+ anything else */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arpa/inet.h>
+
+#include "OSC-client.h"
+
+#ifdef TARGET_API_MAC_CARBON
+/* KLUDGE for OSX: */
+#define htonl(x) (x)
+#endif
+
+char *OSC_errorMessage;
+
+
+static int strlen(char *s);
+static int OSC_padString(char *dest, char *str);
+static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
+static int OSC_WritePadding(char *dest, int i);
+static int CheckTypeTag(OSCbuf *buf, char expectedType);
+
+void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
+ buf->buffer = byteArray;
+ buf->size = size;
+ OSC_resetBuffer(buf);
+}
+
+void OSC_resetBuffer(OSCbuf *buf) {
+ buf->bufptr = buf->buffer;
+ buf->state = EMPTY;
+#ifndef OSC_NOBUNDLES
+ buf->bundleDepth = 0;
+ buf->prevCounts[0] = 0;
+ buf->outerMostTimeStamp = 0;
+#endif
+ buf->gettingFirstUntypedArg = 0;
+ buf->typeStringPtr = 0;
+}
+
+int OSC_isBufferEmpty(OSCbuf *buf) {
+ return buf->bufptr == buf->buffer;
+}
+
+int OSC_freeSpaceInBuffer(OSCbuf *buf) {
+ return buf->size - (buf->bufptr - buf->buffer);
+}
+
+int OSC_isBufferDone(OSCbuf *buf) {
+ return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
+}
+
+char *OSC_getPacket(OSCbuf *buf) {
+#ifdef ERROR_CHECK_GETPACKET
+ if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
+ return buf->buffer;
+ } else {
+ OSC_errorMessage = "Packet has unterminated bundles";
+ return 0;
+ }
+#else
+ return buf->buffer;
+#endif
+}
+
+int OSC_packetSize(OSCbuf *buf) {
+#ifdef ERROR_CHECK_PACKETSIZE
+ if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
+ return (buf->bufptr - buf->buffer);
+ } else {
+ OSC_errorMessage = "Packet has unterminated bundles";
+ return 0;
+ }
+#else
+ return (buf->bufptr - buf->buffer);
+#endif
+}
+
+#define CheckOverflow(buf, bytesNeeded) { \
+ if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
+ OSC_errorMessage = "buffer overflow"; \
+ return 1; \
+ } \
+}
+
+static void PatchMessageSize(OSCbuf *buf) {
+ int4byte size;
+ size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
+ *(buf->thisMsgSize) = htonl(size);
+}
+
+#ifndef OSC_NOBUNDLES
+int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
+ if (buf->state == ONE_MSG_ARGS) {
+ OSC_errorMessage = "Can't open a bundle in a one-message packet";
+ return 3;
+ }
+
+ if (buf->state == DONE) {
+ OSC_errorMessage = "This packet is finished; can't open a new bundle";
+ return 4;
+ }
+
+ if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
+ OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
+ return 2;
+ }
+
+ if (CheckTypeTag(buf, '\0')) return 9;
+
+ if (buf->state == GET_ARGS) {
+ PatchMessageSize(buf);
+ }
+
+ if (buf->state == EMPTY) {
+ /* Need 16 bytes for "#bundle" and time tag */
+ CheckOverflow(buf, 16);
+ } else {
+ /* This bundle is inside another bundle, so we need to leave
+ a blank size count for the size of this current bundle. */
+ CheckOverflow(buf, 20);
+ *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
+ buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
+
+ buf->bufptr += 4;
+ }
+
+ buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
+
+
+ *((OSCTimeTag *) buf->bufptr) = tt;
+ if (buf->state == EMPTY) {
+ buf->outerMostTimeStamp = (OSCTimeTag *) buf->bufptr;
+ }
+
+
+ if (htonl(1) != 1) {
+ /* Byte swap the 8-byte integer time tag */
+ int4byte *intp = (int4byte *)buf->bufptr;
+ intp[0] = htonl(intp[0]);
+ intp[1] = htonl(intp[1]);
+
+#ifdef HAS8BYTEINT
+ { /* tt is a 64-bit int so we have to swap the two 32-bit words.
+ (Otherwise tt is a struct of two 32-bit words, and even though
+ each word was wrong-endian, they were in the right order
+ in the struct.) */
+ int4byte temp = intp[0];
+ intp[0] = intp[1];
+ intp[1] = temp;
+ }
+#endif
+ }
+
+ buf->bufptr += sizeof(OSCTimeTag);
+
+ buf->state = NEED_COUNT;
+
+ buf->gettingFirstUntypedArg = 0;
+ buf->typeStringPtr = 0;
+ return 0;
+}
+
+
+
+int ChangeOutermostTimestamp(OSCbuf *buf, OSCTimeTag tt) {
+ if (buf->outerMostTimeStamp == 0) {
+ OSC_errorMessage = "No outermost timestamp to change.";
+ return 1;
+ } else {
+ *(buf->outerMostTimeStamp) = tt;
+ return 0;
+ }
+}
+
+int OSC_closeBundle(OSCbuf *buf) {
+ if (buf->bundleDepth == 0) {
+ /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
+ OSC_errorMessage = "Can't close bundle; no bundle is open!";
+ return 5;
+ }
+
+ if (CheckTypeTag(buf, '\0')) return 9;
+
+ if (buf->state == GET_ARGS) {
+ PatchMessageSize(buf);
+ }
+
+ if (buf->bundleDepth == 1) {
+ /* Closing the last bundle: No bundle size to patch */
+ buf->state = DONE;
+ } else {
+ /* Closing a sub-bundle: patch bundle size */
+ int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
+ *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
+ buf->state = NEED_COUNT;
+ }
+
+ --buf->bundleDepth;
+ buf->gettingFirstUntypedArg = 0;
+ buf->typeStringPtr = 0;
+ return 0;
+}
+
+
+int OSC_closeAllBundles(OSCbuf *buf) {
+ if (buf->bundleDepth == 0) {
+ /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
+ OSC_errorMessage = "Can't close all bundles; no bundle is open!";
+ return 6;
+ }
+
+ if (CheckTypeTag(buf, '\0')) return 9;
+
+ while (buf->bundleDepth > 0) {
+ OSC_closeBundle(buf);
+ }
+ buf->typeStringPtr = 0;
+ return 0;
+}
+#endif
+
+int OSC_writeAddress(OSCbuf *buf, char *name) {
+ int4byte paddedLength;
+
+ if (buf->state == ONE_MSG_ARGS) {
+ OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
+ return 7;
+ }
+
+ if (buf->state == DONE) {
+ OSC_errorMessage = "This packet is finished; can't write another address";
+ return 8;
+ }
+
+ if (CheckTypeTag(buf, '\0')) return 9;
+
+ paddedLength = OSC_effectiveStringLength(name);
+
+ if (buf->state == EMPTY) {
+ /* This will be a one-message packet, so no sizes to worry about */
+ CheckOverflow(buf, paddedLength);
+ buf->state = ONE_MSG_ARGS;
+ } else {
+ /* GET_ARGS or NEED_COUNT */
+ CheckOverflow(buf, 4+paddedLength);
+ if (buf->state == GET_ARGS) {
+ /* Close the old message */
+ PatchMessageSize(buf);
+ }
+ buf->thisMsgSize = (int4byte *)buf->bufptr;
+ *(buf->thisMsgSize) = 0xbbbbbbbb;
+ buf->bufptr += 4;
+ buf->state = GET_ARGS;
+ }
+
+ /* Now write the name */
+ buf->bufptr += OSC_padString(buf->bufptr, name);
+ buf->typeStringPtr = 0;
+ buf->gettingFirstUntypedArg = 1;
+
+ return 0;
+}
+
+int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) {
+ int result;
+ int4byte paddedLength;
+
+ result = OSC_writeAddress(buf, name);
+
+ if (result) return result;
+
+ paddedLength = OSC_effectiveStringLength(types);
+
+ CheckOverflow(buf, paddedLength);
+
+ buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
+ buf->bufptr += OSC_padString(buf->bufptr, types);
+
+ buf->gettingFirstUntypedArg = 0;
+ return 0;
+}
+
+static int CheckTypeTag(OSCbuf *buf, char expectedType) {
+ if (buf->typeStringPtr) {
+ if (*(buf->typeStringPtr) != expectedType) {
+ if (expectedType == '\0') {
+ OSC_errorMessage =
+ "According to the type tag I expected more arguments.";
+ } else if (*(buf->typeStringPtr) == '\0') {
+ OSC_errorMessage =
+ "According to the type tag I didn't expect any more arguments.";
+ } else {
+ OSC_errorMessage =
+ "According to the type tag I expected an argument of a different type.";
+ /* printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr); */
+ }
+ return 9;
+ }
+ ++(buf->typeStringPtr);
+ }
+ return 0;
+}
+
+
+int OSC_writeFloatArg(OSCbuf *buf, float arg) {
+ int4byte *intp;
+ int result;
+
+ CheckOverflow(buf, 4);
+
+ if (CheckTypeTag(buf, 'f')) return 9;
+
+ /* Pretend arg is a long int so we can use htonl() */
+ intp = ((int4byte *) &arg);
+ *((int4byte *) buf->bufptr) = htonl(*intp);
+
+ buf->bufptr += 4;
+
+ buf->gettingFirstUntypedArg = 0;
+ return 0;
+}
+
+
+
+int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
+ int i;
+ int4byte *intp;
+
+ CheckOverflow(buf, 4 * numFloats);
+
+ /* Pretend args are long ints so we can use htonl() */
+ intp = ((int4byte *) args);
+
+ for (i = 0; i < numFloats; i++) {
+ if (CheckTypeTag(buf, 'f')) return 9;
+ *((int4byte *) buf->bufptr) = htonl(intp[i]);
+ buf->bufptr += 4;
+ }
+
+ buf->gettingFirstUntypedArg = 0;
+ return 0;
+}
+
+int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
+ CheckOverflow(buf, 4);
+ if (CheckTypeTag(buf, 'i')) return 9;
+
+ *((int4byte *) buf->bufptr) = htonl(arg);
+ buf->bufptr += 4;
+
+ buf->gettingFirstUntypedArg = 0;
+ return 0;
+}
+
+int OSC_writeStringArg(OSCbuf *buf, char *arg) {
+ int len;
+
+ if (CheckTypeTag(buf, 's')) return 9;
+
+ len = OSC_effectiveStringLength(arg);
+
+ if (buf->gettingFirstUntypedArg && arg[0] == ',') {
+ /* This un-type-tagged message starts with a string
+ that starts with a comma, so we have to escape it
+ (with a double comma) so it won't look like a type
+ tag string. */
+
+ CheckOverflow(buf, len+4); /* Too conservative */
+ buf->bufptr +=
+ OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
+
+ } else {
+ CheckOverflow(buf, len);
+ buf->bufptr += OSC_padString(buf->bufptr, arg);
+ }
+
+ buf->gettingFirstUntypedArg = 0;
+ return 0;
+
+}
+
+/* String utilities */
+
+static int strlen(char *s) {
+ int i;
+ for (i=0; s[i] != '\0'; i++) /* Do nothing */ ;
+ return i;
+}
+
+#define STRING_ALIGN_PAD 4
+
+int OSC_effectiveStringLength(char *string) {
+ int len = strlen(string) + 1; /* We need space for the null char. */
+
+ /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
+ if ((len % STRING_ALIGN_PAD) != 0) {
+ len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
+ }
+ return len;
+}
+
+static int OSC_padString(char *dest, char *str) {
+ int i;
+
+ for (i = 0; str[i] != '\0'; i++) {
+ dest[i] = str[i];
+ }
+
+ return OSC_WritePadding(dest, i);
+}
+
+static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) {
+ int i;
+
+ dest[0] = ',';
+ for (i = 0; str[i] != '\0'; i++) {
+ dest[i+1] = str[i];
+ }
+
+ return OSC_WritePadding(dest, i+1);
+}
+
+static int OSC_WritePadding(char *dest, int i) {
+ dest[i] = '\0';
+ i++;
+
+ for (; (i % STRING_ALIGN_PAD) != 0; i++) {
+ dest[i] = '\0';
+ }
+
+ return i;
+}
+
+
+/* Blob utility */
+
+int OSC_effectiveBlobLength(int blobDataSize) {
+ int len = 4 + blobDataSize; /* int32 size count. */
+
+ /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
+ if ((len % STRING_ALIGN_PAD) != 0) {
+ len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
+ }
+ return len;
+}
diff --git a/src/OSC-client.h b/src/OSC-client.h
new file mode 100644
index 0000000..5b47f83
--- /dev/null
+++ b/src/OSC-client.h
@@ -0,0 +1,197 @@
+/*
+Written by Matt Wright, The Center for New Music and Audio Technologies,
+University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
+The Regents of the University of California (Regents).
+
+Permission to use, copy, modify, distribute, and distribute modified versions
+of this software and its documentation without fee and without a signed
+licensing agreement, is hereby granted, provided that the above copyright
+notice, this paragraph and the following two paragraphs appear in all copies,
+modifications, and distributions.
+
+IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
+OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*/
+
+/*
+
+ OSC-client.h: library for constructing OpenSoundControl messages.
+ Derived from SynthControl.h
+ Author: Matt Wright
+ Version 0.1: 6/13/97
+ Version 0.2: 7/21/2000: Support for type-tagged messages
+ Version 0.3: 031215: (re)added ChangeOutermostTimestamp()
+
+
+ General notes:
+
+ This library abstracts away the data format for the OpenSoundControl
+ protocol. Users of this library can construct OpenSoundControl packets
+ with a function call interface instead of knowing how to lay out the bits.
+
+ All issues of memory allocation are deferred to the user of this library.
+ There are two data structures that the user must allocate. The first
+ is the actual buffer that the message will be written into. This buffer
+ can be any size, but if it's too small there's a possibility that it
+ will become overfull. The other data structure is called an OSCbuf,
+ and it holds all the state used by the library as it's constructing
+ a buffer.
+
+ All procedures that have the possibility of an error condition return int,
+ with 0 indicating no error and nonzero indicating an error. The variable
+ OSC_errorMessage will be set to point to a string containing an error
+ message explaining what the problem is.
+
+*/
+
+/*
+ * slightly modified to make 'bundles' an optional feature
+ * TODO: extend it to support more types
+ */
+
+#ifndef __OSC_CLIENT_H
+#define __OSC_CLIENT_H
+
+#ifndef OSC_NOBUNDLES
+#include "OSC-timetag.h"
+#endif
+
+/* The int4byte type has to be a 4-byte integer. You may have to
+ change this to long or something else on your system. */
+#ifdef __MWERKS__
+ /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is
+ always 4 bytes */
+ typedef long int4byte;
+#else
+ typedef int int4byte;
+#endif
+
+/* The maximum depth of bundles within bundles within bundles within...
+ This is the size of a static array. If you exceed this limit you'll
+ get an error message. */
+#define MAX_BUNDLE_NESTING 32
+
+
+/* Don't ever manipulate the data in the OSCbuf struct directly. (It's
+ declared here in the header file only so your program will be able to
+ declare variables of type OSCbuf and have the right amount of memory
+ be allocated.) */
+
+typedef struct OSCbuf_struct {
+ char *buffer; /* The buffer to hold the OSC packet */
+ int size; /* Size of the buffer */
+ char *bufptr; /* Current position as we fill the buffer */
+ int state; /* State of partially-constructed message */
+ int4byte *thisMsgSize; /* Pointer to count field before
+ currently-being-written message */
+#ifndef OSC_NOBUNDLES
+ int4byte *prevCounts[MAX_BUNDLE_NESTING];
+ /* Pointers to count field before each currently
+ open bundle */
+ int bundleDepth; /* How many sub-sub-bundles are we in now? */
+ OSCTimeTag *outerMostTimeStamp; /* Pointer to highest-level enclosing timestamp */
+#endif
+ char *typeStringPtr; /* This pointer advances through the type
+ tag string as you add arguments. */
+ int gettingFirstUntypedArg; /* nonzero if this message doesn't have
+ a type tag and we're waiting for the 1st arg */
+} OSCbuf;
+
+
+
+/* Initialize the given OSCbuf. The user of this module must pass in the
+ block of memory that this OSCbuf will use for a buffer, and the number of
+ bytes in that block. (It's the user's job to allocate the memory because
+ you do it differently in different systems.) */
+void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray);
+
+
+/* Reset the given OSCbuf. Do this after you send out the contents of
+ the buffer and want to start writing new data into it. */
+void OSC_resetBuffer(OSCbuf *buf);
+
+
+/* Is the buffer empty? (I.e., would it be stupid to send the buffer
+ contents to the synth?) */
+int OSC_isBufferEmpty(OSCbuf *buf);
+
+
+/* How much space is left in the buffer? */
+int OSC_freeSpaceInBuffer(OSCbuf *buf);
+
+/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */
+int OSC_isBufferDone(OSCbuf *buf);
+
+/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone()
+ returns true), call these two procedures to get the OSC packet that's been
+ assembled and its size in bytes. (And then call OSC_resetBuffer() if you
+ want to re-use this OSCbuf for the next packet.) */
+char *OSC_getPacket(OSCbuf *buf);
+int OSC_packetSize(OSCbuf *buf);
+
+#ifndef OSC_NOBUNDLES
+/* If a packet already has a timestamp, change it to the given new one. */
+int ChangeOutermostTimestamp(OSCbuf *buf, OSCTimeTag tt);
+#endif
+
+/* Here's the basic model for building up OSC messages in an OSCbuf:
+
+ - Make sure the OSCbuf has been initialized with OSC_initBuffer().
+
+ - To open a bundle, call OSC_openBundle(). You can then write
+ messages or open new bundles within the bundle you opened.
+ Call OSC_closeBundle() to close the bundle. Note that a packet
+ does not have to have a bundle; it can instead consist of just a
+ single message.
+
+
+ - For each message you want to send:
+
+ - Call OSC_writeAddress() with the name of your message. (In
+ addition to writing your message name into the buffer, this
+ procedure will also leave space for the size count of this message.)
+
+ - Alternately, call OSC_writeAddressAndTypes() with the name of
+ your message and with a type string listing the types of all the
+ arguments you will be putting in this message.
+
+ - Now write each of the arguments into the buffer, by calling one of:
+ OSC_writeFloatArg()
+ OSC_writeFloatArgs()
+ OSC_writeIntArg()
+ OSC_writeStringArg()
+
+ - Now your message is complete; you can send out the buffer or you can
+ add another message to it.
+*/
+
+#ifndef OSC_NOBUNDLES
+int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt);
+int OSC_closeBundle(OSCbuf *buf);
+int OSC_closeAllBundles(OSCbuf *buf);
+#endif
+
+int OSC_writeAddress(OSCbuf *buf, char *name);
+int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types);
+int OSC_writeFloatArg(OSCbuf *buf, float arg);
+int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args);
+int OSC_writeIntArg(OSCbuf *buf, int4byte arg);
+int OSC_writeStringArg(OSCbuf *buf, char *arg);
+
+extern char *OSC_errorMessage;
+
+/* How many bytes will be needed in the OSC format to hold the given
+ string? The length of the string, plus the null char, plus any padding
+ needed for 4-byte alignment. */
+int OSC_effectiveStringLength(char *string);
+
+#endif
+
diff --git a/src/biosfont.h.cpp b/src/biosfont.h.cpp
new file mode 100644
index 0000000..fc97ea6
--- /dev/null
+++ b/src/biosfont.h.cpp
@@ -0,0 +1,750 @@
+/*****************************************************************************/
+/// @file biosfont.h.cpp with "modified BSD license"
+/// @author Jonathan D. Lettvin (jlettvin|gmail|com) Apr 5 2008
+/*
+* Copyright (c) 2008, Jonathan D. Lettvin
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Jonathan Lettvin Consulting nor the
+* names of its contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY JONATHAN D. LETTVIN ''AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL JONATHAN D. LETTVIN BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/// @brief (http://en.wikipedia.org/wiki/BSD_license)
+/*****************************************************************************/
+/// @brief Usage and example compilations:
+/// Include this file in other source code:
+/// /// #define BIOSFONT_STATICS /// In one compilation unit.
+/// #include "biosfont.h.cpp"
+/// Example of autonomous unit test compilation and execution.
+/// g++ -Wall -W4 -O4 -DBIOSFONT_UNIT_TEST biosfont biosfont.h.cpp
+/// strip biosfont
+/// ./biosfont
+/// This code also compiles in ordinary C (by eliminating namespacing).
+/// gcc -Wall -W4 -O4 -DBIOSFONT_UNIT_TEST biosfont biosfont.h.cpp
+/*****************************************************************************/
+/// @brief Purpose: This file provides an absolute bitmapped graphics font.
+/// This is a (slightly adjusted) iAPX86 ROM BIOS font.
+/// This font supports ASCII codes 00H-FFH.
+/// This code is invariant to endian issues.
+/// No external resources, libraries, or calls are needed or used.
+/// EBCDIC and other encodings are not supported.
+/*****************************************************************************/
+/// @brief File naming convention: (why *.h.cpp?)
+/// Managing multiple source files can be cumbersome.
+/// Files implementing very simple tables and code can be
+/// entirely autonomous, making distribution/integration easy:
+/// This file can be used as a pure header.
+/// There is no restriction on including .cpp files as headers.
+/// Using a .cpp extension enables direct unit test compilation.
+/// Naming it .h.cpp is sufficiently unique to be recognized.
+/// I offer this naming style for headers with built-in unit testing.
+/*****************************************************************************/
+/// @brief Organization:
+/// This files shows a sample debug font acquisition.
+/// This is followed by the magnified font.
+/// This is followed by the font bitmap value table.
+/// This is followed by an inline font bit accessor function.
+/// This is followed by unit test functions and a main function.
+/*****************************************************************************/
+/// @brief Size and Technical details:
+/// 256 8 x 8 bit glyphs fit into 64 bits each for a
+/// memory footprint of 2KBytes both here and in BIOS.
+/// Compiled unit test size including main and runtime libraries:
+/// 9,216 Windows XP with gcc version 3.4.5 (mingw special)
+/// Bits start at the upper left and end at the lower right.
+/// US English BIOS provides ASCII 0-127 at F000:FA6E and
+/// extension codes 128-255 at the address stored in 0000:007C.
+/// Note: the bits of each byte have been swapped end-to-end
+/// (i.e. 000100111 becomes 111001000).
+/// This reduces reconstruction complexity.
+/*****************************************************************************/
+/// @brief How the iAPX86 ROM BIOS font was copied.
+/// Early IBM PCs provided fonts burned into ROM.
+/// (http://en.wikipedia.org/wiki/Color_Graphics_Adapter)
+/// The following web-page is useful for DEBUG novitiates.
+/// (http://mirror.href.com/thestarman/asm/debug/debug2.htm)
+/// Data was acquired by the following DOS operation.
+/*****************************************************************************/
+/*This is both user input and debug output.
+C:\>DEBUG ;Start debug from a command prompt
+-N lower ;Prompted by '-', Name the outut file
+-R CX ;Request to change the byte count
+CX 0000 ;Currently it is 0
+:400 ;You set it to 400H (1024)
+-RBX ;Make sure this is zero
+BX 0000 ;Currently it is 0
+:0000 ;You set it to 0H (0)
+W F000:FA6E ;Write that many bytes to named file
+Writing 00400 bytes;Debug tells you what it did
+-N upper ;Name a second output file
+-D 0000:007C L 4 ;Get contents of INT 1F
+0000:0070 34 30 00 C0
+W C000:3034 ;Reverse order the bytes
+Writing 00400 bytes
+-Q ;Quit because you're done
+C:\>
+ */
+/*****************************************************************************/
+/// The BIOS font appearance (magnified):
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | ****** | ****** | ** ** | * | *** | | |
+//| |* *|********|******* | *** | ***** | * | |
+//| |* * * *|** ** **|******* | ***** | *** | *** | ** |
+//| |* *|********|******* |******* |******* | ***** | **** |
+//| |* **** *|** **| ***** | ***** |******* |******* | **** |
+//| |* ** *|*** ***| *** | *** |* * * | ***** | ** |
+//| |* *|********| * | * | * | *** | |
+//| | ****** | ****** | | | ***** | ***** | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|********| |********| ****| **** | ******| *******|* ** *|
+//|********| **** |** **| ***| ** ** | ** **| ** **| * ** * |
+//|*** ***| ** ** |* ** *| ****| ** ** | ******| *******| **** |
+//|** **| * * |* **** *| ***** *| ** ** | ** | ** **|*** ***|
+//|** **| * * |* **** *|** ** | **** | ** | ** **|*** ***|
+//|*** ***| ** ** |* ** *|** ** | ** | *** | ** ***| **** |
+//|********| **** |** **|** ** | ****** |**** |*** ** | * ** * |
+//|********| |********| **** | ** |*** |** |* ** *|
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|* | * | ** | ** ** | *******| ***** | | ** |
+//|*** | *** | **** | ** ** |** ** **| ** **| | **** |
+//|***** | ***** | ****** | ** ** |** ** **| *** | | ****** |
+//|******* |******* | ** | ** ** | **** **| ** ** | | ** |
+//|***** | ***** | ** | ** ** | ** **| ** ** | ****** | ****** |
+//|*** | *** | ****** | | ** **| *** | ****** | **** |
+//|* | * | **** | ** ** | ** **|* ** | ****** | ** |
+//| | | ** | | |****** | |********|
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** | ** | | | | | | |
+//| **** | ** | ** | ** | | * * | ** |********|
+//| ****** | ** | ** | ** |** | ** ** | **** |********|
+//| ** | ** |******* |******* |** |********| ****** | ****** |
+//| ** | ****** | ** | ** |** | ** ** |********| **** |
+//| ** | **** | ** | ** |******* | * * |********| ** |
+//| ** | ** | | | | | | |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | ** | ** ** | ** ** | ** | | *** | ** |
+//| | **** | ** ** | ** ** | ****** |** ** | ** ** | ** |
+//| | **** | ** ** |******* |** |** ** | *** | ** |
+//| | ** | | ** ** | ***** | ** | *** ** | |
+//| | ** | |******* | ** | ** |** *** | |
+//| | | | ** ** |****** | ** ** |** ** | |
+//| | ** | | ** ** | ** |** ** | *** ** | |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** | ** | | | | | | ** |
+//| ** | ** | ** ** | ** | | | | ** |
+//| ** | ** | **** | ** | | | | ** |
+//| ** | ** |********| ****** | | ****** | | ** |
+//| ** | ** | **** | ** | | | | ** |
+//| ** | ** | ** ** | ** | ** | | ** |** |
+//| ** | ** | | | ** | | ** |* |
+//| | | | | ** | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ***** | ** | **** | **** | *** |****** | *** |****** |
+//|** *** | *** |** ** |** ** | **** |** | ** |** ** |
+//|** **** | ** | ** | ** | ** ** |***** |** | ** |
+//|**** ** | ** | *** | *** |** ** | ** |***** | ** |
+//|*** ** | ** | ** | ** |******* | ** |** ** | ** |
+//|** ** | ** |** ** |** ** | ** |** ** |** ** | ** |
+//| ***** |****** |****** | **** | **** | **** | **** | ** |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| **** | **** | | | ** | | ** | **** |
+//|** ** |** ** | ** | ** | ** | | ** | ** ** |
+//|** ** |** ** | ** | ** | ** | ****** | ** | ** |
+//| **** | ***** | | |** | | ** | ** |
+//|** ** | ** | | | ** | ****** | ** | ** |
+//|** ** | ** | ** | ** | ** | | ** | |
+//| **** | *** | ** | ** | ** | | ** | ** |
+//| | | | ** | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ***** | ** |****** | **** |***** |******* |******* | **** |
+//|** ** | **** | ** ** | ** ** | ** ** | ** * | ** * | ** ** |
+//|** **** |** ** | ** ** |** | ** ** | ** * | ** * |** |
+//|** **** |** ** | ***** |** | ** ** | **** | **** |** |
+//|** *** |****** | ** ** |** | ** ** | ** * | ** * |** *** |
+//|** |** ** | ** ** | ** ** | ** ** | ** * | ** | ** ** |
+//| ***** |** ** |****** | **** |***** |******* |**** | *** * |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|** ** | **** | **** |*** ** |**** |** ** |** ** | *** |
+//|** ** | ** | ** | ** ** | ** |*** *** |*** ** | ** ** |
+//|** ** | ** | ** | ** ** | ** |******* |**** ** |** ** |
+//|****** | ** | ** | **** | ** |******* |** **** |** ** |
+//|** ** | ** |** ** | ** ** | ** * |** * ** |** *** |** ** |
+//|** ** | ** |** ** | ** ** | ** ** |** ** |** ** | ** ** |
+//|** ** | **** | **** |*** ** |******* |** ** |** ** | *** |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|****** | ***** |****** | ***** |****** |** ** |** ** |** ** |
+//| ** ** |** ** | ** ** |** ** |* ** * |** ** |** ** |** ** |
+//| ** ** |** ** | ** ** |*** | ** |** ** |** ** |** ** |
+//| ***** |** ** | ***** | **** | ** |** ** |** ** |** ** |
+//| ** |** * ** | ** ** | *** | ** |** ** |** ** |** * ** |
+//| ** | ***** | ** ** |** ** | ** |** ** | **** |******* |
+//|**** | *** |*** ** | ***** | **** |****** | ** | ** ** |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|** ** |** ** |******* | **** |** | **** | * | |
+//|** ** |** ** |** ** | ** | ** | ** | *** | |
+//| ** ** |** ** |* ** | ** | ** | ** | ** ** | |
+//| *** | **** | ** | ** | ** | ** |** ** | |
+//| ** ** | ** | ** * | ** | ** | ** | | |
+//|** ** | ** | ** ** | ** | ** | ** | | |
+//|** ** | **** |******* | **** | * | **** | | |
+//| | | | | | | |********|
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** | |*** | | *** | | *** | |
+//| ** | | ** | | ** | | ** ** | |
+//| ** | **** | ** | **** | ** | **** | ** * | *** ** |
+//| | ** | ***** |** ** | ***** |** ** |**** |** ** |
+//| | ***** | ** ** |** |** ** |****** | ** |** ** |
+//| |** ** | ** ** |** ** |** ** |** | ** | ***** |
+//| | *** ** |** *** | **** | *** ** | **** |**** | ** |
+//| | | | | | | |***** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|*** | ** | ** |*** | *** | | | |
+//| ** | | | ** | ** | | | |
+//| ** ** | *** | *** | ** ** | ** |** ** |* *** | **** |
+//| *** ** | ** | ** | ** ** | ** |******* |** ** |** ** |
+//| ** ** | ** | ** | **** | ** |******* |** ** |** ** |
+//| ** ** | ** |** ** | ** ** | ** |** * ** |** ** |** ** |
+//|*** ** | **** |** ** |*** ** | **** |** * ** |** ** | **** |
+//| | | **** | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | | | | * | | | |
+//| | | | | ** | | | |
+//|** *** | *** ** |** *** | ***** |****** |** ** |** ** |** ** |
+//| ** ** |** ** | *** ** |** | ** |** ** |** ** |** ** |
+//| ** ** |** ** | ** * | *** | ** |** ** |** ** |** * ** |
+//| ***** | ***** | ** | *** | ** * |** ** | **** |******* |
+//| ** | ** |**** |***** | ** | *** ** | ** | ** ** |
+//|**** | **** | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | | | *** | ** |*** | *** ** | |
+//| | | | ** | ** | ** |** *** | * |
+//|** ** |** ** |****** | ** | ** | ** | | *** |
+//| ** ** |** ** |* ** |*** | | *** | | ** ** |
+//| *** |** ** | ** | ** | ** | ** | |** ** |
+//| ** ** | ***** | ** * | ** | ** | ** | |** ** |
+//|** ** | ** |****** | *** | ** |*** | |******* |
+//| |***** | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| **** | | *** | ****** |** ** |*** | ** | |
+//|** ** |** ** | |** **| | | ** | |
+//|** | | **** | **** | **** | **** | **** | **** |
+//|** ** |** ** |** ** | ** | ** | ** | ** |** |
+//| **** |** ** |****** | ***** | ***** | ***** | ***** |** |
+//| ** |** ** |** | ** ** |** ** |** ** |** ** | **** |
+//| ** | ****** | **** | ******| ****** | ****** | ****** | ** |
+//| **** | | | | | | | *** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ****** |** ** |*** |** ** | ***** |*** |** ** | ** |
+//|** **| | | |** ** | | *** | ** |
+//| **** | **** | **** | *** | *** | *** | ** ** | |
+//| ** ** |** ** |** ** | ** | ** | ** |** ** | **** |
+//| ****** |****** |****** | ** | ** | ** |******* |** ** |
+//| ** |** |** | ** | ** | ** |** ** |****** |
+//| **** | **** | **** | **** | **** | **** |** ** |** ** |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| *** | | ***** | **** | | | **** | |
+//| | | ** ** |** ** |** ** |*** |** ** |*** |
+//|****** | *******|** ** | | | | | |
+//| ** | ** |******* | **** | **** | **** |** ** |** ** |
+//| **** | *******|** ** |** ** |** ** |** ** |** ** |** ** |
+//| ** |** ** |** ** |** ** |** ** |** ** |** ** |** ** |
+//|****** | *******|** *** | **** | **** | **** | ****** | ****** |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| |** **|** ** | ** | *** |** ** |***** | *** |
+//|** ** | ** | | ** | ** ** |** ** |** ** | ** **|
+//| | **** |** ** | ****** | ** * | **** |** ** | ** |
+//|** ** | ** ** |** ** |** |**** |****** |***** * | **** |
+//|** ** | ** ** |** ** |** | ** | ** |** ** | ** |
+//| ***** | **** |** ** | ****** |*** ** |****** |** ****| ** |
+//| ** | ** | **** | ** |****** | ** |** ** |** ** |
+//|***** | | | ** | | ** |** ***| *** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| *** | *** | | | |****** | **** | *** |
+//| | | *** | *** |***** | | ** ** | ** ** |
+//| **** | *** | | | |** ** | ** ** | ** ** |
+//| ** | ** | **** |** ** |***** |*** ** | ***** | *** |
+//| ***** | ** |** ** |** ** |** ** |****** | | |
+//|** ** | ** |** ** |** ** |** ** |** *** | ****** | ***** |
+//| ****** | **** | **** | ****** |** ** |** ** | | |
+//| | | | | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** | | |** **|** **| ** | | |
+//| | | |** ** |** ** | ** | ** **|** ** |
+//| ** | | |** ** |** ** | | ** ** | ** ** |
+//| ** |****** |****** |** **** |** ** **| ** |** ** | ** **|
+//|** |** | ** | ** **| ** ***| ** | ** ** | ** ** |
+//|** ** |** | ** | ** ** | ** ****| ** | ** **|** ** |
+//| **** | | |** ** |** ****| ** | | |
+//| | | | ****| **| | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| * * | * * * *|** ** **| ** | ** | ** | ** ** | |
+//|* * |* * * * | *** ***| ** | ** | ** | ** ** | |
+//| * * | * * * *|** ** **| ** | ** |***** | ** ** | |
+//|* * |* * * * |*** *** | ** | ** | ** | ** ** | |
+//| * * | * * * *|** ** **| ** |***** |***** |**** ** |******* |
+//|* * |* * * * | *** ***| ** | ** | ** | ** ** | ** ** |
+//| * * | * * * *|** ** **| ** | ** | ** | ** ** | ** ** |
+//|* * |* * * * |*** *** | ** | ** | ** | ** ** | ** ** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | ** ** | ** ** | | ** ** | ** ** | ** | |
+//| | ** ** | ** ** | | ** ** | ** ** | ** | |
+//|***** |**** ** | ** ** |******* |**** ** | ** ** |***** | |
+//| ** | ** | ** ** | ** | ** | ** ** | ** | |
+//|***** |**** ** | ** ** |**** ** |******* |******* |***** |***** |
+//| ** | ** ** | ** ** | ** ** | | | | ** |
+//| ** | ** ** | ** ** | ** ** | | | | ** |
+//| ** | ** ** | ** ** | ** ** | | | | ** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** | ** | | ** | | ** | ** | ** ** |
+//| ** | ** | | ** | | ** | ** | ** ** |
+//| ** | ** | | ** | | ** | *****| ** ** |
+//| ** | ** | | ** | | ** | ** | ** ** |
+//| *****|********|********| *****|********|********| *****| ** ***|
+//| | | ** | ** | | ** | ** | ** ** |
+//| | | ** | ** | | ** | ** | ** ** |
+//| | | ** | ** | | ** | ** | ** ** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** ** | | ** ** | | ** ** | | ** ** | ** |
+//| ** ** | | ** ** | | ** ** | | ** ** | ** |
+//| ** ***| ******|**** ***|********| ** ***|********|**** ***|********|
+//| ** | ** | | | ** | | | |
+//| ******| ** ***|********|**** ***| ** ***|********|**** ***|********|
+//| | ** ** | | ** ** | ** ** | | ** ** | |
+//| | ** ** | | ** ** | ** ** | | ** ** | |
+//| | ** ** | | ** ** | ** ** | | ** ** | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** ** | | | ** ** | ** | | | ** ** |
+//| ** ** | | | ** ** | ** | | | ** ** |
+//| ** ** |********| | ** ** | *****| *****| | ** ** |
+//| ** ** | | | ** ** | ** | ** | | ** ** |
+//|********|********|********| ******| *****| *****| ******|********|
+//| | ** | ** ** | | | ** | ** ** | ** ** |
+//| | ** | ** ** | | | ** | ** ** | ** ** |
+//| | ** | ** ** | | | ** | ** ** | ** ** |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| ** | ** | |********| |**** | ****|********|
+//| ** | ** | |********| |**** | ****|********|
+//|********| ** | |********| |**** | ****|********|
+//| ** | ** | |********| |**** | ****|********|
+//|********|***** | *****|********|********|**** | ****| |
+//| ** | | ** |********|********|**** | ****| |
+//| ** | | ** |********|********|**** | ****| |
+//| ** | | ** |********|********|**** | ****| |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | | | |****** | | | |
+//| | **** |****** |******* |** ** | | ** ** | *** ** |
+//| *** ** |** ** |** ** | ** ** | ** | ****** | ** ** |** *** |
+//|** *** |***** |** | ** ** | ** |** ** | ** ** | ** |
+//|** * |** ** |** | ** ** | ** |** ** | ** ** | ** |
+//|** *** |***** |** | ** ** |** ** |** ** | ***** | ** |
+//| *** ** |** |** | ** ** |****** | *** | ** | ** |
+//| |** | | | | |** | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//|****** | *** | *** | *** | | ** | *** | **** |
+//| ** | ** ** | ** ** | ** | | ** | ** |** ** |
+//| **** |** ** |** ** | ** | ****** | ****** |** |** ** |
+//|** ** |******* |** ** | ***** |** ** **|** ** **|***** |** ** |
+//|** ** |** ** | ** ** |** ** |** ** **|** ** **|** |** ** |
+//| **** | ** ** | ** ** |** ** | ****** | ****** | ** |** ** |
+//| ** | *** |*** *** | **** | | ** | *** |** ** |
+//|****** | | | | |** | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| | ** | ** | ** | *** | ** | ** | |
+//|****** | ** | ** | ** | ** **| ** | ** | *** ** |
+//| |****** | ** | ** | ** **| ** | |** *** |
+//|****** | ** | ** | ** | ** | ** |****** | |
+//| | ** | ** | ** | ** | ** | | *** ** |
+//|****** | | | | ** |** ** | ** |** *** |
+//| |****** |****** |****** | ** |** ** | ** | |
+//| | | | | ** | *** | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+//| *** | | | ****| **** | *** | | |
+//| ** ** | | | ** | ** ** | ** | | |
+//| ** ** | | | ** | ** ** | ** | **** | |
+//| *** | ** | | ** | ** ** | ** | **** | |
+//| | ** | ** |*** ** | ** ** | **** | **** | |
+//| | | | ** ** | | | **** | |
+//| | | | **** | | | | |
+//| | | | *** | | | | |
+//+--------+--------+--------+--------+--------+--------+--------+--------+
+/*****************************************************************************/
+#ifndef BIOSFONT_H
+#define BIOSFONT_H
+/*****************************************************************************/
+#ifdef BIOSFONT_UNIT_TEST
+#define BIOSFONT_STATIC
+#endif//BIOSFONT_UNIT_TEST
+/*****************************************************************************/
+#ifdef __cplusplus
+namespace BIOSfont {
+#endif//__cplusplus
+#ifdef BIOSFONT_STATIC
+ static const unsigned char bytes[ 256 ][ 8 ] = {
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} ///< character 0x00 | ^@|
+ ,{0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e} ///< character 0x01 | ^A|
+ ,{0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e} ///< character 0x02 | ^B|
+ ,{0x36,0x7f,0x7f,0x7f,0x3e,0x1c,0x08,0x00} ///< character 0x03 | ^C|
+ ,{0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x08,0x00} ///< character 0x04 | ^D|
+ ,{0x1c,0x3e,0x1c,0x7f,0x7f,0x49,0x08,0x3e} ///< character 0x05 | ^E|
+ ,{0x00,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x3e} ///< character 0x06 | ^F|
+ ,{0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00} ///< character 0x07 | ^G|
+ ,{0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff} ///< character 0x08 | ^H|
+ ,{0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00} ///< character 0x09 | ^I|
+ ,{0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff} ///< character 0x0a | ^J|
+ ,{0xf0,0xe0,0xf0,0xbe,0x33,0x33,0x33,0x1e} ///< character 0x0b | ^K|
+ ,{0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18} ///< character 0x0c | ^L|
+ ,{0xfc,0xcc,0xfc,0x0c,0x0c,0x0e,0x0f,0x07} ///< character 0x0d | ^M|
+ ,{0xfe,0xc6,0xfe,0xc6,0xc6,0xe6,0x67,0x03} ///< character 0x0e | ^N|
+ ,{0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99} ///< character 0x0f | ^O|
+ ,{0x01,0x07,0x1f,0x7f,0x1f,0x07,0x01,0x00} ///< character 0x10 | ^P|
+ ,{0x40,0x70,0x7c,0x7f,0x7c,0x70,0x40,0x00} ///< character 0x11 | ^Q|
+ ,{0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18} ///< character 0x12 | ^R|
+ ,{0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00} ///< character 0x13 | ^S|
+ ,{0xfe,0xdb,0xdb,0xde,0xd8,0xd8,0xd8,0x00} ///< character 0x14 | ^T|
+ ,{0x7c,0xc6,0x1c,0x36,0x36,0x1c,0x61,0x3f} ///< character 0x15 | ^U|
+ ,{0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00} ///< character 0x16 | ^V|
+ ,{0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff} ///< character 0x17 | ^W|
+ ,{0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00} ///< character 0x18 | ^X|
+ ,{0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00} ///< character 0x19 | ^Y|
+ ,{0x00,0x18,0x30,0x7f,0x30,0x18,0x00,0x00} ///< character 0x1a | ^Z|
+ ,{0x00,0x0c,0x06,0x7f,0x06,0x0c,0x00,0x00} ///< character 0x1b | ^[|
+ ,{0x00,0x00,0x03,0x03,0x03,0x7f,0x00,0x00} ///< character 0x1c | ^\|
+ ,{0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00} ///< character 0x1d | ^]|
+ ,{0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00} ///< character 0x1e | ^^|
+ ,{0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00} ///< character 0x1f | ^_|
+ ,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} ///< character 0x20 | |
+ ,{0x18,0x3c,0x3c,0x18,0x18,0x00,0x18,0x00} ///< character 0x21 | !|
+ ,{0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00} ///< character 0x22 | "|
+ ,{0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00} ///< character 0x23 | #|
+ ,{0x18,0x7e,0x03,0x3e,0x60,0x3f,0x18,0x00} ///< character 0x24 | $|
+ ,{0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00} ///< character 0x25 | %|
+ ,{0x1c,0x36,0x1c,0x6e,0x3b,0x33,0x6e,0x00} ///< character 0x26 | &|
+ ,{0x0c,0x0c,0x06,0x00,0x00,0x00,0x00,0x00} ///< character 0x27 | '|
+ ,{0x18,0x0c,0x06,0x06,0x06,0x0c,0x18,0x00} ///< character 0x28 | (|
+ ,{0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00} ///< character 0x29 | )|
+ ,{0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00} ///< character 0x2a | *|
+ ,{0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00} ///< character 0x2b | +|
+ ,{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0c} ///< character 0x2c | ,|
+ ,{0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00} ///< character 0x2d | -|
+ ,{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00} ///< character 0x2e | .|
+ ,{0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00} ///< character 0x2f | /|
+ ,{0x3e,0x73,0x7b,0x6f,0x67,0x63,0x3e,0x00} ///< character 0x30 | 0|
+ ,{0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x3f,0x00} ///< character 0x31 | 1|
+ ,{0x1e,0x33,0x30,0x1c,0x06,0x33,0x3f,0x00} ///< character 0x32 | 2|
+ ,{0x1e,0x33,0x30,0x1c,0x30,0x33,0x1e,0x00} ///< character 0x33 | 3|
+ ,{0x38,0x3c,0x36,0x33,0x7f,0x30,0x78,0x00} ///< character 0x34 | 4|
+ ,{0x3f,0x03,0x1f,0x30,0x30,0x33,0x1e,0x00} ///< character 0x35 | 5|
+ ,{0x1c,0x06,0x03,0x1f,0x33,0x33,0x1e,0x00} ///< character 0x36 | 6|
+ ,{0x3f,0x33,0x30,0x18,0x0c,0x0c,0x0c,0x00} ///< character 0x37 | 7|
+ ,{0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e,0x00} ///< character 0x38 | 8|
+ ,{0x1e,0x33,0x33,0x3e,0x30,0x18,0x0e,0x00} ///< character 0x39 | 9|
+ ,{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00} ///< character 0x3a | :|
+ ,{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x0c} ///< character 0x3b | ;|
+ ,{0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x00} ///< character 0x3c | <|
+ ,{0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00} ///< character 0x3d | =|
+ ,{0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00} ///< character 0x3e | >|
+ ,{0x3c,0x66,0x30,0x18,0x18,0x00,0x18,0x00} ///< character 0x3f | ?|
+ ,{0x3e,0x63,0x7b,0x7b,0x3b,0x03,0x3e,0x00} ///< character 0x40 | @|
+ ,{0x0c,0x1e,0x33,0x33,0x3f,0x33,0x33,0x00} ///< character 0x41 | A|
+ ,{0x3f,0x66,0x66,0x3e,0x66,0x66,0x3f,0x00} ///< character 0x42 | B|
+ ,{0x3c,0x66,0x03,0x03,0x03,0x66,0x3c,0x00} ///< character 0x43 | C|
+ ,{0x1f,0x36,0x66,0x66,0x66,0x36,0x1f,0x00} ///< character 0x44 | D|
+ ,{0x7f,0x46,0x16,0x1e,0x16,0x46,0x7f,0x00} ///< character 0x45 | E|
+ ,{0x7f,0x46,0x16,0x1e,0x16,0x06,0x0f,0x00} ///< character 0x46 | F|
+ ,{0x3c,0x66,0x03,0x03,0x73,0x66,0x5c,0x00} ///< character 0x47 | G|
+ ,{0x33,0x33,0x33,0x3f,0x33,0x33,0x33,0x00} ///< character 0x48 | H|
+ ,{0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0x49 | I|
+ ,{0x78,0x30,0x30,0x30,0x33,0x33,0x1e,0x00} ///< character 0x4a | J|
+ ,{0x67,0x66,0x36,0x1e,0x36,0x66,0x67,0x00} ///< character 0x4b | K|
+ ,{0x0f,0x06,0x06,0x06,0x46,0x66,0x7f,0x00} ///< character 0x4c | L|
+ ,{0x63,0x77,0x7f,0x7f,0x6b,0x63,0x63,0x00} ///< character 0x4d | M|
+ ,{0x63,0x67,0x6f,0x7b,0x73,0x63,0x63,0x00} ///< character 0x4e | N|
+ ,{0x1c,0x36,0x63,0x63,0x63,0x36,0x1c,0x00} ///< character 0x4f | O|
+ ,{0x3f,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00} ///< character 0x50 | P|
+ ,{0x3e,0x63,0x63,0x63,0x6b,0x3e,0x70,0x00} ///< character 0x51 | Q|
+ ,{0x3f,0x66,0x66,0x3e,0x36,0x66,0x67,0x00} ///< character 0x52 | R|
+ ,{0x3e,0x63,0x07,0x1e,0x70,0x63,0x3e,0x00} ///< character 0x53 | S|
+ ,{0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0x54 | T|
+ ,{0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x00} ///< character 0x55 | U|
+ ,{0x33,0x33,0x33,0x33,0x33,0x1e,0x0c,0x00} ///< character 0x56 | V|
+ ,{0x63,0x63,0x63,0x63,0x6b,0x7f,0x36,0x00} ///< character 0x57 | W|
+ ,{0x63,0x63,0x36,0x1c,0x36,0x63,0x63,0x00} ///< character 0x58 | X|
+ ,{0x33,0x33,0x33,0x1e,0x0c,0x0c,0x1e,0x00} ///< character 0x59 | Y|
+ ,{0x7f,0x63,0x31,0x18,0x4c,0x66,0x7f,0x00} ///< character 0x5a | Z|
+ ,{0x1e,0x06,0x06,0x06,0x06,0x06,0x1e,0x00} ///< character 0x5b | [|
+ ,{0x03,0x06,0x0c,0x18,0x30,0x60,0x40,0x00} ///< character 0x5c | \|
+ ,{0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00} ///< character 0x5d | ]|
+ ,{0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00} ///< character 0x5e | ^|
+ ,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff} ///< character 0x5f | _|
+ ,{0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00} ///< character 0x60 | `|
+ ,{0x00,0x00,0x1e,0x30,0x3e,0x33,0x6e,0x00} ///< character 0x61 | a|
+ ,{0x07,0x06,0x06,0x3e,0x66,0x66,0x3b,0x00} ///< character 0x62 | b|
+ ,{0x00,0x00,0x1e,0x33,0x03,0x33,0x1e,0x00} ///< character 0x63 | c|
+ ,{0x38,0x30,0x30,0x3e,0x33,0x33,0x6e,0x00} ///< character 0x64 | d|
+ ,{0x00,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00} ///< character 0x65 | e|
+ ,{0x1c,0x36,0x26,0x0f,0x06,0x06,0x0f,0x00} ///< character 0x66 | f|
+ ,{0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x1f} ///< character 0x67 | g|
+ ,{0x07,0x06,0x36,0x6e,0x66,0x66,0x67,0x00} ///< character 0x68 | h|
+ ,{0x0c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0x69 | i|
+ ,{0x30,0x00,0x38,0x30,0x30,0x33,0x33,0x1e} ///< character 0x6a | j|
+ ,{0x07,0x06,0x66,0x36,0x1e,0x36,0x67,0x00} ///< character 0x6b | k|
+ ,{0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0x6c | l|
+ ,{0x00,0x00,0x33,0x7f,0x7f,0x6b,0x6b,0x00} ///< character 0x6d | m|
+ ,{0x00,0x00,0x1d,0x33,0x33,0x33,0x33,0x00} ///< character 0x6e | n|
+ ,{0x00,0x00,0x1e,0x33,0x33,0x33,0x1e,0x00} ///< character 0x6f | o|
+ ,{0x00,0x00,0x3b,0x66,0x66,0x3e,0x06,0x0f} ///< character 0x70 | p|
+ ,{0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x78} ///< character 0x71 | q|
+ ,{0x00,0x00,0x3b,0x6e,0x46,0x06,0x0f,0x00} ///< character 0x72 | r|
+ ,{0x00,0x00,0x3e,0x03,0x0e,0x38,0x1f,0x00} ///< character 0x73 | s|
+ ,{0x08,0x0c,0x3f,0x0c,0x0c,0x2c,0x18,0x00} ///< character 0x74 | t|
+ ,{0x00,0x00,0x33,0x33,0x33,0x33,0x6e,0x00} ///< character 0x75 | u|
+ ,{0x00,0x00,0x33,0x33,0x33,0x1e,0x0c,0x00} ///< character 0x76 | v|
+ ,{0x00,0x00,0x63,0x63,0x6b,0x7f,0x36,0x00} ///< character 0x77 | w|
+ ,{0x00,0x00,0x63,0x36,0x1c,0x36,0x63,0x00} ///< character 0x78 | x|
+ ,{0x00,0x00,0x33,0x33,0x33,0x3e,0x30,0x1f} ///< character 0x79 | y|
+ ,{0x00,0x00,0x3f,0x19,0x0c,0x26,0x3f,0x00} ///< character 0x7a | z|
+ ,{0x38,0x0c,0x0c,0x07,0x0c,0x0c,0x38,0x00} ///< character 0x7b | {|
+ ,{0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00} ///< character 0x7c | ||
+ ,{0x07,0x0c,0x0c,0x38,0x0c,0x0c,0x07,0x00} ///< character 0x7d | }|
+ ,{0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00} ///< character 0x7e | ~|
+ ,{0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00} ///< character 0x7f | |
+ ,{0x1e,0x33,0x03,0x33,0x1e,0x18,0x30,0x1e} ///< character 0x80 |^M-@|
+ ,{0x00,0x33,0x00,0x33,0x33,0x33,0x7e,0x00} ///< character 0x81 |^M-A|
+ ,{0x38,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00} ///< character 0x82 |^M-B|
+ ,{0x7e,0xc3,0x3c,0x60,0x7c,0x66,0xfc,0x00} ///< character 0x83 |^M-C|
+ ,{0x33,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00} ///< character 0x84 |^M-D|
+ ,{0x07,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00} ///< character 0x85 |^M-E|
+ ,{0x0c,0x0c,0x1e,0x30,0x3e,0x33,0x7e,0x00} ///< character 0x86 |^M-F|
+ ,{0x00,0x00,0x1e,0x03,0x03,0x1e,0x30,0x1c} ///< character 0x87 |^M-G|
+ ,{0x7e,0xc3,0x3c,0x66,0x7e,0x06,0x3c,0x00} ///< character 0x88 |^M-H|
+ ,{0x33,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00} ///< character 0x89 |^M-I|
+ ,{0x07,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00} ///< character 0x8a |^M-J|
+ ,{0x33,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0x8b |^M-K|
+ ,{0x3e,0x63,0x1c,0x18,0x18,0x18,0x3c,0x00} ///< character 0x8c |^M-L|
+ ,{0x07,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0x8d |^M-M|
+ ,{0x63,0x1c,0x36,0x63,0x7f,0x63,0x63,0x00} ///< character 0x8e |^M-N|
+ ,{0x0c,0x0c,0x00,0x1e,0x33,0x3f,0x33,0x00} ///< character 0x8f |^M-O|
+ ,{0x38,0x00,0x3f,0x06,0x1e,0x06,0x3f,0x00} ///< character 0x90 |^M-P|
+ ,{0x00,0x00,0xfe,0x30,0xfe,0x33,0xfe,0x00} ///< character 0x91 |^M-Q|
+ ,{0x7c,0x36,0x33,0x7f,0x33,0x33,0x73,0x00} ///< character 0x92 |^M-R|
+ ,{0x1e,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00} ///< character 0x93 |^M-S|
+ ,{0x00,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00} ///< character 0x94 |^M-T|
+ ,{0x00,0x07,0x00,0x1e,0x33,0x33,0x1e,0x00} ///< character 0x95 |^M-U|
+ ,{0x1e,0x33,0x00,0x33,0x33,0x33,0x7e,0x00} ///< character 0x96 |^M-V|
+ ,{0x00,0x07,0x00,0x33,0x33,0x33,0x7e,0x00} ///< character 0x97 |^M-W|
+ ,{0x00,0x33,0x00,0x33,0x33,0x3e,0x30,0x1f} ///< character 0x98 |^M-X|
+ ,{0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00} ///< character 0x99 |^M-Y|
+ ,{0x33,0x00,0x33,0x33,0x33,0x33,0x1e,0x00} ///< character 0x9a |^M-Z|
+ ,{0x18,0x18,0x7e,0x03,0x03,0x7e,0x18,0x18} ///< character 0x9b |^M-[|
+ ,{0x1c,0x36,0x26,0x0f,0x06,0x67,0x3f,0x00} ///< character 0x9c |^M-\|
+ ,{0x33,0x33,0x1e,0x3f,0x0c,0x3f,0x0c,0x0c} ///< character 0x9d |^M-]|
+ ,{0x1f,0x33,0x33,0x5f,0x63,0xf3,0x63,0xe3} ///< character 0x9e |^M-^|
+ ,{0x70,0xd8,0x18,0x3c,0x18,0x18,0x1b,0x0e} ///< character 0x9f |^M-_|
+ ,{0x38,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00} ///< character 0xa0 | M- |
+ ,{0x1c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00} ///< character 0xa1 | M-!|
+ ,{0x00,0x38,0x00,0x1e,0x33,0x33,0x1e,0x00} ///< character 0xa2 | M-"|
+ ,{0x00,0x38,0x00,0x33,0x33,0x33,0x7e,0x00} ///< character 0xa3 | M-#|
+ ,{0x00,0x1f,0x00,0x1f,0x33,0x33,0x33,0x00} ///< character 0xa4 | M-$|
+ ,{0x3f,0x00,0x33,0x37,0x3f,0x3b,0x33,0x00} ///< character 0xa5 | M-%|
+ ,{0x3c,0x36,0x36,0x7c,0x00,0x7e,0x00,0x00} ///< character 0xa6 | M-&|
+ ,{0x1c,0x36,0x36,0x1c,0x00,0x3e,0x00,0x00} ///< character 0xa7 | M-'|
+ ,{0x0c,0x00,0x0c,0x06,0x03,0x33,0x1e,0x00} ///< character 0xa8 | M-(|
+ ,{0x00,0x00,0x00,0x3f,0x03,0x03,0x00,0x00} ///< character 0xa9 | M-)|
+ ,{0x00,0x00,0x00,0x3f,0x30,0x30,0x00,0x00} ///< character 0xaa | M-*|
+ ,{0xc3,0x63,0x33,0x7b,0xcc,0x66,0x33,0xf0} ///< character 0xab | M-+|
+ ,{0xc3,0x63,0x33,0xdb,0xec,0xf6,0xf3,0xc0} ///< character 0xac | M-,|
+ ,{0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00} ///< character 0xad | M--|
+ ,{0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00} ///< character 0xae | M-.|
+ ,{0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00} ///< character 0xaf | M-/|
+ ,{0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11} ///< character 0xb0 | M-0|
+ ,{0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55} ///< character 0xb1 | M-1|
+ ,{0xdb,0xee,0xdb,0x77,0xdb,0xee,0xdb,0x77} ///< character 0xb2 | M-2|
+ ,{0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18} ///< character 0xb3 | M-3|
+ ,{0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18} ///< character 0xb4 | M-4|
+ ,{0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18} ///< character 0xb5 | M-5|
+ ,{0x6c,0x6c,0x6c,0x6c,0x6f,0x6c,0x6c,0x6c} ///< character 0xb6 | M-6|
+ ,{0x00,0x00,0x00,0x00,0x7f,0x6c,0x6c,0x6c} ///< character 0xb7 | M-7|
+ ,{0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18} ///< character 0xb8 | M-8|
+ ,{0x6c,0x6c,0x6f,0x60,0x6f,0x6c,0x6c,0x6c} ///< character 0xb9 | M-9|
+ ,{0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c} ///< character 0xba | M-:|
+ ,{0x00,0x00,0x7f,0x60,0x6f,0x6c,0x6c,0x6c} ///< character 0xbb | M-;|
+ ,{0x6c,0x6c,0x6f,0x60,0x7f,0x00,0x00,0x00} ///< character 0xbc | M-<|
+ ,{0x6c,0x6c,0x6c,0x6c,0x7f,0x00,0x00,0x00} ///< character 0xbd | M-=|
+ ,{0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00} ///< character 0xbe | M->|
+ ,{0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18} ///< character 0xbf | M-?|
+ ,{0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00} ///< character 0xc0 | M-@|
+ ,{0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00} ///< character 0xc1 | M-A|
+ ,{0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18} ///< character 0xc2 | M-B|
+ ,{0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18} ///< character 0xc3 | M-C|
+ ,{0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00} ///< character 0xc4 | M-D|
+ ,{0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18} ///< character 0xc5 | M-E|
+ ,{0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18} ///< character 0xc6 | M-F|
+ ,{0x6c,0x6c,0x6c,0x6c,0xec,0x6c,0x6c,0x6c} ///< character 0xc7 | M-G|
+ ,{0x6c,0x6c,0xec,0x0c,0xfc,0x00,0x00,0x00} ///< character 0xc8 | M-H|
+ ,{0x00,0x00,0xfc,0x0c,0xec,0x6c,0x6c,0x6c} ///< character 0xc9 | M-I|
+ ,{0x6c,0x6c,0xef,0x00,0xff,0x00,0x00,0x00} ///< character 0xca | M-J|
+ ,{0x00,0x00,0xff,0x00,0xef,0x6c,0x6c,0x6c} ///< character 0xcb | M-K|
+ ,{0x6c,0x6c,0xec,0x0c,0xec,0x6c,0x6c,0x6c} ///< character 0xcc | M-L|
+ ,{0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00} ///< character 0xcd | M-M|
+ ,{0x6c,0x6c,0xef,0x00,0xef,0x6c,0x6c,0x6c} ///< character 0xce | M-N|
+ ,{0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00} ///< character 0xcf | M-O|
+ ,{0x6c,0x6c,0x6c,0x6c,0xff,0x00,0x00,0x00} ///< character 0xd0 | M-P|
+ ,{0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18} ///< character 0xd1 | M-Q|
+ ,{0x00,0x00,0x00,0x00,0xff,0x6c,0x6c,0x6c} ///< character 0xd2 | M-R|
+ ,{0x6c,0x6c,0x6c,0x6c,0xfc,0x00,0x00,0x00} ///< character 0xd3 | M-S|
+ ,{0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00} ///< character 0xd4 | M-T|
+ ,{0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18} ///< character 0xd5 | M-U|
+ ,{0x00,0x00,0x00,0x00,0xfc,0x6c,0x6c,0x6c} ///< character 0xd6 | M-V|
+ ,{0x6c,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c} ///< character 0xd7 | M-W|
+ ,{0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18} ///< character 0xd8 | M-X|
+ ,{0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00} ///< character 0xd9 | M-Y|
+ ,{0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18} ///< character 0xda | M-Z|
+ ,{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} ///< character 0xdb | M-[|
+ ,{0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff} ///< character 0xdc | M-\|
+ ,{0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f} ///< character 0xdd | M-]|
+ ,{0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} ///< character 0xde | M-^|
+ ,{0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00} ///< character 0xdf | M-_|
+ ,{0x00,0x00,0x6e,0x3b,0x13,0x3b,0x6e,0x00} ///< character 0xe0 | M-`|
+ ,{0x00,0x1e,0x33,0x1f,0x33,0x1f,0x03,0x03} ///< character 0xe1 | M-a|
+ ,{0x00,0x3f,0x33,0x03,0x03,0x03,0x03,0x00} ///< character 0xe2 | M-b|
+ ,{0x00,0x7f,0x36,0x36,0x36,0x36,0x36,0x00} ///< character 0xe3 | M-c|
+ ,{0x3f,0x33,0x06,0x0c,0x06,0x33,0x3f,0x00} ///< character 0xe4 | M-d|
+ ,{0x00,0x00,0x7e,0x1b,0x1b,0x1b,0x0e,0x00} ///< character 0xe5 | M-e|
+ ,{0x00,0x66,0x66,0x66,0x66,0x3e,0x06,0x03} ///< character 0xe6 | M-f|
+ ,{0x00,0x6e,0x3b,0x18,0x18,0x18,0x18,0x00} ///< character 0xe7 | M-g|
+ ,{0x3f,0x0c,0x1e,0x33,0x33,0x1e,0x0c,0x3f} ///< character 0xe8 | M-h|
+ ,{0x1c,0x36,0x63,0x7f,0x63,0x36,0x1c,0x00} ///< character 0xe9 | M-i|
+ ,{0x1c,0x36,0x63,0x63,0x36,0x36,0x77,0x00} ///< character 0xea | M-j|
+ ,{0x38,0x0c,0x18,0x3e,0x33,0x33,0x1e,0x00} ///< character 0xeb | M-k|
+ ,{0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00} ///< character 0xec | M-l|
+ ,{0x60,0x30,0x7e,0xdb,0xdb,0x7e,0x06,0x03} ///< character 0xed | M-m|
+ ,{0x1c,0x06,0x03,0x1f,0x03,0x06,0x1c,0x00} ///< character 0xee | M-n|
+ ,{0x1e,0x33,0x33,0x33,0x33,0x33,0x33,0x00} ///< character 0xef | M-o|
+ ,{0x00,0x3f,0x00,0x3f,0x00,0x3f,0x00,0x00} ///< character 0xf0 | M-p|
+ ,{0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x3f,0x00} ///< character 0xf1 | M-q|
+ ,{0x06,0x0c,0x18,0x0c,0x06,0x00,0x3f,0x00} ///< character 0xf2 | M-r|
+ ,{0x18,0x0c,0x06,0x0c,0x18,0x00,0x3f,0x00} ///< character 0xf3 | M-s|
+ ,{0x70,0xd8,0xd8,0x18,0x18,0x18,0x18,0x18} ///< character 0xf4 | M-t|
+ ,{0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0e} ///< character 0xf5 | M-u|
+ ,{0x0c,0x0c,0x00,0x3f,0x00,0x0c,0x0c,0x00} ///< character 0xf6 | M-v|
+ ,{0x00,0x6e,0x3b,0x00,0x6e,0x3b,0x00,0x00} ///< character 0xf7 | M-w|
+ ,{0x1c,0x36,0x36,0x1c,0x00,0x00,0x00,0x00} ///< character 0xf8 | M-x|
+ ,{0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00} ///< character 0xf9 | M-y|
+ ,{0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00} ///< character 0xfa | M-z|
+ ,{0xf0,0x30,0x30,0x30,0x37,0x36,0x3c,0x38} ///< character 0xfb | M-{|
+ ,{0x1e,0x36,0x36,0x36,0x36,0x00,0x00,0x00} ///< character 0xfc | M-||
+ ,{0x0e,0x18,0x0c,0x06,0x1e,0x00,0x00,0x00} ///< character 0xfd | M-}|
+ ,{0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00} ///< character 0xfe | M-~|
+ ,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} ///< character 0xff | |
+ };
+#else
+ extern const unsigned long long bytes[ 256 ][ 8 ];
+#endif//BIOSFONT_STATIC
+
+/*****************************************************************************/
+/// @brief This recovers one font bit.
+ inline bool
+ fontbit( const unsigned char c, const unsigned x, const unsigned y ) {
+ return !!(bytes[ c ][ y ] & (1<<x));
+ }
+#ifdef __cplusplus
+}
+
+#endif//__cplusplus
+/*****************************************************************************/
+#ifdef BIOSFONT_UNIT_TEST
+/// @brief This unit test displays the entire ROM BIOS font.
+#include <stdio.h>
+
+/*****************************************************************************/
+/// @brief This encodes one scan line for 1 character.
+inline char *
+scanchar( char *scan, const unsigned code, const unsigned line ) {
+ const char bit[ 2 ] = { ' ', '*' };
+ scan[ 0 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x01) ];
+ scan[ 1 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x02) ];
+ scan[ 2 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x04) ];
+ scan[ 3 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x08) ];
+ scan[ 4 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x10) ];
+ scan[ 5 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x20) ];
+ scan[ 6 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x40) ];
+ scan[ 7 ] = bit[ !!(BIOSfont::bytes[ code ][ line ] & 0x80) ];
+ return scan;
+}
+
+/*****************************************************************************/
+/// @brief This encodes one scan line for 8 characters across.
+inline char *
+scanline( char *cells, const unsigned start, const unsigned line ) {
+ scanchar( cells + 1 + 9 * 0, start + 0, line );
+ scanchar( cells + 1 + 9 * 1, start + 1, line );
+ scanchar( cells + 1 + 9 * 2, start + 2, line );
+ scanchar( cells + 1 + 9 * 3, start + 3, line );
+ scanchar( cells + 1 + 9 * 4, start + 4, line );
+ scanchar( cells + 1 + 9 * 5, start + 5, line );
+ scanchar( cells + 1 + 9 * 6, start + 6, line );
+ scanchar( cells + 1 + 9 * 7, start + 7, line );
+ return cells;
+}
+
+/*****************************************************************************/
+/// @brief This encodes one set of 8 characters starting at code.
+/// It marches through one set of eight, scan-line at a time..
+void display( const unsigned start ) {
+ static char line[ 80 ] =
+ "+--------+--------+--------+--------+--------+--------+--------+--------+";
+ static char cells[ 80 ] =
+ "| | | | | | | | |";
+ puts( line );
+ if( start >= 0x100 ) return;
+ puts( scanline( cells, start, 0 ) );
+ puts( scanline( cells, start, 1 ) );
+ puts( scanline( cells, start, 2 ) );
+ puts( scanline( cells, start, 3 ) );
+ puts( scanline( cells, start, 4 ) );
+ puts( scanline( cells, start, 5 ) );
+ puts( scanline( cells, start, 6 ) );
+ puts( scanline( cells, start, 7 ) );
+}
+
+/*****************************************************************************/
+/// @brief This causes the entire font to be displayed magnified.
+void display( ) { for( unsigned c = 0; c <= 0x100; c += 0x08 ) display( c );}
+
+/*****************************************************************************/
+int main( int argc, char *argv[ ] ) {
+ if( argc > 1 ) puts( argv[ 0 ] );
+ display( );
+ return 0;
+}
+/*****************************************************************************/
+#endif//BIOSFONT_UNIT_TEST
+#endif//BIOSFONT_H
+/// biosfont.h <EOF>
+/*****************************************************************************/
diff --git a/src/controller.c b/src/controller.c
new file mode 100644
index 0000000..23635a5
--- /dev/null
+++ b/src/controller.c
@@ -0,0 +1,553 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <SDL.h>
+#include <SDL_thread.h>
+
+#include "graphics.h"
+#include "controls.h"
+#include "xml.h"
+#include "osc.h"
+#include "controller.h"
+
+#define DIE(MSG, ...) { \
+ fprintf(stderr, MSG "\n", ##__VA_ARGS__); \
+ goto err; \
+}
+
+static int Slider_EnqueueMessage(struct Control *c);
+static int Field_EnqueueMessage(struct Control *c);
+static inline int EnqueueAllControls(struct Tab *tab);
+
+static inline struct Control *GetControl(struct Tab *tab, Uint16 x, Uint16 y);
+
+static inline int UpdateSliderValue(SDL_Surface *s, struct Control *c,
+ SDL_MouseMotionEvent *motion);
+
+static inline int DrawAllControls(SDL_Surface *s, struct Tab *tab);
+static void FreeRegistry(void);
+static inline int ToggleCursor(void);
+
+static inline int EvalOptions(int argc, char **argv, char **interface,
+ char **host, int *port);
+static void quit_wrapper(void);
+int main(int argc, char **argv);
+
+struct Display display = { /* initialize with default config */
+ .width = 800,
+ .height = 600,
+
+ .bpp = 16,
+
+ .flags = SDL_FULLSCREEN,
+ .cursor = SDL_DISABLE
+};
+
+#define DEFAULT_FOREGROUND 0, 255, 0
+#define DEFAULT_BACKGROUND 0, 0, 0
+
+#define DEFAULT_HOST "localhost" /* default OSC server config */
+#define DEFAULT_PORT 77777
+
+struct Registry registry = {
+ .tabs = NULL,
+ .cTabs = 0
+};
+
+static int
+Slider_EnqueueMessage(struct Control *c)
+{
+ struct Control_OSC *osc = &c->OSC;
+ struct Slider *slider = &c->u.slider;
+
+ if (osc->address)
+ switch (osc->datatype) {
+ case OSC_INT:
+ case OSC_FLOAT:
+ case OSC_DOUBLE:
+ case OSC_BOOL:
+ return Osc_EnqueueFloatMessage(osc->address, slider->value);
+ }
+
+ return 0;
+}
+
+static int
+Field_EnqueueMessage(struct Control *c)
+{
+ struct Control_OSC *osc = &c->OSC;
+ struct Field *field = &c->u.field;
+
+ if (osc->address)
+ switch (osc->datatype) {
+ case OSC_INT:
+ case OSC_FLOAT:
+ case OSC_DOUBLE:
+ case OSC_BOOL:
+ return Osc_EnqueueFloatMessage(osc->address, field->value);
+ }
+
+ return 0;
+}
+
+static inline int
+EnqueueAllControls(struct Tab *tab)
+{
+ struct Control *cur = tab->controls;
+
+ for (Uint32 c = tab->cControls; c; c--, cur++)
+ switch (cur->type) {
+ case SLIDER:
+ if (Slider_EnqueueMessage(cur))
+ return 1;
+ break;
+
+ case FIELD:
+ if (cur->u.field.type == FIELD_SWITCH &&
+ Field_EnqueueMessage(cur))
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static inline struct Control *
+GetControl(struct Tab *tab, Uint16 x, Uint16 y)
+{
+ struct Control *cur = tab->controls;
+
+ for (Uint32 c = tab->cControls; c; c--, cur++)
+ if (x >= cur->geo.x && x <= cur->geo.x + cur->geo.w)
+ switch (cur->type) {
+ case SLIDER:
+ switch (cur->u.slider.type) {
+ case SLIDER_SET:
+ case SLIDER_RELATIVE:
+ if (y >= cur->geo.y && y <= cur->geo.y + cur->geo.h)
+ return cur;
+ break;
+
+ case SLIDER_BUTTON: {
+ struct Slider_Button *button = &cur->u.slider.u.button;
+
+ if (y >= button->button_y && y <= button->button_y +
+ (SLIDER_PADDING(cur) << 1))
+ return cur;
+ break;
+ }
+ }
+ break;
+
+ case FIELD:
+ if (y >= cur->geo.y && y <= cur->geo.y + cur->geo.h)
+ return cur;
+ break;
+ }
+
+ return NULL;
+}
+
+static inline int
+UpdateSliderValue(SDL_Surface *s, struct Control *c,
+ SDL_MouseMotionEvent *motion)
+{
+ struct Slider *slider = &c->u.slider;
+ Uint16 padding = SLIDER_PADDING(c);
+
+ if (slider->show_value) {
+ SDL_Rect text;
+ int len = snprintf(NULL, 0, "%g/%g", slider->value, slider->max);
+
+ if (len == -1)
+ return 1;
+
+ text.x = c->geo.x;
+ text.y = c->geo.y + c->geo.h + 1;
+ text.w = len*FONTWIDTH;
+ text.h = FONTHEIGHT;
+
+ if (Graphics_BlankRect(s, &text))
+ return 1;
+ SDL_UpdateRects(s, 1, &text);
+ }
+
+ switch (slider->type) {
+ case SLIDER_SET:
+ case SLIDER_BUTTON:
+ if (motion->y <= c->geo.y + padding)
+ slider->value = slider->max;
+ else if (motion->y >= c->geo.y + c->geo.h - padding)
+ slider->value = slider->min;
+ else
+ Controls_SetSliderValue(
+ slider,
+ (1. - (double)(motion->y - c->geo.y)/c->geo.h)*
+ (slider->max - slider->min) + slider->min);
+
+ if (slider->type == SLIDER_BUTTON) {
+ struct Slider_Button *button = &slider->u.button;
+ Uint16 x;
+
+ button->button_y += motion->yrel;
+
+ if (button->button_y < (x = c->geo.y + 1) ||
+ button->button_y > (x = c->geo.y + c->geo.h -
+ (padding << 1) - 1))
+ button->button_y = x;
+ }
+
+ break;
+
+ case SLIDER_RELATIVE: {
+ double v = slider->value - (double)motion->yrel/c->geo.h*
+ (slider->max - slider->min);
+
+ if (v > slider->max)
+ slider->value = slider->max;
+ else if (v < slider->min)
+ slider->value = slider->min;
+ else
+ Controls_SetSliderValue(slider, v);
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static inline int
+DrawAllControls(SDL_Surface *s, struct Tab *tab)
+{
+ struct Control *cur = tab->controls;
+
+ for (Uint32 c = tab->cControls; c; c--, cur++)
+ if (Controls_Draw(s, cur))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * not that useful right now but might become handy later when we need to load
+ * interface dynamically
+ */
+
+static void
+FreeRegistry(void)
+{
+ for (struct Tab *tab = registry.tabs; registry.cTabs;
+ registry.cTabs--, tab++) {
+ for (struct Control *control = tab->controls; tab->cControls;
+ tab->cControls--, control++) {
+ free(control->OSC.address);
+
+ switch (control->type) {
+ case SLIDER:
+ free(control->u.slider.label);
+ break;
+
+ case FIELD:
+ free(control->u.field.label);
+ break;
+ }
+ }
+
+ free(tab->controls);
+ free(tab->label);
+ }
+
+ free(registry.tabs);
+ memset(&registry, 0, sizeof(struct Registry));
+}
+
+static inline int
+ToggleCursor(void)
+{
+ return (display.cursor = display.cursor == SDL_ENABLE ?
+ SDL_DISABLE : SDL_ENABLE);
+}
+
+static inline int
+EvalOptions(int argc, char **argv, char **interface, char **host, int *port)
+{
+ int c;
+ char *p;
+
+ while ((c = getopt(argc, argv, "hg:b:fci:r:p:d")) != -1)
+ switch (c) {
+ case '?':
+ case 'h':
+ if ((p = strrchr(argv[0], PATH_SEPARATOR)))
+ p++;
+ else
+ p = argv[0];
+
+ printf(WINDOW_TITLE "\n\n"
+ "%s\t-h\t\t" "Show this help\n"
+ "\t\t-i INTERFACE\t" "Interface XML file\n"
+ "\t\t-g WIDTHxHEIGHT\t" "Screen resolution\n"
+ "\t\t-b BPP\t\t" "Color depth\n"
+ "\t\t-f\t\t" "Toggle fullscreen mode\n"
+ "\t\t-c\t\t" "Toggle mouse cursor display\n"
+ "\t\t-r HOST\t\t" "Remote host (OSC server)\n"
+ "\t\t-p PORT\t\t" "Remote port\n"
+ "\t\t-d\t\t" "Disable OSC message dispatching\n\n",
+ p);
+
+ return 1;
+
+ case 'g':
+ if (sscanf(optarg, "%ux%u", &display.width,
+ &display.height) != 2)
+ return 1;
+ break;
+
+ case 'b':
+ display.bpp = strtoul(optarg, &p, 10);
+ if (*p)
+ return 1;
+ break;
+
+ case 'f':
+ display.flags = (display.flags | SDL_FULLSCREEN) &
+ ~(display.flags & SDL_FULLSCREEN);
+ /* ^ toggles fullscreen flag */
+ break;
+
+ case 'c':
+ ToggleCursor();
+ break;
+
+ case 'i':
+ *interface = optarg;
+ break;
+
+ case 'r':
+ *host = optarg;
+ break;
+
+ case 'p':
+ *port = strtoul(optarg, &p, 10);
+ if (*p)
+ return 1;
+ break;
+
+ case 'd':
+ *host = NULL;
+ break;
+ }
+
+ return 0;
+}
+
+static void
+quit_wrapper(void)
+{
+ SDL_Quit();
+}
+
+int main(int argc, char **argv)
+{
+ SDL_Surface *s = NULL;
+
+ SDL_Event event;
+ SDL_MouseButtonEvent *button = &event.button;
+ SDL_MouseMotionEvent *motion = &event.motion;
+
+ struct Tab *curTab;
+ struct Control *cur = NULL;
+
+ char *interface = NULL;
+ char *host = DEFAULT_HOST; /* default config, s.a. */
+ int port = DEFAULT_PORT;
+
+ int socket_fd = -1;
+ SDL_Thread *oscThread = NULL;
+
+ /* TODO: update global (display) default config by evaluating a
+ config XML file */
+
+ if (EvalOptions(argc, argv, &interface, &host, &port))
+ DIE("Error during command line option pasing.");
+
+ if (!interface)
+ DIE("You have to specify an interface definition (-i option).");
+
+ if (host) {
+ if ((socket_fd = Osc_Connect(host, port)) < 0)
+ DIE("Couldn't create and connect socket.");
+
+ if (!(oscThread = Osc_InitThread(&socket_fd)))
+ DIE("Error initializing the OSC sending thread.");
+ }
+
+ if (SDL_Init(SDL_INIT_VIDEO))
+ DIE("Couldn't initialize video subsystem.");
+
+ atexit(quit_wrapper);
+
+ SDL_WM_SetCaption(WINDOW_TITLE, NULL);
+#ifdef __OS2__
+ SDL_ShowCursor(SDL_DISABLE);
+#endif
+ SDL_ShowCursor(display.cursor);
+
+ if (!(s = SDL_SetVideoMode(display.width, display.height,
+ display.bpp, display.flags)))
+ DIE("Couldn't set video mode.");
+
+ /* default config, s.a. */
+ display.foreground = SDL_MapRGB(s->format, DEFAULT_FOREGROUND);
+ display.background = SDL_MapRGB(s->format, DEFAULT_BACKGROUND);
+
+ if (Xml_ReadInterface(interface, s))
+ DIE("Error parsing interface definition.");
+
+ curTab = registry.tabs; /* first tab */
+
+ if (host && EnqueueAllControls(curTab))
+ DIE("Couldn't enqueue OSC message.");
+
+ /* draw control interface */
+
+ if (Graphics_BlankRect(s, NULL))
+ DIE("Couldn't set background color.");
+ SDL_UpdateRect(s, 0, 0, 0, 0);
+
+ if (DrawAllControls(s, curTab))
+ DIE("Couldn't draw control.");
+
+ while (SDL_WaitEvent(&event))
+ switch (event.type) {
+ case SDL_KEYUP:
+ switch (event.key.keysym.sym) {
+ case SDLK_f: /* toggle (f)ullscreen */
+ if (!SDL_WM_ToggleFullScreen(s))
+ DIE("Couldn't toggle fullscreen state.");
+#ifndef __OS2__ /* at least in OS/2 we need to redraw the screen */
+ break;
+#endif
+
+ case SDLK_r: /* refresh */
+ SDL_UpdateRect(s, 0, 0, 0, 0);
+
+ if (display.cursor == SDL_ENABLE) {
+ SDL_ShowCursor(SDL_DISABLE);
+ SDL_ShowCursor(SDL_ENABLE);
+ }
+ break;
+
+ case SDLK_c: /* toggle cursor */
+ SDL_ShowCursor(ToggleCursor());
+ break;
+
+ case SDLK_q: /* quit */
+ case SDLK_ESCAPE:
+ goto finish;
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ if (cur) {
+ switch (cur->type) {
+ case FIELD: {
+ struct Field *field = &cur->u.field;
+
+ field->value = field->type == FIELD_BUTTON ?
+ 0 : !field->value;
+
+ if (host && Field_EnqueueMessage(cur))
+ DIE("Couldn't enqueue OSC message.");
+
+ if (Controls_Field(s, cur))
+ DIE("Couldn't draw control.");
+
+ break;
+ }
+ }
+
+ cur = NULL;
+ }
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ if (button->button == SDL_BUTTON_LEFT &&
+ (cur = GetControl(curTab, motion->x, motion->y)))
+ switch (cur->type) {
+ case FIELD: {
+ struct Field *field = &cur->u.field;
+
+ if (field->type == FIELD_BUTTON) {
+ field->value = 1;
+
+ if (host && Field_EnqueueMessage(cur))
+ DIE("Couldn't enqueue OSC message.");
+
+ if (Controls_Field(s, cur))
+ DIE("Couldn't draw control.");
+ }
+ break;
+ }
+ }
+
+ case SDL_MOUSEMOTION:
+ if (cur)
+ switch (cur->type) {
+ case SLIDER:
+ if (UpdateSliderValue(s, cur, motion))
+ DIE("Couldn't update control value.");
+
+ if (host && Slider_EnqueueMessage(cur))
+ DIE("Couldn't enqueue OSC message.");
+
+ if (Controls_Slider(s, cur))
+ DIE("Couldn't draw control.");
+ break;
+ }
+ break;
+
+ case SDL_USEREVENT:
+ switch ((enum Controller_Event)event.user.code) {
+ case CONTROLLER_ERR_THREAD:
+ DIE("Error during OSC thread execution.");
+ }
+ break;
+
+ case SDL_QUIT: /* quit */
+ goto finish;
+ }
+ DIE("Error retrieving event.");
+
+finish:
+
+ FreeRegistry();
+ SDL_FreeSurface(s);
+ if (host) {
+ Osc_Disconnect(socket_fd);
+ if (Osc_TerminateThread())
+ return 1;
+ }
+
+ return 0;
+
+err:
+
+ FreeRegistry();
+ if (s)
+ SDL_FreeSurface(s);
+ if (oscThread)
+ Osc_TerminateThread();
+ if (socket_fd > 0)
+ Osc_Disconnect(socket_fd);
+
+ return 1;
+}
diff --git a/src/controller.h b/src/controller.h
new file mode 100644
index 0000000..b459681
--- /dev/null
+++ b/src/controller.h
@@ -0,0 +1,55 @@
+
+#ifndef __CONTROLLER_H
+#define __CONTROLLER_H
+
+#include <SDL.h>
+
+#include "controls.h"
+
+extern struct Display {
+ int width;
+ int height;
+
+ int bpp;
+
+ Uint32 flags;
+ int cursor;
+
+ Uint32 foreground;
+ Uint32 background;
+} display;
+
+extern struct Registry {
+ struct Tab {
+ struct Control *controls;
+ Uint32 cControls;
+
+ char *label;
+ } *tabs;
+ Uint32 cTabs;
+} registry;
+
+#ifndef PACKAGE_NAME
+#define PACKAGE_NAME "Virtual OSC Controller"
+#endif
+#ifndef PACKAGE_VERSION
+#define PACKAGE_VERSION "dev"
+#endif
+
+#define WINDOW_TITLE PACKAGE_NAME " (" PACKAGE_VERSION ")"
+
+#ifndef PATH_SEPARATOR
+# if defined(__OS2__) || defined(__NT__)
+# define PATH_SEPARATOR '\\'
+# else
+# define PATH_SEPARATOR '/'
+# endif
+#endif
+
+enum Controller_Event {
+ CONTROLLER_OK = 0,
+ CONTROLLER_ERR_THREAD
+};
+
+#endif
+
diff --git a/src/controls.c b/src/controls.c
new file mode 100644
index 0000000..525ce55
--- /dev/null
+++ b/src/controls.c
@@ -0,0 +1,190 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <SDL.h>
+
+#include "graphics.h"
+#include "controls.h"
+#include "controller.h"
+
+int
+Controls_Slider(SDL_Surface *s, struct Control *c)
+{
+ struct Slider *slider = &c->u.slider;
+ struct Paint *paint = &slider->paint;
+
+ Uint32 border_color;
+
+ Uint16 padding = SLIDER_PADDING(c);
+ SDL_Rect bar;
+
+ if (Graphics_BlankRect(s, &c->geo))
+ return 1;
+
+ bar.x = c->geo.x + padding;
+ bar.w = c->geo.w - (padding << 1);
+
+ if (slider->step) { /* stepwise */
+ float cr, cg, cb;
+ float diff_r, diff_g, diff_b;
+
+ Uint32 color;
+
+ Uint16 steps = (slider->max - slider->min)/slider->step;
+ float box_s = (float)(c->geo.h - padding)/steps;
+ float fy = c->geo.y + c->geo.h - box_s;
+
+ bar.h = box_s - padding;
+
+ switch (paint->type) {
+ case PAINT_PLAIN:
+ color = border_color = paint->u.plain.color;
+ break;
+
+ case PAINT_GRAD: {
+ struct Paint_Grad *grad = &paint->u.grad;
+
+ cr = grad->bottom.r;
+ cg = grad->bottom.g;
+ cb = grad->bottom.b;
+
+ diff_r = (float)(grad->top.r - cr)/steps;
+ diff_g = (float)(grad->top.g - cg)/steps;
+ diff_b = (float)(grad->top.b - cb)/steps;
+
+ break;
+ }
+ }
+
+ for (double i = slider->min; i < slider->value;
+ i += slider->step, fy -= box_s) {
+ if (paint->type == PAINT_GRAD) {
+ color = SDL_MapRGB(s->format, cr, cg, cb);
+
+ cr += diff_r;
+ cg += diff_g;
+ cb += diff_b;
+ }
+
+ bar.y = fy;
+
+ if (Graphics_FillRect(s, &bar, color))
+ return 1;
+ }
+
+ if (paint->type == PAINT_GRAD)
+ border_color = SDL_MapRGB(s->format, cr, cg, cb);
+ } else { /* continious */
+ Uint16 max_h = c->geo.h - (padding << 1);
+
+ bar.h = (slider->value - slider->min)*max_h/
+ (slider->max - slider->min);
+ bar.y = c->geo.y + c->geo.h - padding - bar.h;
+
+ switch (paint->type) {
+ case PAINT_PLAIN:
+ border_color = paint->u.plain.color;
+ if (Graphics_FillRect(s, &bar, border_color))
+ return 1;
+
+ break;
+
+ case PAINT_GRAD: {
+ SDL_Color border;
+
+ if (Graphics_GradFillRect(s, &bar, max_h,
+ &paint->u.grad.top,
+ &paint->u.grad.bottom, &border))
+ return 1;
+
+ border_color = SDL_MapRGB(s->format, border.r, border.g,
+ border.b);
+ break;
+ }
+ }
+ }
+
+ if (Graphics_DrawRect(s, &c->geo, border_color))
+ return 1;
+
+ if (slider->type == SLIDER_BUTTON) {
+ bar.w = c->geo.w - 2; /* reuse 'bar' */
+ bar.h = padding << 1;
+ bar.x = c->geo.x + 1;
+ bar.y = slider->u.button.button_y;
+
+ if (Graphics_FillRect(s, &bar, border_color))
+ return 1;
+ }
+
+ SDL_UpdateRects(s, 1, &c->geo);
+
+ /* slider label */
+
+ if (slider->label) {
+ if (Graphics_WriteText(s, c->geo.x, c->geo.y - FONTHEIGHT,
+ slider->label, border_color))
+ return 1;
+ SDL_UpdateRect(s, c->geo.x, c->geo.y - FONTHEIGHT,
+ strlen(slider->label)*FONTWIDTH, FONTHEIGHT);
+ }
+
+ /* slider value */
+
+ if (slider->show_value) {
+ Uint16 y = c->geo.y + c->geo.h + 1;
+ int len = Graphics_printf(s, c->geo.x, y, border_color,
+ "%g/%g", slider->value, slider->max);
+
+ if (len == -1)
+ return 1;
+
+ SDL_UpdateRect(s, c->geo.x, y, len*FONTWIDTH, FONTHEIGHT);
+ }
+
+ return 0;
+}
+
+int
+Controls_Field(SDL_Surface *s, struct Control *c)
+{
+ struct Field *field = &c->u.field;
+
+ if (Graphics_BlankRect(s, &c->geo))
+ return 1;
+
+ if (field->value) {
+ if (Graphics_FillRect(s, &c->geo, field->color))
+ return 1;
+ } else if (Graphics_DrawRect(s, &c->geo, field->color))
+ return 1;
+
+ if (field->label &&
+ Graphics_WriteText(s, c->geo.x + c->geo.w/2 -
+ strlen(field->label)*(FONTWIDTH/2),
+ c->geo.y + c->geo.h/2 - FONTHEIGHT/2,
+ field->label, field->value ?
+ display.background : field->color))
+ return 1;
+
+ SDL_UpdateRects(s, 1, &c->geo);
+ return 0;
+}
+
+int
+Controls_Draw(SDL_Surface *s, struct Control *c)
+{
+ switch (c->type) {
+ case SLIDER:
+ return Controls_Slider(s, c);
+ case FIELD:
+ return Controls_Field(s, c);
+ }
+
+ return 1;
+}
+
diff --git a/src/controls.h b/src/controls.h
new file mode 100644
index 0000000..29e687a
--- /dev/null
+++ b/src/controls.h
@@ -0,0 +1,113 @@
+
+#ifndef __CONTROLS_H
+#define __CONTROLS_H
+
+#include <SDL.h>
+
+#include "osc.h"
+
+struct Paint {
+ enum Paint_Type {
+ PAINT_PLAIN = 0,
+ PAINT_GRAD
+ } type;
+
+ union {
+ struct Paint_Plain {
+ Uint32 color;
+ } plain;
+
+ struct Paint_Grad {
+ SDL_Color top;
+ SDL_Color bottom;
+ } grad;
+ } u;
+};
+
+struct Control {
+ enum Control_Type {
+ SLIDER = 0,
+ FIELD
+ } type;
+
+ SDL_Rect geo;
+
+ struct Control_OSC {
+ char *address;
+ enum Osc_DataType datatype;
+ } OSC;
+
+ union {
+ struct Slider {
+ enum Slider_Type {
+ SLIDER_BUTTON = 0,
+ SLIDER_SET,
+ SLIDER_RELATIVE
+ } type;
+ #define SLIDER_TYPE \
+ "button\0" \
+ "set\0" \
+ "relative\0"
+
+ struct Paint paint;
+
+ double min;
+ double max;
+ double step;
+
+ double value;
+
+ char *label;
+ Uint8 show_value;
+
+ union {
+ struct Slider_Button {
+ Uint16 button_y;
+ } button;
+ } u;
+ } slider;
+
+ struct Field {
+ enum Field_Type {
+ FIELD_BUTTON = 0,
+ FIELD_SWITCH
+ } type;
+
+ Uint32 color;
+ Uint8 value;
+ char *label;
+ } field;
+ } u;
+};
+
+ /* slider inner padding is 1/2000 of its area */
+#define SLIDER_PADDING(C) ((C)->geo.w*(C)->geo.h/2000)
+
+static inline void Controls_SetSliderValue(struct Slider *slider, double value);
+static inline void Controls_InitSliderButton(struct Control *c);
+
+int Controls_Slider(SDL_Surface *s, struct Control *c);
+int Controls_Field(SDL_Surface *s, struct Control *c);
+int Controls_Draw(SDL_Surface *s, struct Control *c);
+
+static inline void
+Controls_SetSliderValue(struct Slider *slider, double value)
+{
+ slider->value = slider->step ?
+ (Uint32)((value - slider->min)/slider->step+.5)*
+ slider->step + slider->min : value;
+}
+
+static inline void
+Controls_InitSliderButton(struct Control *c)
+{
+ struct Slider *slider = &c->u.slider;
+ Uint16 padding = SLIDER_PADDING(c);
+
+ slider->u.button.button_y = c->geo.y + (c->geo.h - (padding << 1))*
+ (1. - (slider->value - slider->min)/
+ (slider->max - slider->min)) - padding;
+}
+
+#endif
+
diff --git a/src/fontface.c b/src/fontface.c
new file mode 100644
index 0000000..2e9f352
--- /dev/null
+++ b/src/fontface.c
@@ -0,0 +1,3101 @@
+/*
+ * modified file from sdl_picofont (originally Linux source...):
+ */
+
+/* sdl_picofont
+
+ http://nurd.se/~noname/sdl_picofont
+
+ File authors:
+ Fredrik Hultin
+
+ With code from:
+ Greg Harp
+ John Shifflett
+
+ License: GPLv2
+*/
+
+/* This is the font_pearl_8x8.c file from the linux source with some minor modifications */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <SDL.h>
+
+#include "fontface.h"
+
+const Uint8 Font_Face[256][FONTHEIGHT] = {
+ /* 0 0x00 '^@' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 1 0x01 '^A' */
+ {
+ 0x7e, /* 01111110 */
+ 0x81, /* 10000001 */
+ 0xa5, /* 10100101 */
+ 0x81, /* 10000001 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0x81, /* 10000001 */
+ 0x7e /* 01111110 */
+ },
+
+ /* 2 0x02 '^B' */
+ {
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xdb, /* 11011011 */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0x7e /* 01111110 */
+ },
+
+ /* 3 0x03 '^C' */
+ {
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 4 0x04 '^D' */
+ {
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 5 0x05 '^E' */
+ {
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0x10, /* 00010000 */
+ 0x38 /* 00111000 */
+ },
+
+ /* 6 0x06 '^F' */
+ {
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x10, /* 00010000 */
+ 0x38 /* 00111000 */
+ },
+
+ /* 7 0x07 '^G' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 8 0x08 '^H' */
+ {
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xe7, /* 11100111 */
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff /* 11111111 */
+ },
+
+ /* 9 0x09 '^I' */
+ {
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x42, /* 01000010 */
+ 0x42, /* 01000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 10 0x0a '^J' */
+ {
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0x99, /* 10011001 */
+ 0xbd, /* 10111101 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0xc3, /* 11000011 */
+ 0xff /* 11111111 */
+ },
+
+ /* 11 0x0b '^K' */
+ {
+ 0x0f, /* 00001111 */
+ 0x07, /* 00000111 */
+ 0x0f, /* 00001111 */
+ 0x7d, /* 01111101 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78 /* 01111000 */
+ },
+
+ /* 12 0x0c '^L' */
+ {
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 13 0x0d '^M' */
+ {
+ 0x3f, /* 00111111 */
+ 0x33, /* 00110011 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x70, /* 01110000 */
+ 0xf0, /* 11110000 */
+ 0xe0 /* 11100000 */
+ },
+
+ /* 14 0x0e '^N' */
+ {
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x67, /* 01100111 */
+ 0xe6, /* 11100110 */
+ 0xc0 /* 11000000 */
+ },
+
+ /* 15 0x0f '^O' */
+ {
+ 0x18, /* 00011000 */
+ 0xdb, /* 11011011 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0x3c, /* 00111100 */
+ 0xdb, /* 11011011 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 16 0x10 '^P' */
+ {
+ 0x80, /* 10000000 */
+ 0xe0, /* 11100000 */
+ 0xf8, /* 11111000 */
+ 0xfe, /* 11111110 */
+ 0xf8, /* 11111000 */
+ 0xe0, /* 11100000 */
+ 0x80, /* 10000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 17 0x11 '^Q' */
+ {
+ 0x02, /* 00000010 */
+ 0x0e, /* 00001110 */
+ 0x3e, /* 00111110 */
+ 0xfe, /* 11111110 */
+ 0x3e, /* 00111110 */
+ 0x0e, /* 00001110 */
+ 0x02, /* 00000010 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 18 0x12 '^R' */
+ {
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 19 0x13 '^S' */
+ {
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 20 0x14 '^T' */
+ {
+ 0x7f, /* 01111111 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7b, /* 01111011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 21 0x15 '^U' */
+ {
+ 0x3e, /* 00111110 */
+ 0x61, /* 01100001 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x86, /* 10000110 */
+ 0x7c /* 01111100 */
+ },
+
+ /* 22 0x16 '^V' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 23 0x17 '^W' */
+ {
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0xff /* 11111111 */
+ },
+
+ /* 24 0x18 '^X' */
+ {
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 25 0x19 '^Y' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 26 0x1a '^Z' */
+ {
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 27 0x1b '^[' */
+ {
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 28 0x1c '^\' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 29 0x1d '^]' */
+ {
+ 0x00, /* 00000000 */
+ 0x24, /* 00100100 */
+ 0x66, /* 01100110 */
+ 0xff, /* 11111111 */
+ 0x66, /* 01100110 */
+ 0x24, /* 00100100 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 30 0x1e '^^' */
+ {
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 31 0x1f '^_' */
+ {
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 32 0x20 ' ' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 33 0x21 '!' */
+ {
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 34 0x22 '"' */
+ {
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 35 0x23 '#' */
+ {
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 36 0x24 '$' */
+ {
+ 0x18, /* 00011000 */
+ 0x3e, /* 00111110 */
+ 0x60, /* 01100000 */
+ 0x3c, /* 00111100 */
+ 0x06, /* 00000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 37 0x25 '%' */
+ {
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x66, /* 01100110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 38 0x26 '&' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x68, /* 01101000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 39 0x27 ''' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 40 0x28 '(' */
+ {
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 41 0x29 ')' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 42 0x2a '*' */
+ {
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0xff, /* 11111111 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 43 0x2b '+' */
+ {
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 44 0x2c ',' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30 /* 00110000 */
+ },
+
+ /* 45 0x2d '-' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 46 0x2e '.' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 47 0x2f '/' */
+ {
+ 0x03, /* 00000011 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 48 0x30 '0' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xde, /* 11011110 */
+ 0xfe, /* 11111110 */
+ 0xf6, /* 11110110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 49 0x31 '1' */
+ {
+ 0x18, /* 00011000 */
+ 0x78, /* 01111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 50 0x32 '2' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 51 0x33 '3' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x1c, /* 00011100 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 52 0x34 '4' */
+ {
+ 0x1c, /* 00011100 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 53 0x35 '5' */
+ {
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 54 0x36 '6' */
+ {
+ 0x38, /* 00111000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 55 0x37 '7' */
+ {
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 56 0x38 '8' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 57 0x39 '9' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ },
+
+ /* 58 0x3a ':' */
+ {
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 59 0x3b ';' */
+ {
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30 /* 00110000 */
+ },
+
+ /* 60 0x3c '<' */
+ {
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 61 0x3d '=' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 62 0x3e '>' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 63 0x3f '?' */
+ {
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 64 0x40 '@' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 65 0x41 'A' */
+ {
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 66 0x42 'B' */
+ {
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 67 0x43 'C' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 68 0x44 'D' */
+ {
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 69 0x45 'E' */
+ {
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xf8, /* 11111000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 70 0x46 'F' */
+ {
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xf8, /* 11111000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 71 0x47 'G' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 72 0x48 'H' */
+ {
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 73 0x49 'I' */
+ {
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 74 0x4a 'J' */
+ {
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 75 0x4b 'K' */
+ {
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0xd8, /* 11011000 */
+ 0xf0, /* 11110000 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 76 0x4c 'L' */
+ {
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 77 0x4d 'M' */
+ {
+ 0x82, /* 10000010 */
+ 0xc6, /* 11000110 */
+ 0xee, /* 11101110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 78 0x4e 'N' */
+ {
+ 0xc6, /* 11000110 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 79 0x4f 'O' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 80 0x50 'P' */
+ {
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 81 0x51 'Q' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xf6, /* 11110110 */
+ 0xde, /* 11011110 */
+ 0x7c, /* 01111100 */
+ 0x06, /* 00000110 */
+ },
+
+ /* 82 0x52 'R' */
+ {
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 83 0x53 'S' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 84 0x54 'T' */
+ {
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 85 0x55 'U' */
+ {
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 86 0x56 'V' */
+ {
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 87 0x57 'W' */
+ {
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0xee, /* 11101110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 88 0x58 'X' */
+ {
+ 0xc3, /* 11000011 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc3, /* 11000011 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 89 0x59 'Y' */
+ {
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 90 0x5a 'Z' */
+ {
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 91 0x5b '[' */
+ {
+ 0x3c, /* 00111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 92 0x5c '\' */
+ {
+ 0xc0, /* 11000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x03, /* 00000011 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 93 0x5d ']' */
+ {
+ 0x3c, /* 00111100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 94 0x5e '^' */
+ {
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 95 0x5f '_' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe /* 11111110 */
+ },
+
+ /* 96 0x60 '`' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 97 0x61 'a' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0x06, /* 00000110 */
+ 0x7e, /* 01111110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 98 0x62 'b' */
+ {
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 99 0x63 'c' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 100 0x64 'd' */
+ {
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x7e, /* 01111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 101 0x65 'e' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 102 0x66 'f' */
+ {
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 103 0x67 'g' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x7c /* 01111100 */
+ },
+
+ /* 104 0x68 'h' */
+ {
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 105 0x69 'i' */
+ {
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 106 0x6a 'j' */
+ {
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c /* 01111100 */
+ },
+
+ /* 107 0x6b 'k' */
+ {
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xcc, /* 11001100 */
+ 0xd8, /* 11011000 */
+ 0xf0, /* 11110000 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 108 0x6c 'l' */
+ {
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 109 0x6d 'm' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xec, /* 11101100 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 110 0x6e 'n' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 111 0x6f 'o' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 112 0x70 'p' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfc, /* 11111100 */
+ 0xc0, /* 11000000 */
+ 0xc0 /* 11000000 */
+ },
+
+ /* 113 0x71 'q' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x06 /* 00000110 */
+ },
+
+ /* 114 0x72 'r' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0xe6, /* 11100110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 115 0x73 's' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x06, /* 00000110 */
+ 0xfc, /* 11111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 116 0x74 't' */
+ {
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x7c, /* 01111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x36, /* 00110110 */
+ 0x1c, /* 00011100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 117 0x75 'u' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 118 0x76 'v' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 119 0x77 'w' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 120 0x78 'x' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 121 0x79 'y' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc3, /* 11000011 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60 /* 01100000 */
+ },
+
+ /* 122 0x7a 'z' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x38, /* 00111000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 123 0x7b '{' */
+ {
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 124 0x7c '|' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 125 0x7d '}' */
+ {
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 126 0x7e '~' */
+ {
+ 0x72, /* 01110010 */
+ 0x9c, /* 10011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 127 0x7f '' */
+ {
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 128 0x80 '�' */
+ {
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x78 /* 01111000 */
+ },
+
+ /* 129 0x81 '?' */
+ {
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 130 0x82 '�' */
+ {
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 131 0x83 '�' */
+ {
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 132 0x84 '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 133 0x85 '�' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 134 0x86 '�' */
+ {
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 135 0x87 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x7e, /* 01111110 */
+ 0x0c, /* 00001100 */
+ 0x38 /* 00111000 */
+ },
+
+ /* 136 0x88 '�' */
+ {
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 137 0x89 '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 138 0x8a '�' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 139 0x8b '�' */
+ {
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 140 0x8c '�' */
+ {
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 141 0x8d '?' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 142 0x8e '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 143 0x8f '?' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 144 0x90 '?' */
+ {
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xf8, /* 11111000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 145 0x91 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 146 0x92 '�' */
+ {
+ 0x3e, /* 00111110 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xce, /* 11001110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 147 0x93 '�' */
+ {
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 148 0x94 '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 149 0x95 '�' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 150 0x96 '�' */
+ {
+ 0x78, /* 01111000 */
+ 0x84, /* 10000100 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 151 0x97 '�' */
+ {
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 152 0x98 '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0xfc /* 11111100 */
+ },
+
+ /* 153 0x99 '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 154 0x9a '�' */
+ {
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 155 0x9b '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 156 0x9c '�' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x64, /* 01100100 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x66, /* 01100110 */
+ 0xfc, /* 11111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 157 0x9d '?' */
+ {
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 158 0x9e '�' */
+ {
+ 0xf8, /* 11111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xfa, /* 11111010 */
+ 0xc6, /* 11000110 */
+ 0xcf, /* 11001111 */
+ 0xc6, /* 11000110 */
+ 0xc7 /* 11000111 */
+ },
+
+ /* 159 0x9f '�' */
+ {
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 160 0xa0 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 161 0xa1 '�' */
+ {
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 162 0xa2 '�' */
+ {
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 163 0xa3 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 164 0xa4 '�' */
+ {
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 165 0xa5 '�' */
+ {
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 166 0xa6 '�' */
+ {
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 167 0xa7 '�' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 168 0xa8 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x63, /* 01100011 */
+ 0x3e, /* 00111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 169 0xa9 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 170 0xaa '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 171 0xab '�' */
+ {
+ 0x63, /* 01100011 */
+ 0xe6, /* 11100110 */
+ 0x6c, /* 01101100 */
+ 0x7e, /* 01111110 */
+ 0x33, /* 00110011 */
+ 0x66, /* 01100110 */
+ 0xcc, /* 11001100 */
+ 0x0f /* 00001111 */
+ },
+
+ /* 172 0xac '�' */
+ {
+ 0x63, /* 01100011 */
+ 0xe6, /* 11100110 */
+ 0x6c, /* 01101100 */
+ 0x7a, /* 01111010 */
+ 0x36, /* 00110110 */
+ 0x6a, /* 01101010 */
+ 0xdf, /* 11011111 */
+ 0x06 /* 00000110 */
+ },
+
+ /* 173 0xad '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 174 0xae '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x33, /* 00110011 */
+ 0x66, /* 01100110 */
+ 0xcc, /* 11001100 */
+ 0x66, /* 01100110 */
+ 0x33, /* 00110011 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 175 0xaf '�' */
+ {
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0x66, /* 01100110 */
+ 0x33, /* 00110011 */
+ 0x66, /* 01100110 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 176 0xb0 '�' */
+ {
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88 /* 10001000 */
+ },
+
+ /* 177 0xb1 '�' */
+ {
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa /* 10101010 */
+ },
+
+ /* 178 0xb2 '�' */
+ {
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd /* 11011101 */
+ },
+
+ /* 179 0xb3 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 180 0xb4 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 181 0xb5 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 182 0xb6 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 183 0xb7 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 184 0xb8 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 185 0xb9 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 186 0xba '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 187 0xbb '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 188 0xbc '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 189 0xbd '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 190 0xbe '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 191 0xbf '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 192 0xc0 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 193 0xc1 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 194 0xc2 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 195 0xc3 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 196 0xc4 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 197 0xc5 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 198 0xc6 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 199 0xc7 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 200 0xc8 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 201 0xc9 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 202 0xca '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 203 0xcb '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 204 0xcc '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 205 0xcd '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 206 0xce '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 207 0xcf '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 208 0xd0 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 209 0xd1 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 210 0xd2 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 211 0xd3 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 212 0xd4 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 213 0xd5 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 214 0xd6 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 215 0xd7 '�' */
+ {
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36 /* 00110110 */
+ },
+
+ /* 216 0xd8 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 217 0xd9 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 218 0xda '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 219 0xdb '�' */
+ {
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff /* 11111111 */
+ },
+
+ /* 220 0xdc '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff /* 11111111 */
+ },
+
+ /* 221 0xdd '�' */
+ {
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0 /* 11110000 */
+ },
+
+ /* 222 0xde '�' */
+ {
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f /* 00001111 */
+ },
+
+ /* 223 0xdf '�' */
+ {
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 224 0xe0 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xc8, /* 11001000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 225 0xe1 '�' */
+ {
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 226 0xe2 '�' */
+ {
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 227 0xe3 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 228 0xe4 '�' */
+ {
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 229 0xe5 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 230 0xe6 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0xc0 /* 11000000 */
+ },
+
+ /* 231 0xe7 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 232 0xe8 '�' */
+ {
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e /* 01111110 */
+ },
+
+ /* 233 0xe9 '�' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 234 0xea '�' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xee, /* 11101110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 235 0xeb '�' */
+ {
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x3e, /* 00111110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 236 0xec '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 237 0xed '�' */
+ {
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7e, /* 01111110 */
+ 0x60, /* 01100000 */
+ 0xc0 /* 11000000 */
+ },
+
+ /* 238 0xee '�' */
+ {
+ 0x1e, /* 00011110 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x7e, /* 01111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x1e, /* 00011110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 239 0xef '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 240 0xf0 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 241 0xf1 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 242 0xf2 '�' */
+ {
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 243 0xf3 '�' */
+ {
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 244 0xf4 '�' */
+ {
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18 /* 00011000 */
+ },
+
+ /* 245 0xf5 '�' */
+ {
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70 /* 01110000 */
+ },
+
+ /* 246 0xf6 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 247 0xf7 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 248 0xf8 '�' */
+ {
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 249 0xf9 '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 250 0xfa '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 251 0xfb '�' */
+ {
+ 0x0f, /* 00001111 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xec, /* 11101100 */
+ 0x6c, /* 01101100 */
+ 0x3c, /* 00111100 */
+ 0x1c /* 00011100 */
+ },
+
+ /* 252 0xfc '�' */
+ {
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 253 0xfd '�' */
+ {
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 254 0xfe '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ },
+
+ /* 255 0xff '�' */
+ {
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00 /* 00000000 */
+ }
+};
diff --git a/src/fontface.h b/src/fontface.h
new file mode 100644
index 0000000..a220608
--- /dev/null
+++ b/src/fontface.h
@@ -0,0 +1,12 @@
+
+#ifndef __FONTFACE_H
+#define __FONTFACE_H
+
+#include <SDL.h>
+
+#define FONTHEIGHT 8
+#define FONTWIDTH 8
+
+extern const Uint8 Font_Face[256][FONTHEIGHT];
+
+#endif
diff --git a/src/graphics.c b/src/graphics.c
new file mode 100644
index 0000000..4f14466
--- /dev/null
+++ b/src/graphics.c
@@ -0,0 +1,175 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <SDL.h>
+
+#include "controller.h"
+#include "graphics.h"
+
+#define GENERIC_LOCK(S) { \
+ if (SDL_MUSTLOCK(S) && SDL_LockSurface(S)) \
+ return 1; \
+}
+
+#define GENERIC_UNLOCK(S) { \
+ if (SDL_MUSTLOCK(S)) \
+ SDL_UnlockSurface(S); \
+ return 0; \
+}
+
+#define XYTOPTR(S, X, Y, BPP) ((Uint8*)(S)->pixels + (Y)*(S)->pitch + (X)*(BPP))
+#define SETPIXEL(P, BPP, C) memcpy(P, &(C), BPP)
+#define SAFE_SETPIXEL(P, MAX, BPP, C) { \
+ if (P < MAX) \
+ SETPIXEL(P, BPP, C); \
+}
+
+int
+Graphics_DrawHLine(SDL_Surface *s, Uint16 x, Uint16 y, Uint16 l, Uint32 color)
+{
+ Uint8 bpp = s->format->BytesPerPixel;
+ Uint8 *p = XYTOPTR(s, x, y, bpp);
+
+ GENERIC_LOCK(s);
+
+ while (l--) {
+ SETPIXEL(p, bpp, color);
+ p += bpp;
+ }
+
+ GENERIC_UNLOCK(s);
+}
+
+int
+Graphics_DrawVLine(SDL_Surface *s, Uint16 x, Uint16 y, Uint16 l, Uint32 color)
+{
+ Uint8 bpp = s->format->BytesPerPixel;
+ Uint8 *p = XYTOPTR(s, x, y, bpp);
+
+ GENERIC_LOCK(s);
+
+ while (l--) {
+ SETPIXEL(p, bpp, color);
+ p += s->pitch;
+ }
+
+ GENERIC_UNLOCK(s);
+}
+
+int
+Graphics_DrawRect(SDL_Surface *s, SDL_Rect *rect, Uint32 color)
+{
+ Uint8 bpp = s->format->BytesPerPixel;
+ Uint8 *p = XYTOPTR(s, rect->x + 1, rect->y, bpp);
+
+ Uint32 d;
+
+ GENERIC_LOCK(s);
+
+ if (rect->w > 2) {
+ d = (rect->h - 1)*s->pitch;
+
+ for (Uint16 w = rect->w - 2; w; w--, p += bpp) {
+ SETPIXEL(p, bpp, color);
+ SETPIXEL(p + d, bpp, color);
+ }
+ }
+
+ d = (rect->w - 1)*bpp;
+ for (Uint16 h = rect->h; h; h--, p += s->pitch) {
+ SETPIXEL(p, bpp, color);
+ SETPIXEL(p - d, bpp, color);
+ }
+
+ GENERIC_UNLOCK(s);
+}
+
+int
+Graphics_GradFillRect(SDL_Surface *s, SDL_Rect *rect, Uint16 max,
+ SDL_Color *top, SDL_Color *bottom, SDL_Color *last)
+{
+ Uint8 bpp = s->format->BytesPerPixel;
+ Uint8 *p = XYTOPTR(s, rect->x, rect->y + rect->h, bpp);
+
+ float cr = bottom->r, cg = bottom->g, cb = bottom->b;
+ float diff_r = (float)(top->r - cr)/max;
+ float diff_g = (float)(top->g - cg)/max;
+ float diff_b = (float)(top->b - cb)/max;
+
+ Sint8 p_diff = bpp;
+
+ GENERIC_LOCK(s);
+
+ for (Uint16 h = rect->h; h; h--) {
+ Uint32 color = SDL_MapRGB(s->format, cr, cg, cb);
+
+ for (Uint16 w = rect->w; w; w--, p += p_diff)
+ SETPIXEL(p, bpp, color);
+
+ cr += diff_r;
+ cg += diff_g;
+ cb += diff_b;
+
+ p -= s->pitch + p_diff;
+ p_diff = -p_diff;
+ }
+
+ if (last) {
+ last->r = cr;
+ last->g = cg;
+ last->b = cb;
+ }
+
+ GENERIC_UNLOCK(s);
+}
+
+int
+Graphics_WriteText(SDL_Surface *s, Uint16 x, Uint16 y, const char *text,
+ Uint32 color)
+{
+ Uint8 bpp = s->format->BytesPerPixel;
+ Uint8 *p = XYTOPTR(s, x + FONTWIDTH, y, bpp);
+ Uint8 *max = XYTOPTR(s, 0, s->h, 0);
+
+ GENERIC_LOCK(s);
+
+ for (const char *c = text; *c; c++, p += bpp*FONTWIDTH) {
+ const Uint8 *line = Font_Face[*c];
+ Uint8 *py = p;
+
+ for (Uint8 yc = FONTHEIGHT; yc; yc--, line++, py += s->pitch) {
+ Uint8 col = *line;
+ Uint8 *px = py;
+
+ for (Uint8 xc = FONTWIDTH; xc; xc--, col >>= 1, px -= bpp)
+ if (col & 1)
+ SAFE_SETPIXEL(px, max, bpp, color);
+ }
+ }
+
+ GENERIC_UNLOCK(s);
+}
+
+int
+Graphics_printf(SDL_Surface *s, Uint16 x, Uint16 y, Uint32 color,
+ const char *format, ...)
+{
+ char buffer[1024];
+ va_list args;
+
+ int ret;
+
+ va_start(args, format);
+ ret = vsnprintf(buffer, sizeof(buffer), format, args);
+ va_end(args);
+
+ return ret != -1 && ret < sizeof(buffer) &&
+ !Graphics_WriteText(s, x, y, buffer, color) ? ret : -1;
+}
+
diff --git a/src/graphics.h b/src/graphics.h
new file mode 100644
index 0000000..b40b3ce
--- /dev/null
+++ b/src/graphics.h
@@ -0,0 +1,37 @@
+
+#ifndef __GRAPHICS_H
+#define __GRAPHICS_H
+
+#include <SDL.h>
+
+#include "controller.h"
+#include "fontface.h"
+ /* ^ defines FONTWIDTH/FONTHEIGHT */
+
+int Graphics_DrawHLine(SDL_Surface *s, Uint16 x, Uint16 y, Uint16 l, Uint32 color);
+int Graphics_DrawVLine(SDL_Surface *s, Uint16 x, Uint16 y, Uint16 l, Uint32 color);
+int Graphics_DrawRect(SDL_Surface *s, SDL_Rect *rect, Uint32 color);
+int Graphics_GradFillRect(SDL_Surface *s, SDL_Rect *rect, Uint16 max,
+ SDL_Color *top, SDL_Color *bottom, SDL_Color *last);
+int Graphics_WriteText(SDL_Surface *s, Uint16 x, Uint16 y, const char *text,
+ Uint32 color);
+int Graphics_printf(SDL_Surface *s, Uint16 x, Uint16 y, Uint32 color,
+ const char *format, ...);
+
+
+static inline int Graphics_BlankRect(SDL_Surface *s, SDL_Rect *rect);
+static inline int Graphics_FillRect(SDL_Surface *s, SDL_Rect *rect, Uint32 color);
+
+static inline int
+Graphics_BlankRect(SDL_Surface *s, SDL_Rect *rect)
+{
+ return SDL_FillRect(s, rect, display.background);
+}
+
+static inline int
+Graphics_FillRect(SDL_Surface *s, SDL_Rect *rect, Uint32 color)
+{
+ return SDL_FillRect(s, rect, color);
+}
+
+#endif
diff --git a/src/osc.c b/src/osc.c
new file mode 100644
index 0000000..c0c576b
--- /dev/null
+++ b/src/osc.c
@@ -0,0 +1,312 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __WATCOMC__
+# include <types.h>
+# include <tcpustd.h>
+#else
+# include <sys/select.h>
+#endif
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#include <SDL.h>
+#include <SDL_thread.h>
+
+#include "controller.h"
+#include "OSC-client.h"
+#include "osc.h"
+
+#define FOREACH_QUEUE(VAR) \
+ for (struct Osc_QueueElement *VAR = Osc_QueueHead.next; VAR; VAR = VAR->next)
+
+static struct Osc_QueueElement {
+ struct Osc_QueueElement *next;
+
+ OSCbuf buffer;
+} Osc_QueueHead = {NULL};
+
+static struct Osc_QueueElement *Osc_QueueTail = &Osc_QueueHead;
+
+static SDL_mutex *Osc_QueueMutex = NULL;
+static SDL_sem *Osc_QueueSemaphore = NULL;
+
+static int SDLCALL Osc_DequeueThread(void *ud);
+
+static inline Uint32 Osc_StrPad32(Uint32 l);
+static inline int Osc_BuildFloatMessage(OSCbuf *buf, const char *address,
+ float value);
+
+int
+Osc_Connect(const char *hostname, int port)
+{
+ struct hostent *entry;
+ struct sockaddr_in addr;
+
+ int fd;
+
+ if (!(entry = gethostbyname(hostname)) ||
+ (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return -1;
+
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = *(in_addr_t*)*entry->h_addr_list;
+ addr.sin_port = htons(port);
+
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+SDL_Thread *
+Osc_InitThread(int *fd)
+{
+ SDL_Thread *thread;
+
+ if (!(Osc_QueueMutex = SDL_CreateMutex()))
+ return NULL;
+
+ if (!(Osc_QueueSemaphore = SDL_CreateSemaphore(0))) {
+ SDL_DestroyMutex(Osc_QueueMutex);
+ return NULL;
+ }
+
+ if (!(thread = SDL_CreateThread(Osc_DequeueThread, fd))) {
+ SDL_DestroyMutex(Osc_QueueMutex);
+ SDL_DestroySemaphore(Osc_QueueSemaphore);
+ }
+
+ return thread;
+}
+
+/*
+ * terminate thread without killing it by freeing the remaining queue and
+ * increasing the semaphore (gentle termination condition)
+ */
+
+int
+Osc_TerminateThread(void)
+{
+ struct Osc_QueueElement *next;
+
+ if (SDL_LockMutex(Osc_QueueMutex))
+ return -1;
+
+ for (struct Osc_QueueElement *el = Osc_QueueHead.next; el; el = next) {
+ next = el->next;
+
+ free(OSC_getPacket(&el->buffer));
+ free(el);
+ }
+
+ Osc_QueueHead.next = NULL;
+ Osc_QueueTail = &Osc_QueueHead;
+
+ return SDL_UnlockMutex(Osc_QueueMutex) ||
+ SDL_SemPost(Osc_QueueSemaphore);
+}
+
+#define THREAD_ABORT() { \
+ if (SDL_PushEvent((SDL_Event*)&abort)) \
+ return 1; \
+ continue; \
+}
+
+static int SDLCALL
+Osc_DequeueThread(void *ud)
+{
+ int fd = *(int*)ud;
+
+ static const SDL_Event abort = {
+ .type = SDL_USEREVENT,
+ .user = {
+ .type = SDL_USEREVENT,
+ .code = CONTROLLER_ERR_THREAD
+ }
+ };
+
+ for (;;) {
+ struct Osc_QueueElement *el;
+ char *data;
+
+ fd_set wrset;
+ ssize_t r;
+
+ struct timeval timeout = {
+ .tv_sec = 30,
+ .tv_usec = 0
+ };
+
+ if (SDL_SemWait(Osc_QueueSemaphore) ||
+ SDL_LockMutex(Osc_QueueMutex))
+ THREAD_ABORT();
+
+ if (!(el = Osc_QueueHead.next)) { /* gentle thread termination */
+ SDL_DestroyMutex(Osc_QueueMutex);
+ SDL_DestroySemaphore(Osc_QueueSemaphore);
+ Osc_QueueMutex = NULL;
+ Osc_QueueSemaphore = NULL;
+
+ return 0;
+ }
+
+ if (SDL_UnlockMutex(Osc_QueueMutex))
+ THREAD_ABORT();
+
+ FD_ZERO(&wrset);
+ FD_SET(fd, &wrset);
+
+ if (select(fd + 1, NULL, &wrset, NULL, &timeout) <= 0)
+ THREAD_ABORT();
+
+ data = OSC_getPacket(&el->buffer);
+
+ do
+ r = send(fd, data, OSC_packetSize(&el->buffer), 0);
+ while (r < 0 && errno == EINTR);
+
+ if (r <= 0 ||
+ SDL_LockMutex(Osc_QueueMutex))
+ THREAD_ABORT();
+
+ if (!(Osc_QueueHead.next = el->next))
+ Osc_QueueTail = &Osc_QueueHead;
+
+ if (SDL_UnlockMutex(Osc_QueueMutex))
+ THREAD_ABORT();
+
+ free(data);
+ free(el);
+ }
+}
+
+static inline Uint32
+Osc_StrPad32(Uint32 l)
+{
+ Uint32 m = ++l % sizeof(Uint32);
+ return m ? l + sizeof(Uint32) - m : l;
+}
+
+#if 0
+int
+Osc_BuildMessage(OSCbuf *buf, const char *address, const char *types, ...)
+{
+ va_list args;
+
+ Uint32 size = Osc_StrPad32(strlen(address)) + Osc_StrPad32(strlen(types));
+ char *data = NULL;
+
+ va_start(args, types);
+
+ for (const char *p = types + 1; *p; p++)
+ switch (*p) {
+ case 'f':
+ case 'i':
+ va_arg(args, Uint32);
+ size += sizeof(Uint32);
+ break;
+
+ case 's':
+ size += Osc_StrPad32(strlen(va_arg(args, char*)));
+ break;
+
+ default:
+ goto err;
+ }
+
+ va_end(args);
+ va_start(args, types);
+
+ if (!(data = malloc(size)))
+ goto err;
+ OSC_initBuffer(buf, size, data);
+
+ if (OSC_writeAddressAndTypes(buf, (char*)address, (char*)types))
+ goto err;
+
+ for (const char *p = types + 1; *p; p++)
+ switch (*p) {
+ case 'f':
+ if (OSC_writeFloatArg(buf, va_arg(args, float)))
+ goto err;
+ break;
+
+ case 'i':
+ if (OSC_writeIntArg(buf, va_arg(args, int)))
+ goto err;
+ break;
+
+ case 's':
+ if (OSC_writeStringArg(buf, va_arg(args, char*)))
+ goto err;
+ break;
+ }
+
+ va_end(args);
+ return 0;
+
+err:
+
+ va_end(args);
+ free(data);
+ return 1;
+}
+#endif
+
+static inline int
+Osc_BuildFloatMessage(OSCbuf *buf, const char *address, float value)
+{
+ Uint32 size = Osc_StrPad32(strlen(address)) + 4 + sizeof(float);
+ char *data;
+
+ if (!(data = malloc(size)))
+ return 1;
+
+ OSC_initBuffer(buf, size, data);
+
+ if (OSC_writeAddressAndTypes(buf, (char*)address, ",f") ||
+ OSC_writeFloatArg(buf, value)) {
+ free(data);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+Osc_EnqueueFloatMessage(const char *address, float value)
+{
+ struct Osc_QueueElement *el;
+
+ if (SDL_LockMutex(Osc_QueueMutex) ||
+ !(el = malloc(sizeof(struct Osc_QueueElement))))
+ return 1;
+ memset(el, 0, sizeof(struct Osc_QueueElement));
+
+ if (Osc_BuildFloatMessage(&el->buffer, address, value)) {
+ free(el);
+ return 1;
+ }
+
+ Osc_QueueTail->next = el;
+ Osc_QueueTail = el;
+
+ return SDL_UnlockMutex(Osc_QueueMutex) ||
+ SDL_SemPost(Osc_QueueSemaphore);
+}
+
diff --git a/src/osc.h b/src/osc.h
new file mode 100644
index 0000000..f8aa6d9
--- /dev/null
+++ b/src/osc.h
@@ -0,0 +1,61 @@
+
+#ifndef __OSC_H
+#define __OSC_H
+
+#include <unistd.h>
+#ifdef __WATCOMC__
+#include <types.h>
+#endif
+#include <sys/socket.h>
+
+#include <SDL.h>
+#include <SDL_thread.h>
+
+ /* mainly for Open Watcom C */
+
+#ifndef HAVE_IN_ADDR_T
+#define HAVE_IN_ADDR_T
+typedef Uint32 in_addr_t;
+#endif
+
+#if !(defined(SHUT_RD) || defined(SHUT_WR) || defined(SHUT_RDWR))
+enum {
+ SHUT_RD = 0, /* No more receptions. */
+#define SHUT_RD SHUT_RD
+ SHUT_WR, /* No more transmissions. */
+#define SHUT_WR SHUT_WR
+ SHUT_RDWR /* No more receptions or transmissions. */
+#define SHUT_RDWR SHUT_RDWR
+};
+#endif
+
+int Osc_Connect(const char *hostname, int port);
+static inline void Osc_Disconnect(int fd);
+
+SDL_Thread *Osc_InitThread(int *fd);
+int Osc_TerminateThread(void);
+
+int Osc_EnqueueFloatMessage(const char *address, float value);
+
+static inline void
+Osc_Disconnect(int fd)
+{
+ shutdown(fd, SHUT_WR);
+ close(fd);
+}
+
+enum Osc_DataType {
+ OSC_INT = 0,
+ OSC_FLOAT,
+ OSC_DOUBLE,
+ OSC_STRING,
+ OSC_BOOL
+};
+#define OSC_DATATYPE \
+ "int\0" \
+ "float\0" \
+ "double\0" \
+ "string\0" \
+ "bool\0"
+
+#endif
diff --git a/src/xml.c b/src/xml.c
new file mode 100644
index 0000000..997fe7e
--- /dev/null
+++ b/src/xml.c
@@ -0,0 +1,378 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <SDL.h>
+#include <expat.h>
+
+#include "controls.h"
+#include "controller.h"
+#include "xml.h"
+
+#define FOREACH_ATTR(VAR, ATTS) \
+ for (const XML_Char **VAR = ATTS; *VAR; VAR += 2)
+
+static inline int CaseEnumMap(const char *p, const char *value, int s);
+static int DecodeColorAttrib(const XML_Char *str, SDL_Color *color);
+
+static void XMLCALL Interface_CollectCharacterData(void *ud, const XML_Char *s,
+ int len);
+static inline void Interface_PrepareCDBuffer(XML_Parser parser,
+ XML_EndElementHandler handler);
+static void XMLCALL Interface_StartElement(void *ud, const XML_Char *name,
+ const XML_Char **atts);
+static void XMLCALL Interface_EndSlider(void *ud, const XML_Char *name);
+static void XMLCALL Interface_EndSwitch(void *ud, const XML_Char *name);
+
+static XML_Char Interface_CDBuffer[32]; /* character data buffer */
+
+static inline int
+CaseEnumMap(const char *p, const char *value, int s)
+{
+ while (*p) {
+ if (!strcasecmp(p, value))
+ return s;
+
+ p += strlen(p) + 1;
+ s++;
+ }
+
+ return -1;
+}
+
+static int
+DecodeColorAttrib(const XML_Char *str, SDL_Color *color)
+{
+ static const char colors[] = /* red green blue */
+ "black\0" /* 0 0 0 */
+ "blue\0" /* 0 0 255 */
+ "green\0" /* 0 255 0 */
+ "cyan\0" /* 0 255 255 */
+ "red\0" /* 255 0 0 */
+ "magenta\0" /* 255 0 255 */
+ "yellow\0" /* 255 255 0 */
+ "white\0"; /* 255 255 255 */
+ Sint8 c;
+
+ if (*str == '#') { /* hex-encoded RGB color */
+ Uint32 v;
+ char *p;
+
+ if (strlen(++str) != 6)
+ return 1;
+
+ v = strtoul(str, &p, 16);
+ if (*p)
+ return 1;
+
+ color->b = v >> 0 & 0xFF;
+ color->g = v >> 8 & 0xFF;
+ color->r = v >> 16 & 0xFF;
+
+ return 0;
+ }
+
+ /* else: assume color string */
+
+ if ((c = CaseEnumMap(colors, str, 0)) == -1)
+ return 1;
+
+ color->b = ((c >>= 0) & 0x1)*255; /* we're working with single bytes, so it should be */
+ color->g = ((c >>= 1) & 0x1)*255; /* endianess-independent */
+ color->r = ((c >> 1) & 0x1)*255;
+
+ return 0;
+}
+
+/*
+ * TODO: rewrite this - use a pointer to the end of the buffer
+ * maybe rewrite the parser user data stuff (use a structure)
+ */
+
+static void XMLCALL
+Interface_CollectCharacterData(void *ud, const XML_Char *s, int len)
+{
+ if (strlen(Interface_CDBuffer) + len < sizeof(Interface_CDBuffer))
+ strncat(Interface_CDBuffer, s, len);
+ else
+ XML_StopParser(ud, XML_FALSE);
+}
+
+static inline void
+Interface_PrepareCDBuffer(XML_Parser parser, XML_EndElementHandler handler)
+{
+ *Interface_CDBuffer = '\0';
+ XML_SetCharacterDataHandler(parser, Interface_CollectCharacterData);
+ XML_SetElementHandler(parser, NULL, handler);
+}
+
+static void XMLCALL
+Interface_StartElement(void *ud, const XML_Char *name, const XML_Char **atts)
+{
+ XML_Parser parser = (XML_Parser)ud;
+ SDL_Surface *s = XML_GetUserData(parser);
+
+ struct Tab *tab;
+ SDL_Color color;
+
+ if (!strcasecmp(name, "interface")) {
+ FOREACH_ATTR(a, atts)
+ if (!strcasecmp(*a, "foreground")) {
+ if (DecodeColorAttrib(a[1], &color))
+ goto err;
+
+ display.foreground = SDL_MapRGB(s->format, color.r, color.g, color.b);
+ } else if (!strcasecmp(*a, "background")) {
+ if (DecodeColorAttrib(a[1], &color))
+ goto err;
+
+ display.background = SDL_MapRGB(s->format, color.r, color.g, color.b);
+ } else
+ goto err;
+ } else if (!strcasecmp(name, "tab")) {
+ registry.cTabs++;
+ registry.tabs = realloc(registry.tabs,
+ registry.cTabs*sizeof(struct Tab));
+ if (!registry.tabs)
+ goto allocerr;
+
+ tab = registry.tabs + registry.cTabs - 1;
+ memset(tab, 0, sizeof(struct Tab));
+
+ FOREACH_ATTR(a, atts)
+ if (!strcasecmp(*a, "label")) {
+ if (!(tab->label = strdup(a[1])))
+ goto allocerr;
+ } else
+ goto err;
+
+ if (!tab->label)
+ goto err;
+ } else if (!strcasecmp(name, "slider") ||
+ !strcasecmp(name, "button") ||
+ !strcasecmp(name, "switch")) {
+ /* common for all controls */
+
+ struct Control *control;
+
+ if (!registry.tabs)
+ goto err;
+ tab = registry.tabs + registry.cTabs - 1;
+
+ tab->cControls++;
+ tab->controls = realloc(tab->controls,
+ tab->cControls*sizeof(struct Control));
+ if (!tab->controls)
+ goto allocerr;
+
+ control = tab->controls + tab->cControls - 1;
+ memset(control, 0, sizeof(struct Control));
+ /* ^ already sets some default values (0/NULL) */
+
+ FOREACH_ATTR(a, atts)
+ if (!strcasecmp(*a, "geo")) {
+ float x, y, w, h;
+
+ if (sscanf(a[1], "%f %f %f %f",
+ &x, &y, &w, &h) != 4)
+ goto err;
+
+ control->geo.x = x*display.width/100;
+ control->geo.y = y*display.height/100;
+ control->geo.w = w*display.width/100;
+ control->geo.h = h*display.height/100;
+ } else if (!strcasecmp(*a, "OSCAddress")) {
+ /* FIXME: check the OSC address string */
+ if (!(control->OSC.address = strdup(a[1])))
+ goto allocerr;
+ } else if (!strcasecmp(*a, "OSCDataType")) {
+ control->OSC.datatype = CaseEnumMap(OSC_DATATYPE, a[1], OSC_INT);
+ if (control->OSC.datatype == -1)
+ goto err;
+ }
+
+ /* control-specific */
+
+ if (!strcasecmp(name, "slider")) {
+ struct Slider *slider = &control->u.slider;
+ struct Paint *paint = &slider->paint;
+
+ paint->u.plain.color = display.foreground;
+ /* ^ slider color defaults to foreground color */
+
+ FOREACH_ATTR(a, atts)
+ if (!strcasecmp(*a, "type")) {
+ slider->type = CaseEnumMap(SLIDER_TYPE, a[1], SLIDER_BUTTON);
+ if (slider->type == -1)
+ goto err;
+ } else if (!strcasecmp(*a, "color")) {
+ char *p;
+
+ if ((p = strchr(a[1], ' '))) {
+ paint->type = PAINT_GRAD;
+
+ *p++ = '\0';
+ if (DecodeColorAttrib(a[1], &paint->u.grad.top) ||
+ DecodeColorAttrib(p, &paint->u.grad.bottom))
+ goto err;
+ } else {
+ if (DecodeColorAttrib(a[1], &color))
+ goto err;
+ paint->u.plain.color = SDL_MapRGB(s->format, color.r, color.g, color.b);
+ }
+ } else if (!strcasecmp(*a, "min")) {
+ if (sscanf(a[1], "%lf", &slider->min) == EOF)
+ goto err;
+ } else if (!strcasecmp(*a, "max")) {
+ if (sscanf(a[1], "%lf", &slider->max) == EOF)
+ goto err;
+ } else if (!strcasecmp(*a, "step")) {
+ if (sscanf(a[1], "%lf", &slider->step) == EOF)
+ goto err;
+ } else if (!strcasecmp(*a, "label")) {
+ if (!(slider->label = strdup(a[1])))
+ goto allocerr;
+ } else if (!strcasecmp(*a, "showValue"))
+ slider->show_value = strcasecmp(a[1], "false");
+
+ if (slider->min >= slider->max || slider->step < 0)
+ goto err;
+
+ Interface_PrepareCDBuffer(parser, Interface_EndSlider);
+ } else { /* button/switch field */
+ struct Field *field = &control->u.field;
+
+ control->type = FIELD;
+
+ field->color = display.foreground; /* default color */
+
+ FOREACH_ATTR(a, atts)
+ if (!strcasecmp(*a, "color")) {
+ if (DecodeColorAttrib(a[1], &color))
+ goto err;
+ field->color = SDL_MapRGB(s->format, color.r, color.g, color.b);
+ } else if (!strcasecmp(*a, "label")) {
+ if (!(field->label = strdup(a[1])))
+ goto allocerr;
+ }
+
+ /* field->type is FIELD_BUTTON by default */
+
+ if (!strcasecmp(name, "switch")) {
+ field->type = FIELD_SWITCH;
+ Interface_PrepareCDBuffer(parser, Interface_EndSwitch);
+ }
+ }
+ } else
+ goto err;
+
+ return;
+
+err:
+
+ fprintf(stderr, "Error parsing interface file (line %u, column %u)\n",
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser));
+
+allocerr:
+
+ XML_StopParser(parser, XML_FALSE);
+}
+
+static void XMLCALL
+Interface_EndSlider(void *ud, const XML_Char *name)
+{
+ XML_Parser parser = (XML_Parser)ud;
+
+ struct Tab *tab = registry.tabs + registry.cTabs - 1;
+ struct Control *control = tab->controls + tab->cControls - 1;
+ struct Slider *slider = &control->u.slider;
+
+ double val;
+
+ if (strcasecmp(name, "slider")) {
+ XML_StopParser(parser, XML_FALSE);
+ return;
+ }
+
+ if (*Interface_CDBuffer) {
+ if(sscanf(Interface_CDBuffer, "%lf", &val) == EOF ||
+ val < slider->min || val > slider->max) {
+ XML_StopParser(parser, XML_FALSE);
+ return;
+ }
+ } else
+ val = slider->min;
+
+ Controls_SetSliderValue(slider, val);
+
+ if (slider->type == SLIDER_BUTTON)
+ Controls_InitSliderButton(control);
+
+ XML_SetCharacterDataHandler(parser, NULL);
+ XML_SetElementHandler(parser, Interface_StartElement, NULL);
+}
+
+static void XMLCALL
+Interface_EndSwitch(void *ud, const XML_Char *name)
+{
+ XML_Parser parser = (XML_Parser)ud;
+
+ struct Tab *tab = registry.tabs + registry.cTabs - 1;
+ struct Control *control = tab->controls + tab->cControls - 1;
+
+ if (strcasecmp(name, "switch")) {
+ XML_StopParser(parser, XML_FALSE);
+ return;
+ }
+
+ if (*Interface_CDBuffer)
+ control->u.field.value = !strcasecmp(Interface_CDBuffer, "true");
+
+ XML_SetCharacterDataHandler(parser, NULL);
+ XML_SetElementHandler(parser, Interface_StartElement, NULL);
+}
+
+int
+Xml_ReadInterface(const char *file, SDL_Surface *surface)
+{
+ FILE *f;
+ XML_Parser parser;
+
+ Uint8 buf[1024];
+ size_t len;
+
+ if (!(f = fopen(file, "r")))
+ return 1;
+
+ if (!(parser = XML_ParserCreate(NULL))) {
+ fclose(f);
+ return 1;
+ }
+
+ XML_UseParserAsHandlerArg(parser);
+ XML_SetUserData(parser, surface);
+ XML_SetStartElementHandler(parser, Interface_StartElement);
+
+ do {
+ len = fread(buf, 1, sizeof(buf), f);
+
+ if ((ferror(f) && errno != EINTR) ||
+ XML_Parse(parser, buf, len, feof(f)) == XML_STATUS_ERROR) {
+ XML_ParserFree(parser);
+ fclose(f);
+ return 1;
+ }
+ } while (!feof(f));
+
+ XML_ParserFree(parser);
+ fclose(f);
+ return !registry.tabs;
+}
+
diff --git a/src/xml.h b/src/xml.h
new file mode 100644
index 0000000..4717172
--- /dev/null
+++ b/src/xml.h
@@ -0,0 +1,9 @@
+
+#ifndef __XML_H
+#define __XML_H
+
+#include <SDL.h>
+
+int Xml_ReadInterface(const char *file, SDL_Surface *surface);
+
+#endif