--- /dev/null
+.SUFFIXES: .c .rel
+
+CC = fcc -m$(USERCPU) $(Z80_PLATFORM)
+COPT = $(FUZIX_CCOPTS)
+
+SRCS = io_base.c keyboard_base.c plato.c protocol.c screen_base.c terminal.c \
+ touch_base.c
+
+FSRCS = font.c io.c keyboard.c scale.c screen.c splash.c \
+ terminal_char_load.c touch.c
+
+INC = io.h keyboard.h plato_key.h protocol.h screen.h terminal.h touch.h
+
+all: plato
+
+OBJS = $(SRCS:.c=.rel)
+FOBJS = $(patsubst fuzix/%.c,%.rel, $(FSRCS))
+
+plato: $(OBJS) $(FOBJS)
+ $(CC) -o plato --nostdio $(OBJS) $(FOBJS)
+
+$(OBJS):.c.rel:
+ $(CC) $(COPT) $(CFLAGS) -c $< -o $@
+
+$(FOBJS):.c.rel:
+ $(CC) $(COPT) $(CFLAGS) -c $< -o $@
+
+
+$(OBJS) : $(INC)
+
+$(FOBJS) : $(INC)
+
+clean:
+ rm -f *.o *.rel *.lst *.sym *.asm *.map *.noi *.lk *.bin *~ plato
+ (cd fuzix; rm -f *.o *.rel *.lst *.sym *.asm *.map *.noi *.lk *.bin *~ )
\ No newline at end of file
--- /dev/null
+Implement
+
+- Fix up our output code to buffer into a 256 byte buffer
+- Keep shovelling every tick
+- Set the tty up and atexit properly
+- Block all the signals we don't want (inc PIPE)
+- Actually look up the address properly
+- Get the splash screen off disk instead
+
+
+It would be nice to squash it to the point we can afford 576 byte I/O buffers
--- /dev/null
+/**
+ * Font definitions for font memories M0 and M1
+ */
+
+#include <stdint.h>
+
+uint8_t FONT_SIZE_X = 4;
+uint8_t FONT_SIZE_Y = 6;
+
+uint8_t font[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* SPACE 0x20 */
+ 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, /* ! 0x21 */
+ 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, /* " 0x22 */
+ 0xA0, 0xE0, 0xA0, 0xE0, 0xA0, 0x00, /* # 0x23 */
+ 0x40, 0xE0, 0xC0, 0x60, 0xE0, 0x40, /* $ 0x24 */
+ 0xA0, 0x20, 0x40, 0x80, 0xA0, 0x00, /* % 0x25 */
+ 0x40, 0xA0, 0x40, 0xA0, 0x60, 0x00, /* & 0x26 */
+ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, /* ' 0x27 */
+ 0x20, 0x40, 0x40, 0x40, 0x20, 0x00, /* ( 0x28 */
+ 0x40, 0x20, 0x20, 0x20, 0x40, 0x00, /* ) 0x29 */
+ 0xa0, 0x40, 0xe0, 0x40, 0xa0, 0x00, /* * 0x2a */
+ 0x00, 0x40, 0xe0, 0x40, 0x00, 0x00, /* + 0x2b */
+ 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, /* , 0x2c */
+ 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, /* - 0x2d */
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* . 0x2e */
+ 0x00, 0x20, 0x60, 0xc0, 0x80, 0x00, /* / 0x2f */
+ 0x60, 0xA0, 0xA0, 0xA0, 0xC0, 0x00, /* 0 0x30 */
+ 0x40, 0xC0, 0x40, 0x40, 0xE0, 0x00, /* 1 0x31 */
+ 0xC0, 0x20, 0x40, 0x80, 0xE0, 0x00, /* 2 0x32 */
+ 0xC0, 0x20, 0x40, 0x20, 0xC0, 0x00, /* 3 0x33 */
+ 0x20, 0xA0, 0xE0, 0x20, 0x20, 0x00, /* 4 0x34 */
+ 0xE0, 0x80, 0xC0, 0x20, 0xC0, 0x00, /* 5 0x35 */
+ 0x40, 0x80, 0xC0, 0xA0, 0x40, 0x00, /* 6 0x36 */
+ 0xE0, 0x20, 0x20, 0x40, 0x40, 0x00, /* 7 0x37 */
+ 0x40, 0xA0, 0x40, 0xA0, 0x40, 0x00, /* 8 0x38 */
+ 0x40, 0xA0, 0x60, 0x20, 0x40, 0x00, /* 9 0x39 */
+ 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, /* : 0x3A */
+ 0x40, 0x00, 0x00, 0x40, 0x80, 0x00, /* ; 0x3B */
+ 0x20, 0x40, 0x80, 0x40, 0x20, 0x00, /* < 0x3C */
+ 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, /* = 0x3D */
+ 0x80, 0x40, 0x20, 0x40, 0x80, 0x00, /* < 0x3E */
+ 0xC0, 0x20, 0x40, 0x00, 0x40, 0x00, /* ? 0x3F */
+ 0x40, 0xA0, 0xA0, 0xA0, 0x80, 0x60, /* @ 0x40 */
+ 0x40, 0xA0, 0xE0, 0xA0, 0xA0, 0x00, /* A 0x41 */
+ 0xC0, 0xA0, 0xC0, 0xA0, 0xC0, 0x00, /* B 0x42 */
+ 0x60, 0x80, 0x80, 0x80, 0x60, 0x00, /* C 0x43 */
+ 0xC0, 0xA0, 0xA0, 0xA0, 0xC0, 0x00, /* D 0x44 */
+ 0xE0, 0x80, 0xC0, 0x80, 0xE0, 0x00, /* E 0x45 */
+ 0xE0, 0x80, 0xC0, 0x80, 0x80, 0x00, /* F 0x46 */
+ 0x60, 0x80, 0xA0, 0xA0, 0x60, 0x00, /* G 0x47 */
+ 0xA0, 0xA0, 0xE0, 0xA0, 0xA0, 0x00, /* H 0x48 */
+ 0xE0, 0x40, 0x40, 0x40, 0xE0, 0x00, /* I 0x49 */
+ 0x20, 0x20, 0x20, 0x20, 0xC0, 0x00, /* J 0x4A */
+ 0xA0, 0xA0, 0xC0, 0xA0, 0xA0, 0x00, /* K 0x4B */
+ 0x80, 0x80, 0x80, 0x80, 0xE0, 0x00, /* L 0x4C */
+ 0xA0, 0xE0, 0xE0, 0xA0, 0xA0, 0x00, /* M 0x4D */
+ 0xC0, 0xA0, 0xA0, 0xA0, 0xA0, 0x00, /* N 0x4E */
+ 0x40, 0xA0, 0XA0, 0xA0, 0x40, 0x00, /* O 0x4F */
+ 0xC0, 0xA0, 0xC0, 0x80, 0x80, 0x00, /* P 0x50 */
+ 0x40, 0xA0, 0xA0, 0xA0, 0x40, 0x20, /* Q 0x51 */
+ 0xC0, 0xA0, 0xC0, 0xA0, 0xA0, 0x00, /* R 0x52 */
+ 0x60, 0x80, 0x40, 0x20, 0xC0, 0x00, /* S 0x53 */
+ 0xE0, 0x40, 0x40, 0x40, 0x40, 0x00, /* T 0x54 */
+ 0xA0, 0xA0, 0xA0, 0xA0, 0x40, 0x00, /* U 0x55 */
+ 0xA0, 0xA0, 0xA0, 0x40, 0x40, 0x00, /* V 0x56 */
+ 0xA0, 0xA0, 0xE0, 0xE0, 0xA0, 0x00, /* W 0x57 */
+ 0xA0, 0xA0, 0x40, 0xA0, 0xA0, 0x00, /* X 0x58 */
+ 0xA0, 0xA0, 0x40, 0x40, 0x40, 0x00, /* Y 0x59 */
+ 0xE0, 0x20, 0x40, 0x80, 0xE0, 0x00, /* Z 0x5A */
+ 0xE0, 0x80, 0x80, 0x80, 0xE0, 0x00, /* [ 0x5B */
+ 0x80, 0xC0, 0x60, 0x20, 0x00, 0x00, /* \ 0x5C */
+ 0xE0, 0x20, 0x20, 0x20, 0xE0, 0x00, /* ] 0x5D */
+ 0x40, 0xA0, 0x00, 0x00, 0x00, 0x00, /* ^ 0x5E */
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, /* _ 0x5F */
+ 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, /* ` 0x60 */
+ 0x00, 0x60, 0xA0, 0xA0, 0x60, 0x00, /* a 0x61 */
+ 0x80, 0xC0, 0xA0, 0xA0, 0xC0, 0x00, /* b 0x62 */
+ 0x00, 0x60, 0x80, 0x80, 0x60, 0x00, /* c 0x63 */
+ 0x20, 0x60, 0xA0, 0xA0, 0x60, 0x00, /* d 0x64 */
+ 0x00, 0x60, 0xA0, 0xC0, 0x60, 0x00, /* e 0x65 */
+ 0x20, 0x40, 0xE0, 0x40, 0x40, 0x00, /* f 0x66 */
+ 0x00, 0x60, 0xA0, 0xA0, 0x60, 0xC0, /* g 0x67 */
+ 0x80, 0xC0, 0xA0, 0xA0, 0xA0, 0x00, /* h 0x68 */
+ 0x40, 0x00, 0xC0, 0x40, 0xE0, 0x00, /* i 0x69 */
+ 0x20, 0x00, 0x60, 0x20, 0x20, 0xC0, /* j 0x6a */
+ 0x80, 0xA0, 0xC0, 0xA0, 0xA0, 0x00, /* k 0x6b */
+ 0xC0, 0x40, 0x40, 0x40, 0xE0, 0x00, /* l 0x6c */
+ 0x00, 0xA0, 0xE0, 0xA0, 0xA0, 0x00, /* m 0x6d */
+ 0x00, 0xC0, 0xA0, 0xA0, 0xA0, 0x00, /* n 0x6e */
+ 0x00, 0x40, 0xA0, 0xA0, 0x40, 0x00, /* o 0x6f */
+ 0x00, 0x60, 0xA0, 0xA0, 0xC0, 0x80, /* p 0x70 */
+ 0x00, 0x60, 0xA0, 0xA0, 0x60, 0x20, /* q 0x71 */
+ 0x00, 0xC0, 0xA0, 0x80, 0x80, 0x00, /* r 0x72 */
+ 0x00, 0x20, 0x40, 0x20, 0xC0, 0x00, /* s 0x73 */
+ 0x40, 0xE0, 0x40, 0x40, 0x20, 0x00, /* t 0x74 */
+ 0x00, 0xA0, 0xA0, 0xA0, 0x60, 0x00, /* u 0x75 */
+ 0x00, 0xA0, 0xA0, 0x40, 0x40, 0x00, /* v 0x76 */
+ 0x00, 0xA0, 0xA0, 0xE0, 0xA0, 0x00, /* w 0x77 */
+ 0x00, 0xA0, 0x40, 0x40, 0xA0, 0x00, /* x 0x78 */
+ 0x00, 0xA0, 0xA0, 0xA0, 0x60, 0xC0, /* y 0x79 */
+ 0x00, 0xE0, 0x40, 0x80, 0xE0, 0x00, /* z 0x7A */
+ 0x60, 0x40, 0x80, 0x80, 0x40, 0x60, /* { 0x7B */
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* | 0x7C */
+ 0xC0, 0x40, 0x20, 0x20, 0x40, 0xC0, /* } 0x7D */
+ 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, /* ~ 0x7E */
+ 0x00, 0xF0, 0x90, 0x90, 0xF0, 0x00, /* BOX 0x7F */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* SPACE 0xA0 */
+ 0x00, 0x10, 0x20, 0x40, 0x80, 0x00, /* / 0xA1 */
+ 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, /* EQUIV 0xA2 */
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, /* LOW TILDE 0xA3 */
+ 0x20, 0x70, 0x80, 0x70, 0x20, 0x00, /* ASSIGN 0xA4 */
+ 0x20, 0xE0, 0x40, 0xE0, 0x80, 0x00, /* nEqual 0xA5 */
+ 0x40, 0xE0, 0x40, 0x40, 0x00, 0x00, /* up arrow 0xA6 */
+ 0x00, 0x20, 0xF0, 0x20, 0x00, 0x00, /* rt arrow 0xA7 */
+ 0x40, 0x40, 0xE0, 0x40, 0x00, 0x00, /* dn arrow 0xA8 */
+ 0x00, 0x40, 0xF0, 0x40, 0x00, 0x00, /* lf arrow 0xA9 */
+ 0x00, 0xA0, 0x40, 0xA0, 0x00, 0x00, /* multiply 0xAA */
+ 0xF0, 0x80, 0x60, 0x80, 0xF0, 0x00, /* sigma 0xAB */
+ 0x00, 0x00, 0x40, 0xA0, 0xE0, 0x00, /* delta 0xAC */
+ 0x00, 0x90, 0x90, 0x60, 0x00, 0x00, /* union 0xAD */
+ 0x00, 0x60, 0x90, 0x90, 0x00, 0x00, /* intrsect 0xAE */
+ 0x40, 0x00, 0xE0, 0x00, 0x40, 0x00, /* divide 0xAF */
+ 0x00, 0x50, 0xA0, 0x70, 0x00, 0x00, /* alpha 0xB0 */
+ 0x20, 0x50, 0xA0, 0x90, 0xE0, 0x80, /* beta 0xB1 */
+ 0x40, 0x80, 0x40, 0xA0, 0xE0, 0x00, /* delta 0xB2 */
+ 0x80, 0x40, 0x20, 0x50, 0x90, 0x00, /* lambda 0xB3 */
+ 0x00, 0x00, 0x50, 0x50, 0x60, 0x80, /* mu 0xB4 */
+ 0x00, 0x00, 0xF0, 0x60, 0x60, 0x00, /* pi 0xB5 */
+ 0x00, 0x20, 0x50, 0x50, 0xA0, 0x80, /* rho 0xB6 */
+ 0x00, 0x00, 0xE0, 0xA0, 0x40, 0x00, /* sigma 0xB7 */
+ 0x00, 0x00, 0x90, 0xB0, 0x60, 0x00, /* omega 0xB8 */
+ 0x20, 0x40, 0x80, 0x40, 0x20, 0x70, /* lt ||= 0xB9 */
+ 0x80, 0x40, 0x20, 0x40, 0x80, 0xE0, /* gt ||= 0xBA */
+ 0x40, 0xA0, 0xE0, 0xA0, 0x40, 0x00, /* theta 0xBB */
+ 0x30, 0x60, 0xA0, 0x60, 0x30, 0x00, /* l-embed 0xBC */
+ 0x00, 0x60, 0x90, 0x60, 0x00, 0x00, /* degree 0xBD */
+ 0xC0, 0x60, 0x50, 0x60, 0xC0, 0x00, /* r-embed 0xBE */
+ 0xC0, 0xA0, 0x50, 0x50, 0xA0, 0xC0, /* arrow 0xBF */
+ 0xF0, 0x20, 0x40, 0x40, 0x20, 0xF0, /* copyrig 0xC0 */
+ 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, /* diaeresis 0xC1 */
+ 0x00, 0xE0, 0xA0, 0xE0, 0x00, 0x00, /* box 0xC2 */
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, /* interpunct 0xC3 */
+ 0x00, 0x00, 0x60, 0xF0, 0x60, 0x00, /* diamond 0xC4 */
+ 0x00, 0x90, 0x60, 0x60, 0x90, 0x00, /* multiply 0xC5 */
+ 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, /* acute ac 0xC6 */
+ 0x00, 0x00, 0x00, 0x10, 0x20, 0x00, /* cedilla 0xC7 */
+ 0xA0, 0x40, 0xA0, 0x00, 0x00, 0x00, /* hacek 0xC8 */
+ 0x00, 0x00, 0x60, 0xF0, 0x60, 0x00, /* diamond 0xC9 */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* | 0xca */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t fontm23[768];
+
+uint16_t fontptr[] =
+ { 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96,
+102, 108, 114, 120, 126, 132, 138, 144, 150, 156, 162, 168, 174, 180, 186, 192,
+198, 204, 210, 216, 222, 228, 234, 240, 246, 252, 258, 264, 270, 276, 282, 288,
+294, 300, 306, 312, 318, 324, 330, 336, 342, 348, 354, 360, 366, 372, 378, 384,
+390, 396, 402, 408, 414, 420, 426, 432, 438, 444, 450, 456, 462, 468, 474, 480,
+486, 492, 498, 504, 510, 516, 522, 528, 534, 540, 546, 552, 558, 564, 570, 576,
+582, 588, 594, 600, 606, 612, 618, 624, 630, 636, 642, 648, 654, 660, 666, 672,
+678, 684, 690, 696, 702, 708, 714, 720, 726, 732, 738, 744, 750, 756, 762, 768,
+774, 780, 786, 792, 798, 804, 810, 816, 822, 828, 834, 840, 846, 852, 858, 864,
+870, 876, 882, 888, 894, 900, 906, 912, 918, 924, 930, 936, 942, 948, 954 };
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * io.c - Input/output functions (serial/ethernet) (apple2 specific)
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "../io.h"
+#include "../screen.h"
+
+extern int io_fd;
+static char buf[64];
+static char *bufp = buf;
+
+void io_process_queue(void)
+{
+ int len;
+
+ if (buf == bufp)
+ return;
+ len = write(io_fd, buf, bufp-buf);
+ if (len == 0 || (len == -1 && errno == EAGAIN))
+ return;
+ if (len < 0) {
+ perror("write");
+ return;
+ }
+ /* Circular buffers are elegant, ldir is small and faster for 64 bytes */
+ memmove(buf, buf + len, len);
+ bufp -= len;
+}
+
+/**
+ * io_send_byte(b) - Send specified byte out
+ */
+void io_send_byte(uint8_t b)
+{
+ /* We need to do proper buffering/queueing here ! */
+ if (bufp != &buf[64])
+ *bufp++ = b;
+ else
+ screen_beep();
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * keyboard.c - Keyboard functions (apple2)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include "../screen.h"
+#include "../keyboard.h"
+#include "../protocol.h"
+#include "key.h"
+
+static uint8_t ch;
+static uint8_t shift_lock = false;
+static uint8_t is_escape = false;
+extern uint8_t xoff_enabled;
+extern padBool TTY;
+
+/**
+ * keyboard_main - Handle the keyboard presses
+ */
+void keyboard_main(void)
+{
+ uint8_t ch;
+
+ switch (read(0, &ch, 1)) {
+ case 0:
+ return;
+ case -1:
+ if (errno != EAGAIN) {
+ perror("read");
+ exit(1);
+ }
+ return;
+ }
+ if (is_escape == true && ch == 0x1B) // ESC
+ {
+ screen_beep();
+
+ if (shift_lock == true)
+ shift_lock = false;
+ else
+ shift_lock = true;
+
+ is_escape = false;
+ } else if (is_escape == false && ch == 0x1B)
+ is_escape = true;
+ else if (TTY) {
+ keyboard_out_tty(ch);
+ } else if (is_escape == true) {
+ keyboard_out(esc_key_to_pkey[ch]);
+ is_escape = false;
+ } else if (shift_lock == true) {
+ keyboard_out(shiftlock_key_to_pkey[ch]);
+ } else {
+ keyboard_out(key_to_pkey[ch]);
+ }
+}
+
+/**
+ * keyboard_clear() - Clear the keyboard buffer
+ */
+void keyboard_clear(void)
+{
+ /* We can do this but do we need to ? */
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * scale.c - Scaling table to scale 512x512 to 256x192 (x+12 for apple2)
+ */
+
+#include <stdint.h>
+
+/* X and Y tables used to scale 512x512 PLATO display to 320x192 */
+/* ! Autogenerated by tools/mk_scale.c */
+
+uint16_t scalex[] = {
+ 12, 13, 13, 14, 14, 15, 15, 16,
+ 16, 17, 17, 18, 18, 19, 19, 20,
+ 20, 21, 21, 22, 22, 23, 23, 24,
+ 24, 25, 25, 26, 26, 27, 27, 28,
+ 28, 29, 29, 30, 30, 31, 31, 32,
+ 32, 33, 33, 34, 34, 35, 35, 36,
+ 36, 37, 37, 38, 38, 39, 39, 40,
+ 40, 41, 41, 42, 42, 43, 43, 44,
+ 44, 45, 45, 46, 46, 47, 47, 48,
+ 48, 49, 49, 50, 50, 51, 51, 52,
+ 52, 53, 53, 54, 54, 55, 55, 56,
+ 56, 57, 57, 58, 58, 59, 59, 60,
+ 60, 61, 61, 62, 62, 63, 63, 64,
+ 64, 65, 65, 66, 66, 67, 67, 68,
+ 68, 69, 69, 70, 70, 71, 71, 72,
+ 72, 73, 73, 74, 74, 75, 75, 76,
+ 76, 77, 77, 78, 78, 79, 79, 80,
+ 80, 81, 81, 82, 82, 83, 83, 84,
+ 84, 85, 85, 86, 86, 87, 87, 88,
+ 88, 89, 89, 90, 90, 91, 91, 92,
+ 92, 93, 93, 94, 94, 95, 95, 96,
+ 96, 97, 97, 98, 98, 99, 99, 100,
+ 100, 101, 101, 102, 102, 103, 103, 104,
+ 104, 105, 105, 106, 106, 107, 107, 108,
+ 108, 109, 109, 110, 110, 111, 111, 112,
+ 112, 113, 113, 114, 114, 115, 115, 116,
+ 116, 117, 117, 118, 118, 119, 119, 120,
+ 120, 121, 121, 122, 122, 123, 123, 124,
+ 124, 125, 125, 126, 126, 127, 127, 128,
+ 128, 129, 129, 130, 130, 131, 131, 132,
+ 132, 133, 133, 134, 134, 135, 135, 136,
+ 136, 137, 137, 138, 138, 139, 139, 140,
+ 140, 140, 141, 141, 142, 142, 143, 143,
+ 144, 144, 145, 145, 146, 146, 147, 147,
+ 148, 148, 149, 149, 150, 150, 151, 151,
+ 152, 152, 153, 153, 154, 154, 155, 155,
+ 156, 156, 157, 157, 158, 158, 159, 159,
+ 160, 160, 161, 161, 162, 162, 163, 163,
+ 164, 164, 165, 165, 166, 166, 167, 167,
+ 168, 168, 169, 169, 170, 170, 171, 171,
+ 172, 172, 173, 173, 174, 174, 175, 175,
+ 176, 176, 177, 177, 178, 178, 179, 179,
+ 180, 180, 181, 181, 182, 182, 183, 183,
+ 184, 184, 185, 185, 186, 186, 187, 187,
+ 188, 188, 189, 189, 190, 190, 191, 191,
+ 192, 192, 193, 193, 194, 194, 195, 195,
+ 196, 196, 197, 197, 198, 198, 199, 199,
+ 200, 200, 201, 201, 202, 202, 203, 203,
+ 204, 204, 205, 205, 206, 206, 207, 207,
+ 208, 208, 209, 209, 210, 210, 211, 211,
+ 212, 212, 213, 213, 214, 214, 215, 215,
+ 216, 216, 217, 217, 218, 218, 219, 219,
+ 220, 220, 221, 221, 222, 222, 223, 223,
+ 224, 224, 225, 225, 226, 226, 227, 227,
+ 228, 228, 229, 229, 230, 230, 231, 231,
+ 232, 232, 233, 233, 234, 234, 235, 235,
+ 236, 236, 237, 237, 238, 238, 239, 239,
+ 240, 240, 241, 241, 242, 242, 243, 243,
+ 244, 244, 245, 245, 246, 246, 247, 247,
+ 248, 248, 249, 249, 250, 250, 251, 251,
+ 252, 252, 253, 253, 254, 254, 255, 255,
+ 256, 256, 257, 257, 258, 258, 259, 259,
+ 260, 260, 261, 261, 262, 262, 263, 263,
+ 264, 264, 265, 265, 266, 266, 267, 267,
+};
+
+uint16_t scaley[] = {
+ 191, 191, 190, 190, 190, 189, 189, 189,
+ 188, 188, 187, 187, 187, 186, 186, 186,
+ 185, 185, 184, 184, 184, 183, 183, 183,
+ 182, 182, 181, 181, 181, 180, 180, 180,
+ 179, 179, 178, 178, 178, 177, 177, 177,
+ 176, 176, 175, 175, 175, 174, 174, 174,
+ 173, 173, 172, 172, 172, 171, 171, 171,
+ 170, 170, 169, 169, 169, 168, 168, 168,
+ 167, 167, 167, 166, 166, 165, 165, 165,
+ 164, 164, 164, 163, 163, 162, 162, 162,
+ 161, 161, 161, 160, 160, 159, 159, 159,
+ 158, 158, 158, 157, 157, 156, 156, 156,
+ 155, 155, 155, 154, 154, 153, 153, 153,
+ 152, 152, 152, 151, 151, 150, 150, 150,
+ 149, 149, 149, 148, 148, 147, 147, 147,
+ 146, 146, 146, 145, 145, 144, 144, 144,
+ 143, 143, 143, 142, 142, 142, 141, 141,
+ 140, 140, 140, 139, 139, 139, 138, 138,
+ 137, 137, 137, 136, 136, 136, 135, 135,
+ 134, 134, 134, 133, 133, 133, 132, 132,
+ 131, 131, 131, 130, 130, 130, 129, 129,
+ 128, 128, 128, 127, 127, 127, 126, 126,
+ 125, 125, 125, 124, 124, 124, 123, 123,
+ 122, 122, 122, 121, 121, 121, 120, 120,
+ 120, 119, 119, 118, 118, 118, 117, 117,
+ 117, 116, 116, 115, 115, 115, 114, 114,
+ 114, 113, 113, 112, 112, 112, 111, 111,
+ 111, 110, 110, 109, 109, 109, 108, 108,
+ 108, 107, 107, 106, 106, 106, 105, 105,
+ 105, 104, 104, 103, 103, 103, 102, 102,
+ 102, 101, 101, 100, 100, 100, 99, 99,
+ 99, 98, 98, 97, 97, 97, 96, 96,
+ 96, 95, 95, 95, 94, 94, 93, 93,
+ 93, 92, 92, 92, 91, 91, 90, 90,
+ 90, 89, 89, 89, 88, 88, 87, 87,
+ 87, 86, 86, 86, 85, 85, 84, 84,
+ 84, 83, 83, 83, 82, 82, 81, 81,
+ 81, 80, 80, 80, 79, 79, 78, 78,
+ 78, 77, 77, 77, 76, 76, 75, 75,
+ 75, 74, 74, 74, 73, 73, 72, 72,
+ 72, 71, 71, 71, 70, 70, 70, 69,
+ 69, 68, 68, 68, 67, 67, 67, 66,
+ 66, 65, 65, 65, 64, 64, 64, 63,
+ 63, 62, 62, 62, 61, 61, 61, 60,
+ 60, 59, 59, 59, 58, 58, 58, 57,
+ 57, 56, 56, 56, 55, 55, 55, 54,
+ 54, 53, 53, 53, 52, 52, 52, 51,
+ 51, 50, 50, 50, 49, 49, 49, 48,
+ 48, 48, 47, 47, 46, 46, 46, 45,
+ 45, 45, 44, 44, 43, 43, 43, 42,
+ 42, 42, 41, 41, 40, 40, 40, 39,
+ 39, 39, 38, 38, 37, 37, 37, 36,
+ 36, 36, 35, 35, 34, 34, 34, 33,
+ 33, 33, 32, 32, 31, 31, 31, 30,
+ 30, 30, 29, 29, 28, 28, 28, 27,
+ 27, 27, 26, 26, 25, 25, 25, 24,
+ 24, 24, 23, 23, 23, 22, 22, 21,
+ 21, 21, 20, 20, 20, 19, 19, 18,
+ 18, 18, 17, 17, 17, 16, 16, 15,
+ 15, 15, 14, 14, 14, 13, 13, 12,
+ 12, 12, 11, 11, 11, 10, 10, 9,
+ 9, 9, 8, 8, 8, 7, 7, 6,
+ 6, 6, 5, 5, 5, 4, 4, 3,
+ 3, 3, 2, 2, 2, 1, 1, 0,
+};
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * screen.c - Display output functions
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+
+static uint8_t bp = 0;
+static uint8_t bd = 0;
+
+/**
+ * screen_load_driver()
+ * Load the TGI driver
+ */
+void screen_load_driver(void)
+{
+}
+
+/**
+ * screen_init_hook()
+ * Called after tgi_init to set any special features, e.g. nmi trampolines.
+ */
+void screen_init_hook(void)
+{
+}
+
+/**
+ * Set the terminal colors
+ */
+void screen_update_colors(void)
+{
+}
+
+/**
+ * Wait(void) - Sleep for approx 16.67ms
+ */
+void screen_wait(void)
+{
+ // TODO: 60hz wait
+}
+
+/**
+ * screen_beep(void) - Beep the terminal
+ */
+void screen_beep(void)
+{
+ char c = '\007';
+ write(1, &c, 1);
+}
--- /dev/null
+#include "../protocol.h"
+padByte splash[] = {
+ 0x1B, 0x02, 0x1B, 0x0C, 0x1B, 0x12, 0x1B, 0xD1, 0xC0, 0x50, 0xC0,
+ 0x1B, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xE2, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0x1B, 0x0C, 0x1B, 0x12, 0x1D, 0xAF, 0xF0, 0xC0,
+ 0x1B, 0x5A, 0x1B, 0xD1, 0xC0, 0x44, 0x41, 0x1B, 0xD1, 0xC0,
+ 0x50, 0xC0, 0x1B, 0x0C, 0x1B, 0x12, 0x1B, 0xD1, 0xC0, 0x50,
+ 0xC0, 0x1B, 0x5A, 0x1B, 0x50, 0x00, 0x41, 0xC0, 0x1B, 0xD1,
+ 0xC0, 0x50, 0xC0, 0x1D, 0x2E, 0xF0, 0x22, 0x48, 0x1B, 0x5A,
+ 0x1D, 0x2D, 0xF3, 0x21, 0xD4, 0xAF, 0xED, 0xD4, 0xF0, 0x55,
+ 0x72, 0xD7, 0x74, 0xD8, 0xF5, 0x5A, 0xDE, 0xF5, 0x22, 0x4B,
+ 0x50, 0xF3, 0xD2, 0x71, 0x55, 0x6F, 0xD7, 0xED, 0xD8, 0xEB,
+ 0x5A, 0xE8, 0xDB, 0xE4, 0x5C, 0x2E, 0xFF, 0x5C, 0xFA, 0xDB,
+ 0x78, 0x59, 0xF6, 0xD8, 0x74, 0x55, 0x72, 0x53, 0x71, 0x50,
+ 0x6F, 0x4B, 0xEE, 0xC3, 0x42, 0x2D, 0xF3, 0x42, 0xF3, 0x21,
+ 0xD4, 0x1D, 0x2E, 0xFA, 0x22, 0x42, 0xAF, 0xE8, 0x42, 0x48,
+ 0xCA, 0x4B, 0xE7, 0x4B, 0x66, 0xCC, 0xE4, 0x4D, 0xE2, 0x4E,
+ 0x2E, 0xFF, 0x4D, 0x7D, 0x4B, 0x7B, 0xC9, 0xFA, 0x48, 0x42,
+ 0x1D, 0x2D, 0xFA, 0xA3, 0xC0, 0xAF, 0xF5, 0xC0, 0x4E, 0x2E,
+ 0x60, 0x4E, 0x60, 0x24, 0x41, 0x2D, 0xF3, 0x41, 0xF3, 0xA3,
+ 0x47, 0xC5, 0xF5, 0xC3, 0x77, 0xC0, 0xFA, 0xC0, 0x1D, 0xF3,
+ 0x24, 0xC0, 0xAF, 0xF0, 0xD2, 0x72, 0x53, 0xF3, 0xD4, 0xF5,
+ 0x55, 0x56, 0xF6, 0xD8, 0x77, 0x5A, 0x5C, 0xF6, 0xDE, 0xF5,
+ 0xA5, 0x41, 0xF3, 0x42, 0x71, 0x44, 0x2D, 0xF3, 0x56, 0x48,
+ 0x2E, 0x60, 0xC5, 0x60, 0x24, 0xD2, 0x2D, 0xF3, 0x4E, 0xC0,
+ 0x1D, 0x2E, 0xED, 0x55, 0xAF, 0x69, 0xDB, 0x2E, 0xED, 0xA5,
+ 0x41, 0xED, 0x24, 0x55, 0x1D, 0x2D, 0xF3, 0xA5, 0xDD, 0xAF,
+ 0x69, 0xDD, 0x50, 0xF5, 0x50, 0xF5, 0xA6, 0xD7, 0x69, 0xD7,
+ 0xCA, 0x2D, 0xF3, 0xCA, 0xF3, 0xA5, 0xDD, 0x1D, 0x2E, 0xF0,
+ 0x27, 0xD1, 0x1D, 0x2D, 0xF3, 0xD4, 0x74, 0xCC, 0xF5, 0x48,
+ 0xF6, 0xC5, 0xFA, 0x41, 0xFC, 0xA6, 0x5F, 0x2E, 0x60, 0x5C,
+ 0x63, 0x59, 0x65, 0x59, 0xE8, 0xD7, 0xEE, 0x56, 0x74, 0xD4,
+ 0xF5, 0xD4, 0x78, 0xD4, 0xFC, 0x55, 0xFF, 0x56, 0xAF, 0xE2,
+ 0xD7, 0x65, 0x59, 0xE8, 0xDB, 0xEB, 0xDD, 0x6C, 0xDE, 0xEE,
+ 0x27, 0xC0, 0xF0, 0xC3, 0x72, 0xC5, 0xF3, 0x47, 0xF5, 0x4B,
+ 0xF6, 0xD1, 0x77, 0xD7, 0xD8, 0xF6, 0xDD, 0xF5, 0x28, 0x41,
+ 0x74, 0xC6, 0x72, 0x48, 0x71, 0xCA, 0x6F, 0xCC, 0xED, 0x4E,
+ 0xEB, 0xD1, 0xE7, 0x53, 0x63, 0x55, 0x2E, 0xFF, 0xD7, 0xFA,
+ 0xD8, 0xF9, 0xD8, 0xF5, 0xD8, 0x72, 0xD8, 0xEE, 0xD8, 0x6A,
+ 0xD7, 0xE7, 0x55, 0xE4, 0xD4, 0x60, 0xD1, 0x2D, 0x7D, 0xCF,
+ 0xFA, 0xCC, 0x78, 0xCA, 0xF6, 0xC6, 0x74, 0xC3, 0xF3, 0x27,
+ 0x5F, 0xD4, 0x1D, 0xAF, 0xE8, 0xD4, 0xD7, 0xDB, 0xE7, 0xDE,
+ 0xE4, 0x28, 0x42, 0xE2, 0x44, 0x2E, 0xFF, 0x47, 0xFC, 0x48,
+ 0xF9, 0xC9, 0xF6, 0xCA, 0xF3, 0xCA, 0xEE, 0xC9, 0xEB, 0x47,
+ 0x69, 0xC6, 0xE7, 0x44, 0x65, 0x42, 0xE4, 0x41, 0xE2, 0x27,
+ 0xDD, 0xE1, 0x5A, 0x60, 0xD7, 0xD4, 0xE1, 0xD1, 0x63, 0x4D,
+ 0xE4, 0x4B, 0x66, 0xC9, 0xE8, 0x47, 0x6A, 0xC5, 0x6C, 0x44,
+ 0xEE, 0xC3, 0x71, 0xC3, 0x74, 0xC3, 0x77, 0xC3, 0xFC, 0x44,
+ 0xFF, 0xC6, 0xAF, 0xE1, 0x48, 0x63, 0xCA, 0xE4, 0x4B, 0x65,
+ 0xCC, 0x66, 0x4D, 0xE7, 0x4E, 0xE8, 0xD1, 0xD4, 0x1D, 0x2D,
+ 0xF3, 0xA9, 0x44, 0xAF, 0x69, 0x44, 0x69, 0x28, 0xD7, 0xF5,
+ 0xD7, 0xF5, 0xA9, 0xDE, 0x69, 0xDE, 0xD1, 0x2D, 0xF3, 0xD1,
+ 0x44, 0x1D, 0x2E, 0x60, 0xAA, 0xC3, 0xAF, 0xED, 0xC3, 0x6F,
+ 0x44, 0x72, 0xC5, 0xF3, 0xC6, 0x74, 0xC6, 0xF5, 0x47, 0xC9,
+ 0xF6, 0x4B, 0xF6, 0x2B, 0x44, 0xE8, 0x44, 0xE8, 0xAA, 0x50,
+ 0x2E, 0x7D, 0x50, 0x7D, 0x2B, 0xC3, 0x71, 0xC3, 0x71, 0xAA,
+ 0x50, 0xE1, 0x50, 0xE1, 0x2B, 0x44, 0x2D, 0xF3, 0x44, 0xF3,
+ 0xAA, 0xCC, 0x74, 0xC9, 0xF5, 0x48, 0xF6, 0x47, 0x77, 0xC6,
+ 0xF9, 0x44, 0xFA, 0xC3, 0x2E, 0x60, 0xC3, 0x1D, 0x2D, 0xF3,
+ 0x2B, 0xC6, 0xAF, 0xED, 0xC6, 0xF0, 0x47, 0x72, 0x48, 0xC9,
+ 0xF3, 0xCA, 0x74, 0xCA, 0xF5, 0x4B, 0x4D, 0xDD, 0x5F, 0xF5,
+ 0xAC, 0x42, 0x74, 0x44, 0xF3, 0xC6, 0x72, 0x47, 0x71, 0xC9,
+ 0xF0, 0xCA, 0xEE, 0x4B, 0xCC, 0xED, 0x4D, 0xEB, 0x4E, 0x6A,
+ 0x4E, 0xE8, 0xCF, 0x66, 0x50, 0xE4, 0x50, 0x63, 0x50, 0xE1,
+ 0x50, 0x2E, 0x7E, 0xCF, 0x7B, 0x4E, 0xFA, 0x4E, 0x78, 0x4D,
+ 0x77, 0x4B, 0xF5, 0xCA, 0x74, 0x47, 0xF3, 0xC5, 0x72, 0x44,
+ 0x71, 0xC3, 0x2D, 0xF3, 0xD4, 0x44, 0x2E, 0xF0, 0x2B, 0x56,
+ 0x71, 0x55, 0x74, 0x55, 0x77, 0x56, 0x78, 0xD7, 0xF9, 0x59,
+ 0xFA, 0x5A, 0xDB, 0x7B, 0xDD, 0x7D, 0x5F, 0x7E, 0xAC, 0xC0,
+ 0xAF, 0x60, 0x41, 0xE4, 0x41, 0x66, 0xC0, 0xE8, 0x2B, 0xDE,
+ 0x69, 0xDD, 0xD4, 0x2D, 0xF3, 0xD4, 0xC6, 0x1D, 0xF3, 0xAC,
+ 0x53, 0xAF, 0xF0, 0x53, 0xF3, 0xD4, 0xF5, 0x56, 0xD8, 0xF6,
+ 0x5A, 0x5C, 0xF5, 0x2D, 0xC0, 0x42, 0xF3, 0x44, 0x72, 0xC5,
+ 0xF0, 0xC5, 0x2E, 0x65, 0xD2, 0xAF, 0xF0, 0x5C, 0x72, 0xDD,
+ 0x74, 0x5F, 0xF5, 0x5F, 0xF5, 0x2E, 0xC0, 0xF6, 0x42, 0x77,
+ 0x44, 0x47, 0xF6, 0xCA, 0xF5, 0xCC, 0xF3, 0x4E, 0xF0, 0x50,
+ 0xEE, 0x50, 0x2D, 0xF3, 0x50, 0x44, 0xAF, 0xE2, 0x44, 0x2D,
+ 0xFA, 0x2D, 0x59, 0x77, 0xD8, 0xF5, 0xD7, 0xF3, 0x55, 0xCF,
+ 0xF5, 0x4D, 0xF6, 0xCC, 0x77, 0xCC, 0xFC, 0xCA, 0x2E, 0xE1,
+ 0x48, 0xE7, 0x47, 0x6C, 0xC5, 0xAF, 0xE1, 0xAC, 0xDE, 0x2D,
+ 0xF3, 0xDE, 0x53, 0x1D, 0x2E, 0xF0, 0xAF, 0xC0, 0x1B, 0xD1,
+ 0xC0, 0x50, 0xC0, 0x1D, 0xAC, 0x78, 0x24, 0x5C, 0x1B, 0x5A,
+ 0x9F, 0x1B, 0x12, 0x1B, 0xCC, 0x1B, 0xCF, 0x1B, 0xCA, 0x66,
+ 0x6F, 0x72, 0x1B, 0xCC, 0x1B, 0x4E, 0x1B, 0xCA, 0x1B, 0xD1,
+ 0xC0, 0x50, 0xC0, 0x1D, 0xA3, 0x78, 0x2B, 0xD8, 0x1B, 0x5A,
+ 0x1D, 0xAA, 0xED, 0xA3, 0x56, 0xAC, 0xE8, 0x56, 0xE8, 0x22,
+ 0x47, 0x1D, 0x2B, 0xEB, 0x50, 0x1D, 0xAC, 0xE8, 0x47, 0xE4,
+ 0x21, 0x5F, 0x2B, 0x7E, 0x59, 0x77, 0xD4, 0x6F, 0xD2, 0xE7,
+ 0xD2, 0xAA, 0xFF, 0xD4, 0x78, 0x59, 0x72, 0x5F, 0xEE, 0x22,
+ 0x47, 0x5C, 0x7E, 0x5C, 0x4D, 0x1D, 0x2B, 0xEB, 0x50, 0x1D,
+ 0xAA, 0xFF, 0xCF, 0x2B, 0x60, 0x4B, 0xE2, 0x47, 0x65, 0xC5,
+ 0x69, 0x44, 0xED, 0x44, 0x71, 0xC5, 0x74, 0x47, 0xF6, 0x4B,
+ 0x77, 0xCF, 0x77, 0xA3, 0x44, 0xAA, 0xED, 0x44, 0x56, 0x1D,
+ 0xA9, 0x7D, 0x5F, 0xAC, 0xE8, 0x5F, 0xE8, 0xA5, 0x4E, 0x1D,
+ 0x2B, 0xEB, 0xC6, 0x1D, 0xAC, 0xE8, 0xCF, 0xE4, 0xD7, 0x2B,
+ 0x7E, 0xDD, 0x77, 0xA6, 0x42, 0x6F, 0x44, 0xE7, 0x44, 0xAA,
+ 0xFF, 0x42, 0x78, 0xA5, 0xDD, 0x72, 0xD7, 0xEE, 0xCF, 0xEE,
+ 0x24, 0x59, 0x7E, 0x59, 0x7E, 0xA5, 0xC6, 0x1D, 0x2B, 0xEB,
+ 0xC5, 0x1D, 0xAA, 0xFF, 0xC6, 0x2B, 0x60, 0xCA, 0xE2, 0x4D,
+ 0x65, 0x50, 0x69, 0xD1, 0xED, 0xD1, 0x71, 0x50, 0x74, 0x4D,
+ 0xF6, 0xCA, 0x77, 0xC6, 0x77, 0x24, 0x50, 0xA9, 0x7D, 0x50,
+ 0x7D, 0xA3, 0x5F, 0x1D, 0x7D, 0xA6, 0xCC, 0xAC, 0xE8, 0xCC,
+ 0xE8, 0x27, 0xDB, 0x1D, 0x2B, 0xEB, 0x53, 0x1D, 0xAC, 0xE7,
+ 0xDB, 0xE4, 0x28, 0xC3, 0x2B, 0x7E, 0xC9, 0x77, 0x4E, 0x6F,
+ 0x50, 0xE7, 0x50, 0xAA, 0xFF, 0x4E, 0x78, 0xC9, 0x72, 0xC3,
+ 0x6F, 0x27, 0xDB, 0xC6, 0x7E, 0xC6, 0xD4, 0x1D, 0x2B, 0xEB,
+ 0xD2, 0x1D, 0xAA, 0xFF, 0xD4, 0x2B, 0x60, 0xD8, 0xE2, 0xDB,
+ 0x66, 0xDD, 0x69, 0xDE, 0xED, 0xDE, 0xF0, 0xDD, 0x74, 0xDB,
+ 0xF6, 0xD8, 0x77, 0xD4, 0x77, 0xA6, 0xDE, 0xA9, 0x7D, 0xDE,
+ 0xCC, 0x1D, 0xAA, 0xED, 0x28, 0x59, 0xED, 0xA9, 0xCA, 0xAC,
+ 0xFA, 0xCA, 0xFA, 0x28, 0x59, 0xAA, 0xED, 0x59, 0x1D, 0xED,
+ 0x2B, 0xD7, 0xED, 0xAA, 0xCA, 0x1D, 0x2B, 0xEB, 0xD2, 0x1D,
+ 0xAA, 0xEE, 0xCA, 0x71, 0x42, 0x77, 0xA9, 0xDB, 0x7E, 0x56,
+ 0x2B, 0xE7, 0xD4, 0x6F, 0xD4, 0x78, 0x56, 0xFF, 0xDB, 0xAC,
+ 0x65, 0xAA, 0x42, 0xE8, 0xCA, 0xE8, 0x2B, 0xD7, 0x2B, 0x71,
+ 0xD7, 0x63, 0xCA, 0x63, 0xAA, 0xD4, 0x77, 0x2B, 0x48, 0x77,
+ 0xAA, 0x4E, 0x1D, 0x6A, 0x50, 0x1D, 0xF6, 0x4E, 0xF5, 0xCA,
+ 0xF3, 0x47, 0x6F, 0xC5, 0x6C, 0x44, 0xE8, 0x44, 0x65, 0xC5,
+ 0xE1, 0x47, 0xAA, 0xFF, 0xCA, 0x7E, 0x4E, 0x7E, 0x2B, 0xD7,
+ 0xED, 0xD7, 0x1D, 0xED, 0x2D, 0xC3, 0xED, 0xAC, 0xC3, 0x7D,
+ 0xC3, 0xD1, 0xAC, 0x69, 0xD1, 0x42, 0xF9, 0x42, 0xF9, 0x2D,
+ 0xC3, 0xAA, 0xED, 0xC3, 0x1D, 0xEE, 0x48, 0xAC, 0xF9, 0x48,
+ 0xF9, 0x2E, 0x47, 0x69, 0x47, 0x69, 0x2D, 0xD8, 0xAA, 0x7D,
+ 0xD8, 0x7D, 0x2E, 0x47, 0xED, 0x47, 0xED, 0x2D, 0x48, 0x1D,
+ 0xA9, 0x60, 0xA0, 0xC0, 0x1B, 0x5A, 0x9F, 0x1B, 0x12, 0xC3,
+ 0x6F, 0xF0, 0xF9, 0x72, 0x69, 0xE7, 0xE8, 0x74, 0xA0, 0x28,
+ 0x1B, 0xC3, 0xC0, 0x1B, 0x42, 0xA9, 0xA0, 0xB2, 0x30, 0xB1,
+ 0xB8, 0xA0, 0xC9, 0xD2, 0x41, 0xD4, 0x41, 0x2E, 0xCF, 0x4E,
+ 0xCC, 0xC9, 0x4E, 0xC5, 0x2E, 0xA0, 0xD4, 0xE8, 0x69, 0xF3,
+ 0xA0, 0x74, 0x65, 0x72, 0xED, 0x69, 0xEE, 0xE1, 0x6C, 0xA0,
+ 0x69, 0xF3, 0xA0, 0x72, 0x65, 0x6C, 0x65, 0xE1, 0xF3, 0x65,
+ 0xE4, 0xA0, 0xF5, 0xEE, 0xE4, 0x65, 0x72, 0x8D, 0x74, 0xE8,
+ 0x65, 0xA0, 0x47, 0x4E, 0x55, 0xA0, 0x50, 0xF5, 0xE2, 0x6C,
+ 0x69, 0x63, 0xA0, 0xCC, 0x69, 0x63, 0x65, 0xEE, 0xF3, 0x65,
+ 0x2E, 0xA0, 0xD2, 0xF5, 0xEE, 0xA0, 0x74, 0xE8, 0x65, 0xA0,
+ 0xF0, 0x72, 0x6F, 0xE7, 0x72, 0xE1, 0xED, 0xA0, 0x47, 0x50,
+ 0xCC, 0xAC, 0xA0, 0x66, 0x6F, 0x72, 0xA0, 0xE4, 0x65, 0x74,
+ 0xE1, 0x69, 0x6C, 0xF3, 0x2E, 0x1D, 0x1B, 0x12, 0x28, 0xF0,
+ 0x2E, 0x48, 0x1D, 0xA9, 0x74, 0xA0, 0xC0, 0x74, 0xAF, 0x5F,
+ 0x1D, 0x28, 0x6C, 0xA0, 0xC0, 0x6C, 0xAF, 0x5F, 0x1D, 0x27,
+ 0x60, 0xA0, 0xC0, 0x1B, 0x5A, 0x1B, 0x03
+};
+
+short splash_size = 1388;
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * terminal_char_load.c - Character set loading routine for 4x6 font.
+ */
+
+// TODO: change 5x6 constraints to fit 4x6, pix_thresh, etc.
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "../terminal.h"
+#include "../protocol.h"
+
+// Temporary PLATO character data, 8x16 matrix
+static unsigned char char_data[] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char BTAB[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; // flip one bit on (OR)
+static unsigned char BTAB_5[] = { 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80 }; // flip one bit on for the 5x6 matrix (OR)
+
+static unsigned char TAB_0_5[] =
+ { 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01,
+0x01, 0x01, 0x00, 0x00, 0x00 };
+static unsigned char TAB_0_5i[] =
+ { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04,
+0x04, 0x04, 0x05, 0x05, 0x05 };
+
+static unsigned char TAB_0_4[] = { 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04 }; // return 0..4 given index 0 to 7
+
+static unsigned char PIX_THRESH[] = { 0x03, 0x02, 0x03, 0x03, 0x02, // Pixel threshold table.
+ 0x03, 0x02, 0x03, 0x03, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x03, 0x02, 0x03, 0x03, 0x02,
+ 0x03, 0x02, 0x03, 0x03, 0x02
+};
+
+static unsigned char PIX_WEIGHTS[] = { 0x00, 0x00, 0x00, 0x00, 0x00, // Pixel weights
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char TAB_0_25[] = { 0, 5, 10, 15, 20, 25 }; // Given index 0 of 5, return multiple of 5.
+
+static unsigned char pix_cnt; // total # of pixels
+static unsigned char curr_word; // current word
+static unsigned char u, v; // loop counters
+
+extern unsigned char fontm23[768];
+extern unsigned short fontptr[160];
+
+/**
+ * terminal_char_load - Store a character into the user definable
+ * character set.
+ */
+void terminal_char_load(padWord charnum, charData theChar)
+{
+ // Clear char data.
+ memset(char_data, 0, sizeof(char_data));
+ memset(PIX_WEIGHTS, 0, sizeof(PIX_WEIGHTS));
+ memset(&fontm23[fontptr[charnum]], 0, 6);
+
+ // Transpose character data.
+ for (curr_word = 0; curr_word < 8; curr_word++) {
+ for (u = 16; u-- > 0;) {
+ if (theChar[curr_word] & 1 << u) {
+ pix_cnt++;
+ PIX_WEIGHTS[TAB_0_25[TAB_0_5[u]] +
+ TAB_0_4[curr_word]]++;
+ char_data[u ^ 0x0F & 0x0F] |=
+ BTAB[curr_word];
+ }
+ }
+ }
+
+ // Determine algorithm to use for number of pixels.
+ // Algorithm A is used when roughly half of the # of pixels are set.
+ // Algorithm B is used either when the image is densely or sparsely populated (based on pix_cnt).
+ if ((54 <= pix_cnt) && (pix_cnt < 85)) {
+ // Algorithm A - approx Half of pixels are set
+ for (u = 6; u-- > 0;) {
+ for (v = 5; v-- > 0;) {
+ if (PIX_WEIGHTS[TAB_0_25[u] + v] >=
+ PIX_THRESH[TAB_0_25[u] + v])
+ fontm23[fontptr[charnum] + u] |=
+ BTAB[v];
+ }
+ }
+ } else if ((pix_cnt < 54) || (pix_cnt >= 85)) {
+ // Algorithm B - Sparsely or heavily populated bitmaps
+ for (u = 16; u-- > 0;) {
+ for (v = 8; v-- > 0;) {
+ if (char_data[u] & (1 << v)) {
+ fontm23[fontptr[charnum] +
+ TAB_0_5i[u]] |= BTAB_5[v];
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * touch.c - Touchscreen functions (apple2)
+ */
+
+#include <stdint.h>
+
+/* Scaling tables for touch to convert 320x192 to 512x512 */
+uint16_t scaletx[] = {
+ 0, 2, 4, 5, 7, 8, 10, 12,
+ 13, 15, 16, 18, 20, 21, 23, 24,
+ 26, 28, 29, 31, 32, 34, 36, 37,
+ 39, 40, 42, 44, 45, 47, 48, 50,
+ 52, 53, 55, 56, 58, 60, 61, 63,
+ 64, 66, 68, 69, 71, 72, 74, 76,
+ 77, 79, 80, 82, 84, 85, 87, 88,
+ 90, 92, 93, 95, 96, 98, 100, 101,
+ 103, 104, 106, 108, 109, 111, 112, 114,
+ 116, 117, 119, 120, 122, 124, 125, 127,
+ 128, 130, 132, 133, 135, 136, 138, 140,
+ 141, 143, 144, 146, 148, 149, 151, 152,
+ 154, 156, 157, 159, 160, 162, 164, 165,
+ 167, 168, 170, 172, 173, 175, 176, 178,
+ 180, 181, 183, 184, 186, 188, 189, 191,
+ 192, 194, 196, 197, 199, 200, 202, 204,
+ 205, 207, 208, 210, 212, 213, 215, 216,
+ 218, 220, 221, 223, 224, 226, 228, 229,
+ 231, 232, 234, 236, 237, 239, 240, 242,
+ 244, 245, 247, 248, 250, 252, 253, 255,
+ 256, 258, 260, 261, 263, 264, 266, 268,
+ 269, 271, 272, 274, 276, 277, 279, 280,
+ 282, 284, 285, 287, 288, 290, 292, 293,
+ 295, 296, 298, 300, 301, 303, 304, 306,
+ 308, 309, 311, 312, 314, 316, 317, 319,
+ 320, 322, 324, 325, 327, 328, 330, 332,
+ 333, 335, 336, 338, 340, 341, 343, 344,
+ 346, 348, 349, 351, 352, 354, 356, 357,
+ 359, 360, 362, 364, 365, 367, 368, 370,
+ 372, 373, 375, 376, 378, 380, 381, 383,
+ 384, 386, 388, 389, 391, 392, 394, 396,
+ 397, 399, 400, 402, 404, 405, 407, 408,
+ 410, 412, 413, 415, 416, 418, 420, 421,
+ 423, 424, 426, 428, 429, 431, 432, 434,
+ 436, 437, 439, 440, 442, 444, 445, 447,
+ 448, 450, 452, 453, 455, 456, 458, 460,
+ 461, 463, 464, 466, 468, 469, 471, 472,
+ 474, 476, 477, 479, 480, 482, 484, 485,
+ 487, 488, 490, 492, 493, 495, 496, 498,
+ 500, 501, 503, 504, 506, 508, 509,
+};
+
+uint16_t scalety[] = {
+ 510, 507, 504, 502, 499, 496, 494, 491,
+ 488, 486, 483, 480, 478, 475, 472, 470,
+ 467, 464, 462, 459, 456, 454, 451, 448,
+ 446, 443, 440, 438, 435, 432, 430, 427,
+ 424, 422, 419, 416, 414, 411, 408, 406,
+ 403, 400, 398, 395, 392, 390, 387, 384,
+ 382, 379, 376, 374, 371, 368, 366, 363,
+ 360, 358, 355, 352, 350, 347, 344, 342,
+ 339, 336, 334, 331, 328, 326, 323, 320,
+ 318, 315, 312, 310, 307, 304, 302, 299,
+ 296, 294, 291, 288, 286, 283, 280, 278,
+ 275, 272, 270, 267, 264, 262, 259, 256,
+ 254, 251, 248, 246, 243, 240, 238, 235,
+ 232, 230, 227, 224, 222, 219, 216, 214,
+ 211, 208, 206, 203, 200, 198, 195, 192,
+ 190, 187, 184, 182, 179, 176, 174, 171,
+ 168, 166, 163, 160, 158, 155, 152, 150,
+ 147, 144, 142, 139, 136, 134, 131, 128,
+ 126, 123, 120, 118, 115, 112, 110, 107,
+ 104, 102, 99, 96, 94, 91, 88, 86,
+ 83, 80, 78, 75, 72, 70, 67, 64,
+ 62, 59, 56, 54, 51, 48, 46, 43,
+ 40, 38, 35, 32, 30, 27, 24, 22,
+ 19, 16, 14, 11, 8, 6, 3, 0,
+};
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * io.h - Input/output functions (serial/ethernet)
+ */
+
+#ifndef IO_H
+#define IO_H
+
+/**
+ * io_init() - Set-up the I/O
+ */
+void io_init(void);
+
+/**
+ * io_send_byte(b) - Send specified byte out
+ */
+void io_send_byte(uint8_t b);
+
+/**
+ * io_main() - The IO main loop
+ */
+void io_main(void);
+
+/**
+ * io_done() - Called to close I/O
+ */
+void io_done(void);
+
+/**
+ * io_process_queue() - Process the outbound queue
+ */
+
+void io_process_queue(void);
+
+#endif /* IO_H */
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * io.c - Input/output functions (serial/ethernet)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "io.h"
+#include "protocol.h"
+
+static uint8_t ch=0;
+int io_fd = -1;
+int io_eof;
+
+
+/**
+ * io_init() - Open the device
+ */
+void io_init(void)
+{
+ int s = socket(AF_INET, SOCK_STREAM, 0);
+ struct sockaddr_in sin;
+ if (s == -1) {
+ perror("socket");
+ return;
+ }
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(8005);
+ /* FIXME: don't hard code! */
+ sin.sin_addr.s_addr = htonl(0x60E2F5B3);
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ perror("connect");
+ return;
+ }
+ fcntl(s, F_SETFL, FNDELAY);
+ io_fd = s;
+}
+
+/**
+ * io_recv() - Receive and interpret data.
+ */
+void io_main(void)
+{
+ char buf[256];
+ int l;
+
+ /* The OS does our buffering (badly or not varies) */
+ while((l = read(io_fd, buf, 256)) > 0)
+ ShowPLATO(buf, l);
+ if (l <= 0) {
+ if (l == -1 && errno != EAGAIN) {
+ io_eof = 1;
+ perror("read");
+ }
+ }
+ io_process_queue();
+}
+
+/**
+ * io_done() - Called to close I/O
+ */
+void io_done(void)
+{
+ close(io_fd);
+ io_fd = -1;
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * keyboard.h - Keyboard functions
+ */
+
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+/**
+ * keyboard_out - If platoKey < 0x7f, pass off to protocol
+ * directly. Otherwise, platoKey is an access key, and the
+ * ACCESS key must be sent, followed by the particular
+ * access key from PTAT_ACCESS.
+ */
+void keyboard_out(uint8_t platoKey);
+
+/**
+ * keyboard_main - Handle the keyboard presses
+ */
+void keyboard_main(void);
+
+/**
+ * keyboard_clear() - Clear the keyboard buffer
+ */
+void keyboard_clear(void);
+
+/**
+ * keyboard_out_tty - keyboard output to serial I/O in TTY mode
+ */
+void keyboard_out_tty(char ch);
+
+#endif
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * keyboard_base.c - Keyboard functions (base)
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "keyboard.h"
+#include "screen.h"
+#include "protocol.h"
+#include "io.h"
+#include "plato_key.h"
+
+/**
+ * keyboard_out - If platoKey < 0x7f, pass off to protocol
+ * directly. Otherwise, platoKey is an access key, and the
+ * ACCESS key must be sent, followed by the particular
+ * access key from PTAT_ACCESS.
+ */
+void keyboard_out(uint8_t platoKey)
+{
+ if (platoKey==0xff)
+ return;
+
+ if (platoKey>0x7F)
+ {
+ Key(ACCESS);
+ Key(ACCESS_KEYS[platoKey-0x80]);
+ return;
+ }
+ Key(platoKey);
+ return;
+}
+
+/**
+ * keyboard_out_tty - keyboard output to serial I/O in TTY mode
+ */
+void keyboard_out_tty(char ch)
+{
+ io_send_byte(ch);
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * plato.c - main program
+ */
+
+#include <stdbool.h>
+#include "terminal.h"
+#include "screen.h"
+#include "touch.h"
+#include "keyboard.h"
+#include "io.h"
+
+uint8_t already_started=false;
+extern padByte splash[];
+extern short splash_size;
+
+/**
+ * greeting(void) - Show terminal greeting
+ */
+void greeting(void)
+{
+ ShowPLATO(splash,splash_size);
+ terminal_initial_position();
+}
+
+void main(void)
+{
+ screen_init();
+ io_init();
+ touch_init();
+ terminal_init();
+ greeting();
+ screen_beep();
+
+ already_started=true;
+
+ // And do the terminal
+ for (;;)
+ {
+ io_main();
+ keyboard_main();
+ touch_main();
+ }
+
+ screen_done();
+ touch_done();
+}
--- /dev/null
+/**
+ * plato_key.h
+ * PLATO specific key mappings
+ * used by key.h
+ * this define table is ordered as in s0ascers document.
+ */
+
+#ifndef PLATO_KEY_H
+#define PLATO_KEY_H
+
+#define PKEY_a 0x41
+#define PKEY_A 0x61
+#define PKEY_b 0x42
+#define PKEY_B 0x62
+#define PKEY_c 0x43
+#define PKEY_C 0x63
+#define PKEY_d 0x44
+#define PKEY_D 0x64
+#define PKEY_e 0x45
+#define PKEY_E 0x65
+#define PKEY_f 0x46
+#define PKEY_F 0x66
+#define PKEY_g 0x47
+#define PKEY_G 0x67
+#define PKEY_h 0x48
+#define PKEY_H 0x68
+#define PKEY_i 0x49
+#define PKEY_I 0x69
+#define PKEY_j 0x4a
+#define PKEY_J 0x6a
+#define PKEY_k 0x4b
+#define PKEY_K 0x6b
+#define PKEY_l 0x4c
+#define PKEY_L 0x6C
+#define PKEY_m 0x4d
+#define PKEY_M 0x6d
+#define PKEY_n 0x4e
+#define PKEY_N 0x6e
+#define PKEY_o 0x4f
+#define PKEY_O 0x6f
+#define PKEY_p 0x50
+#define PKEY_P 0x70
+#define PKEY_q 0x51
+#define PKEY_Q 0x71
+#define PKEY_r 0x52
+#define PKEY_R 0x72
+#define PKEY_s 0x53
+#define PKEY_S 0x73
+#define PKEY_t 0x54
+#define PKEY_T 0x74
+#define PKEY_u 0x55
+#define PKEY_U 0x75
+#define PKEY_v 0x56
+#define PKEY_V 0x76
+#define PKEY_w 0x57
+#define PKEY_W 0x77
+#define PKEY_x 0x58
+#define PKEY_X 0x78
+#define PKEY_y 0x59
+#define PKEY_Y 0x79
+#define PKEY_z 0x5a
+#define PKEY_Z 0x7A
+#define PKEY_0 0x00
+#define PKEY_LESS_THAN 0x20
+#define PKEY_1 0x01
+#define PKEY_GREATER_THAN 0x21
+#define PKEY_2 0x02
+#define PKEY_BRACKET_LEFT 0x22
+#define PKEY_3 0x03
+#define PKEY_BRACKET_RIGHT 0x23
+#define PKEY_4 0x04
+#define PKEY_DOLLAR 0x24
+#define PKEY_5 0x05
+#define PKEY_PERCENT 0x25
+#define PKEY_6 0x06
+#define PKEY_UNDERSCORE 0x26
+#define PKEY_7 0x07
+#define PKEY_APOSTROPHE 0x27
+#define PKEY_8 0x08
+#define PKEY_ASTERISK 0x28
+#define PKEY_9 0x09
+#define PKEY_PARENTHESIS_LEFT 0x29
+#define PKEY_EQUALS 0x5B
+#define PKEY_PARENTHESIS_RIGHT 0x7B
+#define PKEY_PLUS 0x0E
+#define PKEY_SIGMA 0x2E
+#define PKEY_ASSIGN 0x0D
+#define PKEY_SHIFT 0x2D
+#define PKEY_MINUS 0x0F
+#define PKEY_DELTA 0x2F
+#define PKEY_DIVIDE 0x0B
+#define PKEY_INTERSECT 0x2B
+#define PKEY_MULTIPLY 0x0A
+#define PKEY_UNION 0x2A
+#define PKEY_SEMICOLON 0x5c
+#define PKEY_COLON 0x7c
+#define PKEY_PERIOD 0x5e
+#define PKEY_EXCLAMATION 0x7e
+#define PKEY_COMMA 0x5f
+#define PKEY_QUOTE 0x7f
+#define PKEY_SLASH 0x5d
+#define PKEY_QUESTION_MARK 0x7d
+#define PKEY_SUPER 0x10
+#define PKEY_SUPER1 0x30
+#define PKEY_SUB 0x11
+#define PKEY_SUB1 0x31
+#define PKEY_ANS 0x12
+#define PKEY_TERM 0x32
+#define PKEY_COPY 0x1B
+#define PKEY_COPY1 0x3B
+#define PKEY_TAB 0x0c
+#define PKEY_CR 0x2c
+#define PKEY_ERASE 0x13
+#define PKEY_ERASE1 0x33
+#define PKEY_MICRO 0x14
+#define PKEY_FONT 0x34
+#define PKEY_HELP 0x15
+#define PKEY_HELP1 0x35
+#define PKEY_SQUARE 0x1C
+#define PKEY_ACCESS 0x3C
+#define PKEY_NEXT 0x16
+#define PKEY_NEXT1 0x36
+#define PKEY_EDIT 0x17
+#define PKEY_EDIT1 0x37
+#define PKEY_BACK 0x18
+#define PKEY_BACK1 0x38
+#define PKEY_LAB 0x1D
+#define PKEY_LAB1 0x3D
+#define PKEY_DATA 0x19
+#define PKEY_DATA1 0x39
+#define PKEY_STOP 0x1a
+#define PKEY_STOP1 0x3a
+#define PKEY_SPACE 0x40
+#define PKEY_BACKSPACE 0x60
+#define PKEY_PRINT 0x1F
+#define PKEY_PRINT1 0x3F
+#define PKEY_NOKEY 0xFF /* no key mapping */
+
+/* The following keys require an ACCESS key combination */
+#define PKEY_ALPHA 0x80
+#define PKEY_BETA 0x81
+#define PKEY_CEDILLA 0x82
+#define PKEY_LOWERCASE_DELTA 0x83
+#define PKEY_ACUTE_ACCENT 0x84
+#define PKEY_LOWERCASE_AE 0x85
+#define PKEY_LOWERCASE_OE 0x86
+#define PKEY_LOWERCASE_A_WITH_RING 0x87
+#define PKEY_LOWERCASE_A_WITH_DIAERESIS 0x88
+#define PKEY_LAMBDA 0x89
+#define PKEY_MU 0x8A
+#define PKEY_TILDE 0x8B
+#define PKEY_DEGREE 0x8C
+#define PKEY_PI 0x8D
+#define PKEY_GRAVE 0x8E
+#define PKEY_RHO 0x8F
+#define PKEY_LOWERCASE_SIGMA 0x90
+#define PKEY_THETA 0x91
+#define PKEY_DIARESIS 0x92
+#define PKEY_HACEK 0x93
+#define PKEY_CAPITAL_PI 0x94
+#define PKEY_CIRCUMFLEX 0x95
+#define PKEY_LEFT_EMBED 0x96
+#define PKEY_RIGHT_EMBED 0x97
+#define PKEY_AT 0x98
+#define PKEY_ARROW 0x99
+#define PKEY_AMPERSAND 0x9A
+#define PKEY_INTERPUNCT 0x9B
+#define PKEY_LOWER_TILDE 0x9C
+#define PKEY_DELIMITER 0x9D
+#define PKEY_BACKSLASH 0x9E
+#define PKEY_NOT_EQUAL 0x9F
+#define PKEY_LOWERCASE_O_WITH_DIARESIS 0xA0
+#define PKEY_LEFT_ARROW 0xA1
+#define PKEY_DOWN_ARROW 0xA2
+#define PKEY_RIGHT_ARROW 0xA3
+#define PKEY_UP_ARROW 0xA4
+#define PKEY_COPYRIGHT 0xA5
+#define PKEY_DIAMOND 0xA6
+#define PKEY_UPPERCASE_AE 0xA7
+#define PKEY_UPPERCASE_OE 0xA8
+#define PKEY_BAR 0xA9
+#define PKEY_UPPERCASE_A_WITH_RING 0xAA
+#define PKEY_UPPERCASE_A_WITH_DIAERESIS 0xAB
+#define PKEY_ACCESS_SQUARE 0xAC
+#define PKEY_UPPERCASE_O_WITH_DIARESIS 0xAD
+#define PKEY_LESS_THAN_OR_EQUAL 0xAE
+#define PKEY_GREATER_THAN_OR_EQUAL 0xAF
+#define PKEY_LEFT_CURLY_BRACE 0xB0
+#define PKEY_RIGHT_CURLY_BRACE 0xB1
+#define PKEY_POUND 0xB2
+#define PKEY_BIG_CROSS 0xB3
+#define PKEY_EQUIVALENT 0xB4
+
+/* ACCESS Key combinations. */
+static uint8_t ACCESS_KEYS[] = {
+ PKEY_a, /* 0x80 a É‘ alpha */
+ PKEY_B, /* 0x81 b ß beta */
+ PKEY_c, /* 0x82 c cedilla */
+ PKEY_d, /* 0x83 d δ delta */
+ PKEY_e, /* 0x84 e ' acute accent */
+ PKEY_g, /* 0x85 g æ ae */
+ PKEY_h, /* 0x86 h oe oe */
+ PKEY_j, /* 0x87 j å a with ring */
+ PKEY_k, /* 0x88 k ä a with diaeresis */
+ PKEY_l, /* 0x89 l Æ› lambda */
+ PKEY_m, /* 0x8A m μ mu */
+ PKEY_n, /* 0x8B n ~ tilde */
+ PKEY_o, /* 0x8C o ° degree */
+ PKEY_p, /* 0x8D p π pi */
+ 0x51, /* 0x8E q ` grave */
+ PKEY_r, /* 0x8F r Ï rho */
+ PKEY_s, /* 0x90 s σ sigma */
+ PKEY_t, /* 0x91 t θ theta */
+ PKEY_u, /* 0x92 u ¨ diaeresis */
+ PKEY_v, /* 0x93 v hacek (upside down circumflex) */
+ PKEY_w, /* 0x94 w Ï– capital pi */
+ PKEY_x, /* 0x95 x ^ circumflex */
+ PKEY_0, /* 0x96 0 l-embed */
+ PKEY_1, /* 0x97 1 r-embed */
+ PKEY_5, /* 0x98 5 @ */
+ PKEY_6, /* 0x99 6 arrow */
+ PKEY_PLUS, /* 0x9a + & */
+ 0x26, /* 0x9b & interpunct */
+ PKEY_COLON, /* 0x9c : ~ lower tilde */
+ 0x5f, /* 0x9d , delimiter */
+ PKEY_SLASH, /* 0x9e / \ */
+ PKEY_EQUALS, /* 0x9f = not equal */
+ PKEY_y, /* 0xA0 y ö */
+ 0x61, /* 0xA1 A left arrow */
+ 0x78, /* 0xA2 X down arrow */
+ 0x64, /* 0xA3 D right arrow */
+ 0x77, /* 0xA4 W up arrow */
+ 0x63, /* 0xA5 C © */
+ 0x66, /* 0xA6 F ♦ */
+ 0x67, /* 0xA7 G Æ */
+ 0x68, /* 0xA8 H OE */
+ 0x69, /* 0xA9 I | */
+ 0x6A, /* 0xAA J Å */
+ 0x6B, /* 0xAB K Ä */
+ 0x6F, /* 0xAC O SQUARE */
+ 0x79, /* 0xAD Y Ö */
+ 0x20, /* 0xAE < ≤ */
+ 0x21, /* 0xAF > ≥ */
+ 0x5B, /* 0xB0 [ { */
+ PKEY_SLASH, /* 0xB1 ] } */
+ 0x24, /* 0xB2 $ # */
+ 0x9a, /* 0xB3 & big cross */
+ 0x7B /* 0xB4 EQUIVALENT */
+};
+
+#endif /* PLATO_KEY_H */
+
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ * This file written by Steve Peltz. Copyright notice preserved.
+ * and this code has been used with permission, and can be considered
+ * public domain.
+ *
+ * protocol.c - Protocol decoder functions
+ */
+
+/* Copyright (c) 1990 by Steve Peltz */
+
+#include <stdbool.h>
+#include "protocol.h"
+
+#define BSIZE 64
+
+static padBool EscFlag; /* Currently in an escape sequence */
+static Mode PMode, /* Mode */
+ CMode; /* Command */
+static uint16_t SubMode; /* Block/Line modes */
+static DataType PType, /* Mode type */
+ CType; /* Current type */
+static uint16_t Phase; /* Phase of current type */
+static padWord theWord; /* Data received for various data types */
+static padByte theChar;
+static padByte rawChar;
+static padByte lastChar;
+static padRGB theColor;
+static uint16_t LowX, /* Previous coordinates received */
+ HiX, LowY, HiY;
+static padPt CurCoord; /* Current coordinate */
+static padWord Margin; /* Margin for CR */
+static padWord MemAddr; /* Load address for program data */
+static uint16_t CharCnt; /* Current count for loading chars */
+static charData Char; /* Character data */
+static padByte charBuff[BSIZE];
+static uint16_t charCount; /* Count of characters currently buffered */
+static padPt charCoord;
+
+extern uint8_t terminal_get_features(void);
+extern uint8_t terminal_get_type(void);
+extern uint8_t terminal_get_subtype(void);
+extern uint8_t terminal_get_load_file(void);
+extern uint8_t terminal_get_configuration(void);
+extern uint16_t terminal_get_char_address(void);
+extern padByte terminal_mem_read(padWord addr);
+extern padByte terminal_ext_in(void);
+
+extern void screen_wait(void);
+extern void screen_beep(void);
+extern void io_send_byte(uint8_t b);
+extern void screen_block_draw(padPt* Coord1, padPt* Coord2);
+extern void screen_dot_draw(padPt* Coord);
+extern void screen_line_draw(padPt* Coord1, padPt* Coord2);
+extern void screen_char_draw(padPt* Coord, unsigned char* ch, unsigned char count);
+extern void screen_tty_char(padByte theChar);
+extern void terminal_mem_load(padWord addr, padWord value);
+extern void terminal_char_load(padWord charnum, charData theChar);
+extern void terminal_mode_5(padWord value);
+extern void terminal_mode_6(padWord value);
+extern void terminal_mode_7(padWord value);
+extern void touch_allow(padBool allow);
+extern void terminal_ext_allow(padBool allow);
+extern void terminal_set_ext_in(padWord device);
+extern void terminal_set_ext_out(padWord device);
+extern void terminal_ext_out(padByte value);
+extern void screen_clear(void);
+extern void terminal_set_tty(void);
+extern void terminal_set_plato(void);
+
+#ifdef PROTOCOL_DEBUG
+extern void log(const char* format, ...);
+#endif
+
+static padByte PTAT0[128] = { /* PLATO to ASCII lookup table */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* original mapping */
+ 0x38, 0x39, 0x26, 0x60, 0x0a, 0x5e, 0x2b, 0x2d,
+ 0x13, 0x04, 0x07, 0x08, 0x7b, 0x0b, 0x0d, 0x1a,
+ 0x02, 0x12, 0x01, 0x03, 0x7d, 0x0c, 0x83, 0x85,
+ 0x3c, 0x3e, 0x5b, 0x5d, 0x24, 0x25, 0x5f, 0x7c,
+ 0x2a, 0x28, 0x40, 0x27, 0x1c, 0x5c, 0x23, 0x7e,
+ 0x17, 0x05, 0x14, 0x19, 0x7f, 0x09, 0x1e, 0x18,
+ 0x0e, 0x1d, 0x11, 0x16, 0x00, 0x0f, 0x87, 0x88,
+ 0x20, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x3d, 0x3b, 0x2f, 0x2e, 0x2c,
+ 0x1f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x29, 0x3a, 0x3f, 0x21, 0x22
+};
+
+static padByte PTAT1[128] = {
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* flow control mapping */
+ 0x38, 0x39, 0x26, 0x60, 0x09, 0x5e, 0x2b, 0x2d,
+ 0x17, 0x04, 0x07, 0x08, 0x7b, 0x0b, 0x0d, 0x1a,
+ 0x02, 0x12, 0x01, 0x03, 0x7d, 0x0c, 0x83, 0x85,
+ 0x3c, 0x3e, 0x5b, 0x5d, 0x24, 0x25, 0x5f, 0x27,
+ 0x2a, 0x28, 0x40, 0x7c, 0x1c, 0x5c, 0x23, 0x7e,
+ 0x97, 0x84, 0x14, 0x19, 0x7f, 0x0a, 0x1e, 0x18,
+ 0x0e, 0x1d, 0x05, 0x16, 0x9d, 0x0f, 0x87, 0x88,
+ 0x20, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x3d, 0x3b, 0x2f, 0x2e, 0x2c,
+ 0x1f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x29, 0x3a, 0x3f, 0x21, 0x22
+};
+
+/* externally referenced variables */
+
+padPt PLATOSize={512,512}; /* Logical screen size */
+CharMem CurMem; /* Font to plot in */
+padBool TTY, /* TTY mode */
+ FlowControl, /* Flow control on */
+ ModeBold, /* Character plotting conditions */
+ Rotate, Reverse;
+DispMode CurMode; /* Current PLATO plotting mode */
+padBool FastText; /* Indicate to main program if text optimizations can be done. */
+
+
+/*----------------------------------------------*
+ * InitPAD, InitTTY, InitPLATO *
+ * *
+ * Called to initialize PAD variables. *
+ * Calls back to external routines to *
+ * set up proper plotting conditions. *
+ *----------------------------------------------*/
+
+void
+InitPAD (void)
+{
+ InitTTY ();
+}
+
+void
+InitTTY (void)
+{
+ charCount = 0;
+ EscFlag = false;
+ TTY = true;
+ FastText = true;
+ FlowControl = false;
+ terminal_set_tty();
+}
+
+void
+InitPLATO (void)
+{
+ // Key (0x382); /* master reset key */
+ if (TTY)
+ InitPLATOx ();
+}
+
+void
+InitPLATOx (void)
+{
+ charCount = 0;
+ EscFlag = false;
+ TTY = false;
+ terminal_set_plato ();
+ SetMode (mAlpha, tByte);
+ LowX = 0;
+ HiX = 0;
+ LowY = 0;
+ HiY = 0;
+ CurCoord.x = 0;
+ CurCoord.y = 0;
+ MemAddr = 0;
+ CharCnt = 0;
+ Margin = 0;
+ ModeBold = false;
+ Rotate = false;
+ Reverse = false;
+ FastText = true;
+ CurMem = M0;
+ CurMode = ModeRewrite;
+}
+
+
+/*----------------------------------------------*
+ * Key *
+ * *
+ * Send a 10-bit internal key. If a keyset *
+ * key, translate, else send as escaped *
+ * sequence. *
+ *----------------------------------------------*/
+
+void
+Key (padWord theKey)
+{
+ if (theKey >> 7)
+ {
+ io_send_byte (0x1b);
+ io_send_byte (0x40 | (theKey & 0x3f));
+ io_send_byte (0x60 | ((theKey >> 6) & 0x0f));
+ }
+ else
+ {
+
+ if (FlowControl == 0)
+ theKey = PTAT0[theKey];
+ else
+ theKey = PTAT1[theKey];
+
+ if (theKey & 0x80)
+ {
+ io_send_byte (0x1b);
+ io_send_byte (theKey & 0x7f);
+ }
+ else
+ io_send_byte (theKey);
+ }
+}
+
+/*----------------------------------------------*
+ * Touch *
+ * *
+ * Send a touch key (01yyyyxxxx). *
+ *----------------------------------------------*/
+
+void Touch(padPt* where)
+{
+ // Send FGT (Fine Grained Touch) data.
+ io_send_byte(0x1b);
+ io_send_byte(0x1f);
+ io_send_byte(0x40 + (where->x & 0x1f));
+ io_send_byte(0x40 + ((where->x >> 5) & 0x0f));
+ io_send_byte(0x40 + (where->y & 0x1f));
+ io_send_byte(0x40 + ((where->y >> 5) & 0x0f));
+
+ // Send coarse touch data
+ Key(0x100 | ((where->x >> 1) & 0xF0) |
+ ((where->y >> 5) & 0x0F));
+}
+
+/*----------------------------------------------*
+ * Ext *
+ * *
+ * Send an external key (10xxxxxxxx). *
+ *----------------------------------------------*/
+
+void
+Ext (padWord theKey)
+{
+ Key (0x200 | (theKey & 0xFF));
+}
+
+
+/*----------------------------------------------*
+ * Echo *
+ * *
+ * Send an echo key (001xxxxxx). *
+ *----------------------------------------------*/
+
+void
+Echo (padWord theKey)
+{
+ Key (0x080 | theKey);
+}
+
+
+
+/*----------------------------------------------*
+ * SetCommand, SetMode *
+ * *
+ * Set state machine variables. *
+ *----------------------------------------------*/
+
+void
+SetCommand (Mode theMode, DataType theType)
+{
+ CMode = theMode;
+ CType = theType;
+ Phase = 0;
+}
+
+void
+SetMode (Mode theMode, DataType theType)
+{
+ PMode = theMode;
+ PType = theType;
+ SubMode = 0;
+ SetCommand (theMode, theType);
+}
+
+
+/*----------------------------------------------*
+ * FixXY *
+ * *
+ * Move location by offset, then make sure *
+ * it is still on the screen. *
+ *----------------------------------------------*/
+
+void
+FixXY (int16_t DX, int16_t DY)
+{
+ if (ModeBold)
+ {
+ DX = DX * 2;
+ DY = DY * 2;
+ }
+ if (Reverse)
+ DX = -DX;
+ if (Rotate)
+ {
+ CurCoord.x = CurCoord.x + DY;
+ CurCoord.y = CurCoord.y + DX;
+ }
+ else
+ {
+ CurCoord.x = CurCoord.x + DX;
+ CurCoord.y = CurCoord.y + DY;
+ }
+
+ if (CurCoord.x < 0)
+ CurCoord.x += PLATOSize.x;
+ else if (CurCoord.x >= PLATOSize.x)
+ CurCoord.x -= PLATOSize.x;
+
+ if (CurCoord.y < 0)
+ CurCoord.y += PLATOSize.y;
+ else if (CurCoord.y >= PLATOSize.y)
+ CurCoord.y -= PLATOSize.y;
+}
+
+
+/*----------------------------------------------*
+ * Superx, Subx, etc. *
+ * *
+ * Various character positioning commands. *
+ *----------------------------------------------*/
+
+void
+Superx (void)
+{
+ FixXY (0, 5);
+}
+
+void
+Subx (void)
+{
+ FixXY (0, -5);
+}
+
+void
+Marginx (void)
+{
+ if (Rotate)
+ Margin = CurCoord.y;
+ else
+ Margin = CurCoord.x;
+}
+
+void
+BSx (void)
+{
+ FixXY (-8, 0);
+}
+
+void
+HTx (void)
+{
+ FixXY (8, 0);
+}
+
+void
+LFx (void)
+{
+ FixXY (0, -16);
+}
+
+void
+VTx (void)
+{
+ FixXY (0, 16);
+}
+
+void
+FFx (void)
+{
+ CurCoord.y = 0;
+ CurCoord.x = 0;
+ LFx ();
+}
+
+void
+CRx (void)
+{
+ if (Rotate)
+ CurCoord.y = Margin;
+ else
+ CurCoord.x = Margin;
+ LFx ();
+}
+
+
+/*----------------------------------------------*
+ * LoadCoordx *
+ * *
+ * Assemble completed coordinate. *
+ *----------------------------------------------*/
+
+void
+LoadCoordx (padPt * SetCoord)
+{
+ SetCoord->x = (HiX << 5) + LowX;
+ SetCoord->y = (HiY << 5) + LowY;
+}
+
+
+/*----------------------------------------------*
+ * Blockx, Pointx, Linex, Alphax *
+ * *
+ * Plot the specified item at the *
+ * current location. *
+ *----------------------------------------------*/
+
+void
+Blockx (void)
+{
+ padPt NewCoord;
+
+ if (SubMode == 0)
+ {
+ LoadCoordx (&CurCoord);
+ SubMode = 1;
+ }
+ else
+ {
+ LoadCoordx (&NewCoord);
+ screen_block_draw (&CurCoord, &NewCoord);
+ SubMode = 0;
+ }
+}
+
+void
+Pointx (void)
+{
+ LoadCoordx (&CurCoord);
+ screen_dot_draw (&CurCoord);
+}
+
+void
+Linex (void)
+{
+ padPt OldCoord;
+
+ if (SubMode == 0)
+ {
+ LoadCoordx (&CurCoord);
+ SubMode = 1;
+ }
+ else
+ {
+ OldCoord.y = CurCoord.y;
+ OldCoord.x = CurCoord.x;
+ LoadCoordx (&CurCoord);
+ screen_line_draw (&OldCoord, &CurCoord);
+ }
+}
+
+void
+Alphax (void)
+{
+ if (charCount == 0) {
+ charCoord.x = CurCoord.x;
+ charCoord.y = CurCoord.y;
+ }
+ charBuff[charCount++] = theChar;
+ HTx ();
+ if (charCount >= BSIZE)
+ {
+ screen_char_draw (&charCoord, charBuff, charCount);
+ charCount = 0;
+ }
+}
+
+
+/*----------------------------------------------*
+ * LoadEchox *
+ * *
+ * Echo responses to system. *
+ *----------------------------------------------*/
+
+void
+LoadEchox (void)
+{
+ theWord &= 0x7f;
+ switch (theWord)
+ {
+
+ case 0x52:
+ FlowControl=true;
+ if (FlowControl)
+ Echo (0x53); /* flow control on */
+ else
+ Echo (0x52); /* flow control not on */
+ break;
+ case 0x60: /* Inquire about ascii specific features. */
+ Echo (terminal_get_features());
+ break;
+ case 0x70:
+ Echo (terminal_get_type ()); /* terminal type */
+ break;
+
+ case 0x71:
+ Echo (terminal_get_subtype()); /* subtype */
+ break;
+
+ case 0x72:
+ Echo (terminal_get_load_file ()); /* load file */
+ break;
+
+ case 0x73:
+ Echo (terminal_get_configuration ()); /* configuration */
+ break;
+
+ case 0x7A:
+ Key (0x3FF); /* send backout */
+ break;
+
+ case 0x7B:
+ screen_beep ();
+ break; /* beep */
+
+ case 0x7D:
+ Echo (terminal_mem_read (MemAddr) & 0x7F);
+ break;
+
+ default:
+ Echo (theWord); /* normal echo */
+ break;
+ }
+}
+
+void
+LoadAddrx (void)
+{
+ MemAddr = theWord;
+ CharCnt = 0;
+}
+
+void
+LoadCharx (void)
+{
+ Char[CharCnt] = theWord;
+ if (CharCnt < 7)
+ CharCnt++;
+ else
+ {
+ terminal_char_load ((((MemAddr - terminal_get_char_address ()) >> 4) & 0x7f), Char);
+ CharCnt = 0;
+ MemAddr += 16;
+ }
+}
+
+void
+LoadMemx (void)
+{
+ terminal_mem_load (MemAddr, theWord);
+ MemAddr += 2;
+}
+
+void
+SSFx (void)
+{
+ padByte device;
+
+ device = (theWord >> 10) & 0xFF;
+ if (device == 1)
+ {
+ terminal_ext_allow ((theWord >> 3) & 1);
+ touch_allow ((theWord >> 5) & 1);
+ }
+ else if ((theWord >> 9) & 1)
+ {
+ terminal_set_ext_in (device);
+ if (!((theWord >> 8) & 1))
+ Ext (terminal_ext_in ());
+ }
+ else
+ {
+ terminal_set_ext_out (device);
+ if (!((theWord >> 8) & 1))
+ terminal_ext_out (theWord & 0xFF);
+ }
+}
+
+void
+Externalx (void)
+{
+ terminal_ext_out ((theWord >> 8) & 0xFF);
+ terminal_ext_out (theWord & 0xFF);
+}
+
+void
+GoMode (void)
+{
+ switch (CMode)
+ {
+ case mBlock:
+ Blockx ();
+ break;
+ case mPoint:
+ Pointx ();
+ break;
+ case mLine:
+ Linex ();
+ break;
+ case mAlpha:
+ Alphax ();
+ break;
+ case mLoadCoord:
+ LoadCoordx (&CurCoord);
+ break;
+ case mLoadAddr:
+ LoadAddrx ();
+ break;
+ case mSSF:
+ SSFx ();
+ break;
+ case mExternal:
+ Externalx ();
+ break;
+ case mLoadEcho:
+ LoadEchox ();
+ break;
+ case mLoadChar:
+ LoadCharx ();
+ break;
+ case mLoadMem:
+ LoadMemx ();
+ break;
+ case mMode5:
+ terminal_mode_5 (theWord);
+ break;
+ case mMode6:
+ terminal_mode_6 (theWord);
+ break;
+ case mMode7:
+ terminal_mode_7 (theWord);
+ break;
+ case mFore:
+ /* ForeGround (&theColor); */
+ break;
+ case mBack:
+ /* BackGround (&theColor); */
+ break;
+ }
+ CMode = PMode;
+ CType = PType;
+ Phase = 0;
+}
+
+void
+GoWord (void)
+{
+ switch (Phase)
+ {
+ case 0:
+ theWord = theChar & 0x3F;
+ Phase = 1;
+ break;
+ case 1:
+ theWord |= ((theChar & 0x3F) << 6);
+ Phase = 2;
+ break;
+ case 2:
+ theWord |= ((theChar & 0x3F) << 12);
+ GoMode ();
+ break;
+ }
+}
+
+void
+GoCoord (void)
+{
+ uint16_t CoordType, CoordValue;
+
+ CoordValue = theChar & 0x1F;
+ CoordType = ((theChar >> 5) & 3);
+ switch (CoordType)
+ {
+ case 1:
+ switch (Phase)
+ {
+ case 0:
+ HiY = CoordValue;
+ break;
+ case 1:
+ HiX = CoordValue;
+ break;
+ }
+ Phase = 1;
+ break;
+ case 2:
+ LowX = CoordValue;
+ GoMode ();
+ break;
+ case 3:
+ LowY = CoordValue;
+ Phase = 1;
+ break;
+ }
+}
+
+void
+GoColor (void)
+{
+ switch (Phase)
+ {
+ case 0:
+ theColor.blue = (theChar & 0x3f);
+ break;
+ case 1:
+ theColor.blue |= (theChar & 0x03) << 6;
+ theColor.green = (theChar & 0x3c) >> 2;
+ break;
+ case 2:
+ theColor.green |= (theChar & 0x0f) << 4;
+ theColor.red = (theChar & 0x30) >> 4;
+ break;
+ case 3:
+ theColor.red |= (theChar & 0x3f) << 2;
+ break;
+ }
+ if (Phase < 3)
+ Phase++;
+ else
+ GoMode ();
+}
+
+void
+GoPaint (void)
+{
+ if (Phase == 0)
+ Phase = 1;
+ else
+ GoMode ();
+
+}
+
+void
+DataChar (void)
+{
+ switch (CType)
+ {
+ case tByte:
+ Alphax ();
+ break;
+ case tWord:
+ GoWord ();
+ break;
+ case tCoord:
+ GoCoord ();
+ break;
+ case tColor:
+ GoColor ();
+ break;
+ case tPaint:
+ GoPaint ();
+ break;
+ }
+}
+
+void
+ShowPLATO (padByte *buff, uint16_t count)
+{
+ while (count--)
+ {
+ theChar = *buff++;
+ if (lastChar==0xFF && theChar==0xFF)
+ {
+ // Drop this character, it is an escaped TELNET IAC.
+ lastChar=0;
+ }
+ else
+ {
+ rawChar=theChar;
+ theChar &=0x7F;
+ if (TTY)
+ {
+ if (!EscFlag)
+ screen_tty_char (theChar);
+ else if (theChar == 0x02)
+ InitPLATOx ();
+ }
+ else if (EscFlag)
+ {
+ switch (theChar)
+ {
+ case 0x03:
+ InitTTY ();
+ break;
+
+ case 0x0C:
+ screen_clear ();
+ break;
+
+ case 0x11:
+ CurMode = ModeInverse;
+ SetFast();
+ break;
+ case 0x12:
+ CurMode = ModeWrite;
+ SetFast();
+ break;
+ case 0x13:
+ CurMode = ModeErase;
+ SetFast();
+ break;
+ case 0x14:
+ CurMode = ModeRewrite;
+ SetFast();
+ break;
+
+ case 0x32:
+ SetCommand (mLoadCoord, tCoord);
+ break;
+
+ case 0x40:
+ Superx ();
+ break;
+ case 0x41:
+ Subx ();
+ break;
+
+ case 0x42:
+ CurMem = M0;
+ break;
+ case 0x43:
+ CurMem = M1;
+ break;
+ case 0x44:
+ CurMem = M2;
+ break;
+ case 0x45:
+ CurMem = M3;
+ break;
+
+ case 0x4A:
+ Rotate = false;
+ SetFast();
+ break;
+ case 0x4B:
+ Rotate = true;
+ SetFast();
+ break;
+ case 0x4C:
+ Reverse = false;
+ SetFast();
+ break;
+ case 0x4D:
+ Reverse = true;
+ SetFast();
+ break;
+ case 0x4E:
+ ModeBold = false;
+ SetFast();
+ break;
+ case 0x4F:
+ ModeBold = true;
+ SetFast();
+ break;
+
+ case 0x50:
+ SetMode (mLoadChar, tWord);
+ break;
+ case 0x51:
+ SetCommand (mSSF, tWord);
+ break;
+ case 0x52:
+ SetCommand (mExternal, tWord);
+ break;
+ case 0x53:
+ SetMode (mLoadMem, tWord);
+ break;
+ case 0x54:
+ SetMode (mMode5, tWord);
+ break;
+ case 0x55:
+ SetMode (mMode6, tWord);
+ break;
+ case 0x56:
+ SetMode (mMode7, tWord);
+ break;
+ case 0x57:
+ SetCommand (mLoadAddr, tWord);
+ break;
+ case 0x59:
+ SetCommand (mLoadEcho, tWord);
+ break;
+
+ case 0x5A:
+ Marginx ();
+ break;
+
+ case 0x61:
+ SetCommand (mFore, tColor);
+ break;
+ case 0x62:
+ SetCommand (mBack, tColor);
+ break;
+ case 0x63:
+ SetCommand (mPaint, tPaint);
+ break;
+ }
+ }
+ else if (theChar < 0x20)
+ {
+ if (charCount > 0)
+ {
+ screen_char_draw (&charCoord, charBuff, charCount);
+ charCount = 0;
+ }
+ switch (theChar)
+ {
+ case 0x00:
+ screen_wait();
+ case 0x08:
+ BSx ();
+ break;
+ case 0x09:
+ HTx ();
+ break;
+ case 0x0A:
+ LFx ();
+ break;
+ case 0x0B:
+ VTx ();
+ break;
+ case 0x0C:
+ FFx ();
+ break;
+ case 0x0D:
+ CRx ();
+ break;
+
+ case 0x19:
+ SetMode (mBlock, tCoord);
+ break;
+ case 0x1C:
+ SetMode (mPoint, tCoord);
+ break;
+ case 0x1D:
+ SetMode (mLine, tCoord);
+ break;
+ case 0x1F:
+ SetMode (mAlpha, tByte);
+ break;
+ }
+ }
+ else
+ DataChar ();
+
+ EscFlag = (theChar == 0x1B);
+ lastChar=rawChar;
+ }
+ }
+ if (charCount > 0)
+ {
+ screen_char_draw (&charCoord, charBuff, charCount);
+ charCount = 0;
+ }
+}
+
+/**
+ * SetFast()
+ * Toggle fast text output if mode = write or erase, and no rotate or bold
+ */
+void SetFast(void)
+{
+ FastText = (((CurMode == ModeWrite) || (CurMode == ModeErase)) && ((Rotate == padF) && (ModeBold == padF)));
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ * This file written by Steve Peltz. Copyright notice preserved.
+ * and this code has been used with permission, and can be considered
+ * public domain.
+ *
+ * protocol.h - Protocol decoder functions
+ */
+
+/* Copyright (c) 1990 by Steve Peltz */
+
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+#include <stdint.h>
+
+#define ACCESS 0x3c
+
+typedef unsigned char padByte;
+typedef enum {padF, padT} padBool;
+typedef unsigned char padChar;
+typedef short padWord;
+typedef padWord charData[8];
+typedef struct {
+ padByte red,
+ green,
+ blue;
+ } padRGB;
+
+typedef struct {
+ padWord x,
+ y;
+ } padPt;
+
+typedef enum {ModeWrite, ModeErase, ModeRewrite, ModeInverse} DispMode;
+typedef enum {M0, M1, M2, M3} CharMem;
+
+typedef enum { mBlock, mPoint, mLine, mAlpha, mLoadCoord, mLoadChar, mSSF,
+ mExternal, mLoadMem, mMode5, mMode6, mMode7, mLoadAddr,
+ mLoadEcho, mFore, mBack, mPaint } Mode;
+
+typedef enum { tByte, tWord, tCoord, tColor, tPaint } DataType;
+
+extern padPt PLATOSize;
+extern CharMem CurMem;
+extern padBool TTY,
+ FlowControl,
+ ModeBold,
+ Rotate,
+ Reverse;
+extern DispMode CurMode;
+
+void InitPAD(void);
+void InitTTY(void);
+void InitPLATO(void);
+void InitPLATOx(void);
+void Key(padWord theKey);
+void Touch(padPt* where);
+void Ext(padWord theKey);
+void Echo(padWord theKey);
+void SetCommand(Mode theMode, DataType theType);
+void SetMode(Mode theMode, DataType theType);
+void FixXY(int16_t DX, int16_t DY);
+void Superx(void);
+void Subx(void);
+void Marginx(void);
+void BSx(void);
+void HTx(void);
+void LFx(void);
+void VTx(void);
+void FFx(void);
+void CRx(void);
+void LoadCoordx(padPt* SetCoord);
+void Blockx(void);
+void Pointx(void);
+void Linex(void);
+void Alphax(void);
+void LoadEchox(void);
+void LoadAddrx(void);
+void LoadCharx(void);
+void LoadMemx(void);
+void SSFx(void);
+void Externalx(void);
+void GoMode(void);
+void GoWord(void);
+void GoCoord(void);
+void GoColor(void);
+void GoPaint(void);
+void DataChar(void);
+void ShowPLATO(padByte* buff, uint16_t count);
+void SetFast(void);
+
+#endif
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * screen.h - Display output functions
+ */
+
+#ifndef SCREEN_H
+#define SCREEN_H
+
+#include "protocol.h"
+
+/**
+ * screen_init() - Set up the screen
+ */
+void screen_init(void);
+
+/**
+ * screen_load_driver()
+ * Load the TGI driver
+ */
+void screen_load_driver(void);
+
+/**
+ * screen_init_hook()
+ * Called after tgi_init to set any special features, e.g. nmi trampolines.
+ */
+void screen_init_hook(void);
+
+/**
+ * screen_cycle_foreground()
+ * Go to the next foreground color in palette
+ */
+void screen_cycle_foreground(void);
+
+/**
+ * screen_cycle_background()
+ * Go to the next background color in palette
+ */
+void screen_cycle_background(void);
+
+/**
+ * screen_cycle_border()
+ * Go to the next border color in palette
+ */
+void screen_cycle_border(void);
+
+/**
+ * screen_cycle_foreground_back()
+ * Go to the previous foreground color in palette
+ */
+void screen_cycle_foreground_back(void);
+
+/**
+ * screen_cycle_background_back()
+ * Go to the previous background color in palette
+ */
+void screen_cycle_background_back(void);
+
+/**
+ * screen_cycle_border_back()
+ * Go to the previous border color in palette
+ */
+void screen_cycle_border_back(void);
+
+/**
+ * screen_update_colors() - Set the terminal colors
+ */
+void screen_update_colors(void);
+
+/**
+ * screen_wait(void) - Sleep for approx 16.67ms
+ */
+void screen_wait(void);
+
+/**
+ * screen_beep(void) - Beep the terminal
+ */
+void screen_beep(void);
+
+/**
+ * screen_clear - Clear the screen
+ */
+void screen_clear(void);
+
+/**
+ * screen_block_draw(Coord1, Coord2) - Perform a block fill from Coord1 to Coord2
+ */
+void screen_block_draw(padPt* Coord1, padPt* Coord2);
+
+/**
+ * screen_dot_draw(Coord) - Plot a mode 0 pixel
+ */
+void screen_dot_draw(padPt* Coord);
+
+/**
+ * screen_line_draw(Coord1, Coord2) - Draw a mode 1 line
+ */
+void screen_line_draw(padPt* Coord1, padPt* Coord2);
+
+/**
+ * screen_char_draw(Coord, ch, count) - Output buffer from ch* of length count as PLATO characters
+ */
+void screen_char_draw(padPt* Coord, unsigned char* ch, unsigned char count);
+
+/**
+ * screen_tty_char - Called to plot chars when in tty mode
+ */
+void screen_tty_char(padByte theChar);
+
+/**
+ * screen_done()
+ * Close down TGI
+ */
+void screen_done(void);
+
+#endif /* SCREEN_H */
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * screen_base.c - Display output functions (base)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include "screen.h"
+#include "protocol.h"
+#include "io.h"
+
+uint8_t CharWide=8;
+uint8_t CharHigh=16;
+padPt TTYLoc;
+uint8_t pal[2];
+
+extern padBool FastText; /* protocol.c */
+
+#ifndef __ATARI__
+extern unsigned short scalex[];
+extern unsigned short scaley[];
+#endif
+
+extern uint8_t font[];
+extern uint8_t fontm23[];
+extern uint16_t fontptr[];
+extern uint8_t FONT_SIZE_X;
+extern uint8_t FONT_SIZE_Y;
+
+extern void (*io_recv_serial_flow_on)(void);
+extern void (*io_recv_serial_flow_off)(void);
+
+// Atari uses fast frac multiplies to save memory
+#ifdef __ATARI__
+extern uint16_t mul0625(uint16_t val);
+extern uint16_t mul0375(uint16_t val);
+#endif
+
+/*
+ * Silly functions to get us going
+ */
+
+static uint8_t pen;
+
+static void tgi_init(void)
+{
+}
+
+static void tgi_done(void)
+{
+}
+
+static void tgi_setpalette(const unsigned char *palette)
+{
+}
+
+static void tgi_clear(void)
+{
+// printf("[CLR]");
+ printf("\033[0;0H\033[J");
+ fflush(stdout);
+}
+
+static void tgi_setcolor(unsigned char c)
+{
+ pen = c;
+}
+
+static void tgi_setpixel(int x, int y)
+{
+ printf("\033[%d;%dH%c", y, x, " #"[pen]);
+// printf("[%d,%d->%d]", x, y, pen);
+ fflush(stdout);
+}
+
+static void tgi_bar(int x1, int y1, int x2, int y2)
+{
+ int x,y;
+ for (y = y1; y < y2; y++) {
+ printf("\033[%d;%dH", y, x1);
+ if (pen)
+ for(x = x1; x < x2; x++)
+ putchar('#');
+ else
+ for(x = x1; x < x2; x++)
+ putchar(' ');
+ }
+ fflush(stdout);
+// printf("[R %d,%d,%d,%d->%d]", x1, y1, x2,y2, pen);
+}
+
+static void tgi_line(int x1, int y1, int x2, int y2)
+{
+ int dx = abs(x2-x1), sx = x1<x2 ? 1 : -1;
+ int dy = -abs(y2-y1), sy = y1<y2 ? 1 : -1;
+ int err = dx+dy, e2; /* error value e_xy */
+
+ for(;;){ /* loop */
+ tgi_setpixel(x1,y1);
+ if (x1==x2 && y1==y2) break;
+ e2 = 2*err;
+ if (e2 >= dy) { err += dy; x1 += sx; } /* e_xy+e_x > 0 */
+ if (e2 <= dx) { err += dx; y1 += sy; } /* e_xy+e_y < 0 */
+ }
+
+// printf("[L %d,%d,%d,%d->%d]", x1, y1, x2,y2, pen);
+}
+
+/**
+ * screen_init() - Set up the screen
+ */
+void screen_init(void)
+{
+ screen_load_driver();
+ tgi_init();
+ screen_init_hook();
+ screen_update_colors();
+ tgi_setpalette(pal);
+ tgi_clear();
+}
+
+/**
+ * screen_clear - Clear the screen
+ */
+void screen_clear(void)
+{
+ tgi_clear();
+}
+
+/**
+ * screen_block_draw(Coord1, Coord2) - Perform a block fill from Coord1 to Coord2
+ */
+void screen_block_draw(padPt* Coord1, padPt* Coord2)
+{
+ if (CurMode==ModeErase || CurMode==ModeInverse)
+ tgi_setcolor(0);
+ else
+ tgi_setcolor(1);
+
+#ifdef __ATARI__
+ tgi_bar(mul0625(Coord1->x),mul0375(Coord1->y^0x1FF),mul0625(Coord2->x),mul0375(Coord2->y^0x1FF));
+#else
+ tgi_bar(scalex[Coord1->x],scaley[Coord1->y],scalex[Coord2->x],scaley[Coord2->y]);
+#endif
+
+}
+
+/**
+ * screen_dot_draw(Coord) - Plot a mode 0 pixel
+ */
+void screen_dot_draw(padPt* Coord)
+{
+ if (CurMode==ModeErase || CurMode==ModeInverse)
+ tgi_setcolor(0);
+ else
+ tgi_setcolor(1);
+#ifdef __ATARI__
+ tgi_setpixel(mul0625(Coord->x),mul0375(Coord->y^0x1FF));
+#else
+ tgi_setpixel(scalex[Coord->x],scaley[Coord->y]);
+#endif
+}
+
+/**
+ * screen_line_draw(Coord1, Coord2) - Draw a mode 1 line
+ */
+void screen_line_draw(padPt* Coord1, padPt* Coord2)
+{
+#ifdef __ATARI__
+ uint16_t x1=mul0625(Coord1->x);
+ uint16_t x2=mul0625(Coord2->x);
+ uint16_t y1=mul0375(Coord1->y^0x1FF);
+ uint16_t y2=mul0375(Coord2->y^0x1FF);
+#else
+ uint16_t x1=scalex[Coord1->x];
+ uint16_t x2=scalex[Coord2->x];
+ uint16_t y1=scaley[Coord1->y];
+ uint16_t y2=scaley[Coord2->y];
+#endif
+
+ if (CurMode==ModeErase || CurMode==ModeInverse)
+ tgi_setcolor(0);
+ else
+ tgi_setcolor(1);
+
+ tgi_line(x1,y1,x2,y2);
+}
+
+/**
+ * screen_char_draw(Coord, ch, count) - Output buffer from ch* of length count as PLATO characters
+ */
+void screen_char_draw(padPt* Coord, unsigned char* ch, unsigned char count)
+{
+ int16_t offset; /* due to negative offsets */
+ uint16_t x; /* Current X and Y coordinates */
+ uint16_t y;
+ uint16_t* px; /* Pointers to X and Y coordinates used for actual plotting */
+ uint16_t* py;
+ uint8_t i; /* current character counter */
+ uint8_t a; /* current character byte */
+ uint8_t j,k; /* loop counters */
+ int8_t b; /* current character row bit signed */
+ uint8_t width=FONT_SIZE_X;
+ uint8_t height=FONT_SIZE_Y;
+ uint16_t deltaX=1;
+ uint16_t deltaY=1;
+ uint8_t mainColor=1;
+ uint8_t altColor=0;
+ uint8_t *p;
+ uint8_t* curfont;
+
+ switch(CurMem)
+ {
+ case M0:
+ curfont=font;
+ offset=-32;
+ break;
+ case M1:
+ curfont=font;
+ offset=64;
+ break;
+ case M2:
+ curfont=fontm23;
+ offset=-32;
+ break;
+ case M3:
+ curfont=fontm23;
+ offset=32;
+ break;
+ }
+
+ if (CurMode==ModeRewrite)
+ {
+ altColor=0;
+ }
+ else if (CurMode==ModeInverse)
+ {
+ altColor=1;
+ }
+
+ if (CurMode==ModeErase || CurMode==ModeInverse)
+ mainColor=0;
+ else
+ mainColor=1;
+
+ tgi_setcolor(mainColor);
+
+#ifdef __ATARI__
+ x=mul0625((Coord->x&0x1FF));
+ y=mul0375((Coord->y+14^0x1FF)&0x1FF);
+#else
+ x=scalex[(Coord->x&0x1FF)];
+ y=scaley[(Coord->y)+14&0x1FF];
+#endif
+
+ if (FastText==padF)
+ {
+ goto chardraw_with_fries;
+ }
+
+ /* the diet chardraw routine - fast text output. */
+
+ for (i=0;i<count;++i)
+ {
+ a=*ch;
+ ++ch;
+ a+=offset;
+ p=&curfont[fontptr[a]];
+
+ for (j=0;j<FONT_SIZE_Y;++j)
+ {
+ b=*p;
+
+ for (k=0;k<FONT_SIZE_X;++k)
+ {
+ if (b<0) /* check sign bit. */
+ {
+ tgi_setcolor(mainColor);
+ tgi_setpixel(x,y);
+ }
+
+ ++x;
+ b<<=1;
+ }
+
+ ++y;
+ x-=width;
+ ++p;
+ }
+
+ x+=width;
+ y-=height;
+ }
+
+ return;
+
+ chardraw_with_fries:
+ if (Rotate)
+ {
+ deltaX=-abs(deltaX);
+ width=-abs(width);
+ px=&y;
+ py=&x;
+ }
+ else
+ {
+ px=&x;
+ py=&y;
+ }
+
+ if (ModeBold)
+ {
+ deltaX = deltaY = 2;
+ width<<=1;
+ height<<=1;
+ }
+
+ for (i=0;i<count;++i)
+ {
+ a=*ch;
+ ++ch;
+ a+=offset;
+ p=&curfont[fontptr[a]];
+ for (j=0;j<FONT_SIZE_Y;++j)
+ {
+ b=*p;
+
+ if (Rotate)
+ {
+ px=&y;
+ py=&x;
+ }
+ else
+ {
+ px=&x;
+ py=&y;
+ }
+
+ for (k=0;k<FONT_SIZE_X;++k)
+ {
+ if (b<0) /* check sign bit. */
+ {
+ tgi_setcolor(mainColor);
+ if (ModeBold)
+ {
+ tgi_setpixel(*px+1,*py);
+ tgi_setpixel(*px,*py+1);
+ tgi_setpixel(*px+1,*py+1);
+ }
+ tgi_setpixel(*px,*py);
+ }
+ else
+ {
+ if (CurMode==ModeInverse || CurMode==ModeRewrite)
+ {
+ tgi_setcolor(altColor);
+ if (ModeBold)
+ {
+ tgi_setpixel(*px+1,*py);
+ tgi_setpixel(*px,*py+1);
+ tgi_setpixel(*px+1,*py+1);
+ }
+ tgi_setpixel(*px,*py);
+ }
+ }
+
+ x += deltaX;
+ b<<=1;
+ }
+
+ y+=deltaY;
+ x-=width;
+ ++p;
+ }
+
+ Coord->x+=width;
+ x+=width;
+ y-=height;
+ }
+
+ return;
+
+}
+
+/**
+ * screen_tty_char - Called to plot chars when in tty mode
+ */
+void screen_tty_char(padByte theChar)
+{
+ if ((theChar >= 0x20) && (theChar < 0x7F)) {
+ screen_char_draw(&TTYLoc, &theChar, 1);
+ TTYLoc.x += CharWide;
+ }
+ else if ((theChar == 0x0b)) /* Vertical Tab */
+ {
+ TTYLoc.y += CharHigh;
+ }
+ else if ((theChar == 0x08) && (TTYLoc.x > 7)) /* backspace */
+ {
+ TTYLoc.x -= CharWide;
+ tgi_setcolor(0);
+#ifdef __ATARI__
+ tgi_bar(mul0625(TTYLoc.x),mul0375(TTYLoc.y^0x1FF),mul0625(TTYLoc.x+CharWide),mul0375(TTYLoc.y^0x1FF+CharHigh));
+#else
+ tgi_bar(scalex[TTYLoc.x],scaley[TTYLoc.y],scalex[TTYLoc.x+CharWide],scaley[TTYLoc.y+CharHigh]);
+#endif
+ tgi_setcolor(1);
+ }
+ else if (theChar == 0x0A) /* line feed */
+ TTYLoc.y -= CharHigh;
+ else if (theChar == 0x0D) /* carriage return */
+ TTYLoc.x = 0;
+
+ if (TTYLoc.x + CharWide > 511) { /* wrap at right side */
+ TTYLoc.x = 0;
+ TTYLoc.y -= CharHigh;
+ }
+
+ if (TTYLoc.y < 0) {
+ tgi_clear();
+ TTYLoc.y=495;
+ }
+
+}
+
+/**
+ * screen_done()
+ * Close down TGI
+ */
+void screen_done(void)
+{
+ tgi_done();
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * terminal.c - Terminal state functions
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <termios.h>
+#include "terminal.h"
+#include "screen.h"
+
+/**
+ * ASCII Features to return in Features
+ */
+#define ASC_ZFGT 0x01
+#define ASC_ZPCKEYS 0x02
+#define ASC_ZKERMIT 0x04
+#define ASC_ZWINDOW 0x08
+
+/**
+ * protocol.c externals
+ */
+extern CharMem CurMem;
+extern padBool TTY;
+extern padBool ModeBold;
+extern padBool Rotate;
+extern padBool Reverse;
+extern DispMode CurMode;
+extern padBool FlowControl;
+
+/**
+ * screen.c externals
+ */
+extern uint8_t CharWide;
+extern uint8_t CharHigh;
+extern padPt TTYLoc;
+
+extern uint8_t already_started;
+
+/**
+ * terminal_init()
+ * Initialize terminal state
+ */
+
+static struct termios saved_term;
+
+void exit_cleanup(void)
+{
+ tcsetattr(0, TCSADRAIN, &saved_term);
+}
+
+void cleanup(int sig)
+{
+ exit(1);
+}
+
+void terminal_init(void)
+{
+ struct termios term;
+
+ if (tcgetattr(0, &term) == 0) {
+ memcpy(&saved_term, &term, sizeof(saved_term));
+ atexit(exit_cleanup);
+ signal(SIGINT, cleanup);
+ signal(SIGQUIT, cleanup);
+ signal(SIGPIPE, cleanup);
+ term.c_lflag &= ~(ICANON | ECHO);
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 1;
+ term.c_cc[VINTR] = 0;
+ term.c_cc[VSUSP] = 0;
+ term.c_cc[VSTOP] = 0;
+ tcsetattr(0, TCSADRAIN, &term);
+ }
+ terminal_set_tty();
+}
+
+/**
+ * terminal_initial_position()
+ * Set terminal initial position after splash screen.
+ */
+void terminal_initial_position(void)
+{
+ TTYLoc.x = 0;
+ TTYLoc.y = 100; // Right under splashscreen.
+}
+
+/**
+ * terminal_set_tty(void) - Switch to TTY mode
+ */
+void terminal_set_tty(void)
+{
+ if (already_started)
+ screen_clear();
+ TTY = true;
+ ModeBold = padF;
+ Rotate = padF;
+ Reverse = padF;
+ CurMem = M0;
+ /* CurMode=ModeRewrite; */
+ CurMode = ModeWrite; /* For speed reasons. */
+ CharWide = 8;
+ CharHigh = 16;
+ TTYLoc.x = 0; // leftmost coordinate on screen
+ TTYLoc.y = 495; // Top of screen - one character height
+}
+
+/**
+ * terminal_set_plato(void) - Switch to PLATO mode
+ */
+void terminal_set_plato(void)
+{
+ TTY = false;
+ screen_clear();
+}
+
+/**
+ * terminal_get_features(void) - Inquire about terminal ASCII features
+ */
+uint8_t terminal_get_features(void)
+{
+ return ASC_ZFGT; /* This terminal can do Fine Grained Touch (FGT) */
+}
+
+/**
+ * terminal_get_type(void) - Return the appropriate terminal type
+ */
+uint8_t terminal_get_type(void)
+{
+ return 12; /* ASCII terminal type */
+}
+
+/**
+ * terminal_get_subtype(void) - Return the appropriate terminal subtype
+ */
+uint8_t terminal_get_subtype(void)
+{
+ return 1; /* ASCII terminal subtype IST-III */
+}
+
+/**
+ * terminal_get_load_file(void) - Return the appropriate terminal loadfile (should just be 0)
+ */
+uint8_t terminal_get_load_file(void)
+{
+ return 0; /* This terminal does not load its resident from the PLATO system. */
+}
+
+/**
+ * terminal_get_configuration(void) - Return the terminal configuration
+ */
+uint8_t terminal_get_configuration(void)
+{
+ return 0x40; /* Touch panel is present. */
+}
+
+/**
+ * terminal_get_char_address(void) - Return the base address of the character set.
+ */
+uint16_t terminal_get_char_address(void)
+{
+ return 0x3000; /* What the? Shouldn't this be 0x3800? */
+}
+
+/**
+ * terminal_mem_read - Read a byte of program memory.
+ * not needed for our terminal, but must
+ * be decoded.
+ */
+padByte terminal_mem_read(padWord addr)
+{
+ return (0xFF);
+}
+
+/**
+ * terminal_mem_load - Write a byte to non-character memory.
+ * not needed for our terminal, but must be decoded.
+ */
+void terminal_mem_load(padWord addr, padWord value)
+{
+ /* Not Implemented */
+}
+
+/**
+ * Mode5, 6, and 7 are basically stubbed.
+ */
+void terminal_mode_5(padWord value)
+{
+}
+
+void terminal_mode_6(padWord value)
+{
+}
+
+void terminal_mode_7(padWord value)
+{
+}
+
+/**
+ * terminal_ext_allow - External Input allowed. Not implemented.
+ */
+void terminal_ext_allow(padBool allow)
+{
+ /* Not Implemented */
+}
+
+/**
+ * terminal_set_ext_in - Set which device to get input from.
+ * Not implemented
+ */
+void terminal_set_ext_in(padWord device)
+{
+}
+
+/**
+ * terminal_set_ext_out - Set which device to send external data to.
+ * Not implemented
+ */
+void terminal_set_ext_out(padWord device)
+{
+}
+
+/**
+ * terminal_ext_in - get an external input from selected device.
+ * Not implemented.
+ */
+padByte terminal_ext_in(void)
+{
+ return 0;
+}
+
+/**
+ * terminal_ext_out - Send an external output to selected device
+ * Not implemented.
+ */
+void terminal_ext_out(padByte value)
+{
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * terminal.c - Terminal state functions
+ */
+
+#ifndef TERMINAL_H
+#define TERMINAL_H
+
+#include "protocol.h"
+
+/**
+ * terminal_init()
+ * Initialize terminal state
+ */
+void terminal_init(void);
+
+/**
+ * terminal_initial_position()
+ * Set terminal initial position after splash screen.
+ */
+void terminal_initial_position(void);
+
+/**
+ * terminal_set_tty(void) - Switch to TTY mode
+ */
+void terminal_set_tty(void);
+
+/**
+ * terminal_set_plato(void) - Switch to PLATO mode
+ */
+void terminal_set_plato(void);
+
+/**
+ * terminal_get_features(void) - Inquire about terminal ASCII features
+ */
+uint8_t terminal_get_features(void);
+
+/**
+ * terminal_get_type(void) - Return the appropriate terminal type
+ */
+uint8_t terminal_get_type(void);
+
+/**
+ * terminal_get_subtype(void) - Return the appropriate terminal subtype
+ */
+uint8_t terminal_get_subtype(void);
+
+/**
+ * terminal_get_load_file(void) - Return the appropriate terminal loadfile (should just be 0)
+ */
+uint8_t terminal_get_load_file(void);
+
+/**
+ * terminal_get_configuration(void) - Return the terminal configuration
+ */
+uint8_t terminal_get_configuration(void);
+
+/**
+ * terminal_get_char_address(void) - Return the base address of the character set.
+ */
+uint16_t terminal_get_char_address(void);
+
+/**
+ * terminal_mem_read - Read a byte of program memory.
+ * not needed for our terminal, but must
+ * be decoded.
+ */
+padByte terminal_mem_read(padWord addr);
+
+/**
+ * terminal_mem_load - Write a byte to non-character memory.
+ * not needed for our terminal, but must be decoded.
+ */
+void terminal_mem_load(padWord addr, padWord value);
+
+/**
+ * terminal_char_load - Store a character into the user definable
+ * character set.
+ */
+void terminal_char_load(padWord charnum, charData theChar);
+
+/**
+ * terminal_mode_5, 6, and 7 are basically stubbed.
+ */
+void terminal_mode_5(padWord value);
+void terminal_mode_6(padWord value);
+void terminal_mode_7(padWord value);
+
+/**
+ * terminal_ext_allow - External Input allowed. Not implemented.
+ */
+void terminal_ext_allow(padBool allow);
+
+/**
+ * terminal_set_ext_in - Set which device to get input from.
+ * Not implemented
+ */
+void terminal_set_ext_in(padWord device);
+
+/**
+ * terminal_set_ext_out - Set which device to send external data to.
+ * Not implemented
+ */
+void terminal_set_ext_out(padWord device);
+
+/**
+ * terminal_ext_in - get an external input from selected device.
+ * Not implemented.
+ */
+padByte terminal_ext_in(void);
+
+/**
+ * terminal_ext_out - Send an external output to selected device
+ * Not implemented.
+ */
+void terminal_ext_out(padByte value);
+
+#endif
--- /dev/null
+
+all: mk_scale mk_font mk_ascii_key_h
+
+mk_font: mk_font.c
+ $(CC) -o mk_font mk_font.c
+
+mk_scale: mk_scale.c
+ $(CC) -lm -o mk_scale mk_scale.c
+
+mk_ascii_key_h: mk_ascii_key_h.c
+ $(CC) -o mk_ascii_key_h mk_ascii_key_h.c
+
+clean:
+ rm -f *~ mk_scale mk_font mk_ascii_key_h
--- /dev/null
+/**
+ * Tool to create initial key map for ASCII keyboards (apple II)
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes@gmail.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void main(void)
+{
+ unsigned int i=0;
+ printf("/**\n");
+ printf(" *\n");
+ printf(" * KEY_H generated by mk_ascii_key_h.c\n");
+ printf(" */\n");
+ printf("\n\n");
+
+ printf("unsigned char key_to_pkey[]={\n");
+
+ for (i=0;i<133;++i)
+ {
+ printf(" PKEY_NOKEY, /* %03d */\n",i);
+ }
+
+ printf("};\n\n");
+
+ /* printf("unsigned char esc_key_to_pkey[]={\n"); */
+
+ /* for (i=0;i<128;++i) */
+ /* { */
+ /* printf(" PKEY_NOKEY, /\* 0x%02x *\/\n",i); */
+ /* } */
+
+ /* printf("};\n"); */
+
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ int i=0;
+ printf("/* ! Autogenerated by tools/mk_font.c */\n\n"
+ "#ifndef FONT_H\n"
+ "#define FONT_H\n\n");
+
+ printf("unsigned char font[]={\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00, /* SPACE 0x20 */\n"
+ "0x40,0x40,0x40,0x00,0x40,0x00, /* ! 0x21 */\n"
+ "0x50,0x50,0x00,0x00,0x00,0x00, /* \" 0x22 */\n"
+ "0x50,0xF8,0x50,0xF8,0x50,0x00, /* # 0x23 */\n"
+ "0x40,0xF0,0xC0,0x30,0xF0,0x20, /* $ 0x24 */\n"
+ "0x90,0x20,0x20,0x40,0x90,0x00, /* %% 0x25 */\n"
+ "0x40,0xA0,0x40,0xB0,0x50,0x00, /* & 0x26 */\n"
+ "0x20,0x40,0x00,0x00,0x00,0x00, /* ' 0x27 */\n"
+ "0x20,0x40,0x40,0x40,0x20,0x00, /* ( 0x28 */\n"
+ "0x40,0x20,0x20,0x20,0x40,0x00, /* ) 0x29 */\n"
+ "0x90,0x60,0xF0,0x60,0x90,0x00, /* * 0x2a */\n"
+ "0x20,0x20,0xF8,0x20,0x20,0x00, /* + 0x2b */\n"
+ "0x00,0x00,0x40,0x40,0x80,0x00, /* , 0x2c */\n"
+ "0x00,0x00,0xF0,0x00,0x00,0x00, /* - 0x2d */\n"
+ "0x00,0x00,0x00,0x40,0x40,0x00, /* . 0x2e */\n"
+ "0x00,0x10,0x20,0x40,0x80,0x00, /* / 0x2f */\n"
+ "0x60,0x90,0x90,0x90,0x60,0x00, /* 0 0x30 */\n"
+ "0x20,0x60,0x20,0x20,0x70,0x00, /* 1 0x31 */\n"
+ "0x60,0x90,0x20,0x40,0xF0,0x00, /* 2 0x32 */\n"
+ "0xF0,0x10,0x20,0x10,0xE0,0x00, /* 3 0x33 */\n"
+ "0x20,0x60,0xA0,0xF0,0x20,0x00, /* 4 0x34 */\n"
+ "0xE0,0x80,0xE0,0x10,0xE0,0x00, /* 5 0x35 */\n"
+ "0x60,0x80,0xE0,0x90,0xE0,0x00, /* 6 0x36 */\n"
+ "0xF0,0x10,0x20,0x40,0x40,0x00, /* 7 0x37 */\n"
+ "0x60,0x90,0x60,0x90,0x60,0x00, /* 8 0x38 */\n"
+ "0x60,0x90,0x70,0x10,0xE0,0x00, /* 9 0x39 */\n"
+ "0x00,0x40,0x00,0x40,0x00,0x00, /* : 0x3a */\n"
+ "0x00,0x40,0x00,0x40,0x80,0x00, /* ; 0x3b */\n"
+ "0x20,0x40,0x80,0x40,0x20,0x00, /* < 0x3c */\n"
+ "0x00,0xF0,0x00,0xF0,0x00,0x00, /* = 0x3d */\n"
+ "0x40,0x20,0x10,0x20,0x40,0x00, /* > 0x3e */\n"
+ "0x60,0x90,0x20,0x00,0x40,0x00, /* ? 0x3f */\n"
+ "0x60,0x90,0xB0,0x80,0x60,0x00, /* @ 0x40 */\n"
+ "0x60,0x90,0xF0,0x90,0x90,0x00, /* A 0x41 */\n"
+ "0xE0,0x90,0xE0,0x90,0xE0,0x00, /* B 0x42 */\n"
+ "0x70,0x80,0x80,0x80,0x70,0x00, /* C 0x43 */\n"
+ "0xE0,0x90,0x90,0x90,0xE0,0x00, /* D 0x44 */\n"
+ "0xF0,0x80,0xE0,0x80,0xF0,0x00, /* E 0x45 */\n"
+ "0xF0,0x80,0xE0,0x80,0x80,0x00, /* F 0x46 */\n"
+ "0x60,0x80,0x90,0x90,0x70,0x00, /* G 0x47 */\n"
+ "0x90,0x90,0xF0,0x90,0x90,0x00, /* H 0x48 */\n"
+ "0xE0,0x40,0x40,0x40,0xE0,0x00, /* I 0x49 */\n"
+ "0x10,0x10,0x10,0x90,0x60,0x00, /* J 0x4a */\n"
+ "0x90,0xA0,0xC0,0xA0,0x90,0x00, /* K 0x4b */\n"
+ "0x80,0x80,0x80,0x80,0xF0,0x00, /* L 0x4c */\n"
+ "0x88,0xD8,0xA8,0x88,0x88,0x00, /* M 0x4d */\n"
+ "0x90,0xD0,0xB0,0x90,0x90,0x00, /* N 0x4e */\n"
+ "0xF0,0x90,0x90,0x90,0xF0,0x00, /* O 0x4f */\n"
+ "0xE0,0x90,0xE0,0x80,0x80,0x00, /* P 0x50 */\n"
+ "0xF0,0x90,0x90,0xB0,0xF8,0x00, /* Q 0x51 */\n"
+ "0xE0,0x90,0xE0,0xA0,0x90,0x00, /* R 0x52 */\n"
+ "0x70,0x80,0xE0,0x10,0xE0,0x00, /* S 0x53 */\n"
+ "0xF8,0x20,0x20,0x20,0x20,0x00, /* T 0x54 */\n"
+ "0x90,0x90,0x90,0x90,0xF0,0x00, /* U 0x55 */\n"
+ "0x90,0x90,0x90,0x60,0x60,0x00, /* V 0x56 */\n"
+ "0x88,0x88,0xA8,0xD8,0x88,0x00, /* W 0x57 */\n"
+ "0x90,0x90,0x60,0x90,0x90,0x00, /* X 0x58 */\n"
+ "0x90,0x90,0xE0,0x40,0x40,0x00, /* Y 0x59 */\n"
+ "0xF0,0x10,0x20,0x40,0xF0,0x00, /* Z 0x5a */\n"
+ "0x70,0x40,0x40,0x40,0x70,0x00, /* [ 0x5b */\n"
+ "0x00,0x80,0x40,0x20,0x10,0x00, /* \\ 0x5c */ \n"
+ "0x70,0x10,0x10,0x10,0x70,0x00, /* ] 0x5d */\n"
+ "0x20,0x50,0x00,0x00,0x00,0x00, /* CIRCUMFLEX ^ 0x5e*/\n"
+ "0x00,0x00,0x00,0x00,0x00,0xF0, /* _ 0x5f */\n"
+ "0x40,0x20,0x00,0x00,0x00,0x00, /* GRAVE ACCENT ` 0x60 */\n"
+ "0x00,0xC0,0x20,0xA0,0XF0,0x00, /* a 0x61 */\n"
+ "0x80,0xE0,0x90,0x90,0xE0,0x00, /* b 0x62 */\n"
+ "0x00,0x60,0x80,0x80,0x60,0x00, /* c 0x63 */\n"
+ "0x10,0x70,0x90,0x90,0x70,0x00, /* d 0x64 */\n"
+ "0x00,0x60,0xB0,0x80,0x60,0x00, /* e 0x65 */\n"
+ "0x60,0x80,0xE0,0x80,0x80,0x00, /* f 0x66 */\n"
+ "0x00,0x60,0x90,0xF0,0x10,0x60, /* g 0x67 */\n"
+ "0x80,0xE0,0x90,0x90,0x90,0x00, /* h 0x68 */\n"
+ "0x40,0x00,0x40,0x40,0x40,0x00, /* i 0x69 */\n"
+ "0x20,0x00,0x20,0x20,0x20,0xC0, /* j 0x6a */\n"
+ "0x80,0xA0,0xC0,0xA0,0x90,0x00, /* k 0x6b */\n"
+ "0x40,0x40,0x40,0x40,0x40,0x00, /* l 0x6c */\n"
+ "0x00,0x90,0xF0,0x90,0x90,0x00, /* m 0x6d */\n"
+ "0x00,0xE0,0x90,0x90,0x90,0x00, /* n 0x6e */\n"
+ "0x00,0x60,0x90,0x90,0x60,0x00, /* o 0x6f */\n"
+ "0x00,0xE0,0x90,0x90,0xE0,0x80, /* p 0x70 */\n"
+ "0x00,0x70,0x90,0x90,0x70,0x10, /* q 0x71 */\n"
+ "0x00,0x70,0x40,0x40,0x40,0x00, /* r 0x72 */\n"
+ "0x00,0x70,0xC0,0x30,0xE0,0x00, /* s 0x73 */\n"
+ "0x40,0xE0,0x40,0x40,0x60,0x00, /* t 0x74 */\n"
+ "0x00,0x90,0x90,0x90,0x70,0x00, /* u 0x75 */\n"
+ "0x00,0x90,0xA0,0xA0,0x40,0x00, /* v 0x76 */\n"
+ "0x00,0x90,0x90,0xF0,0x90,0x00, /* w 0x77 */\n"
+ "0x00,0x90,0x60,0x60,0x90,0x00, /* x 0x78 */\n"
+ "0x00,0x90,0x90,0x70,0x10,0x60, /* y 0x79 */\n"
+ "0x00,0xF0,0x20,0x40,0xF0,0x00, /* z 0x7a */\n"
+ "0x60,0x40,0x80,0x40,0x60,0x00, /* { 0x7b */\n"
+ "0x20,0x20,0x20,0x20,0x20,0x20, /* | 0x7c */\n"
+ "0xC0,0x40,0x20,0x40,0xC0,0x00, /* } 0x7d */\n"
+ "0x00,0x00,0x68,0xB0,0x00,0x00, /* ~ 0x7e */\n"
+ "0x00,0x70,0x50,0x70,0x00,0x00, /* BOX 0x7f */\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00, /* SPACE 0xa0 */\n"
+ "0x00,0x10,0x20,0x40,0x80,0x00, /* / 0xa1 */\n"
+ "0x00,0xF0,0x00,0xF0,0x00,0xF0, /* EQUIVALENT 0xa2 */\n"
+ "0x00,0x00,0x00,0x00,0x68,0xB0, /* LOW TILDE 0xa3 */\n"
+ "0x20,0x70,0x80,0x70,0x20,0x00, /* ASSIGN 0xa4 */\n"
+ "0x20,0xF0,0x20,0xF0,0x40,0x00, /* NOT EQUAL 0xa5 */\n"
+ "0x00,0x20,0x70,0x20,0x20,0x00, /* UP ARROW 0xa6 */\n"
+ "0x00,0x00,0x20,0xF0,0x20,0x00, /* RIGHT ARROW 0xa7 */\n"
+ "0x00,0x20,0x20,0x70,0x20,0x00, /* DOWN ARROW 0xa8 */\n"
+ "0x00,0x00,0x40,0xF0,0x40,0x00, /* LEFT ARROW 0xa9 */\n"
+ "0x00,0x50,0x20,0x50,0x00,0x00, /* MULTIPLY 0xaa */\n"
+ "0xF0,0x80,0x60,0x80,0xF0,0x00, /* SIGMA 0xab */\n"
+ "0x00,0x20,0x50,0x88,0xF8,0x00, /* DELTA 0xac*/\n"
+ "0x00,0x90,0x90,0x60,0x00,0x00, /* UNION 0xad*/\n"
+ "0x00,0x60,0x90,0x90,0x00,0x00, /* INTERSECT 0xae*/\n"
+ "0x00,0x60,0x00,0x60,0x00,0x00, /* DIVIDE 0xaf */\n"
+ "0x00,0x50,0xA0,0x70,0x00,0x00, /* ALPHA 0xb0 */\n"
+ "0x20,0x50,0xA0,0x90,0xE0,0x80, /* BETA 0xb1 */\n"
+ "0x20,0x40,0x20,0x50,0x70,0x00, /* DELTA 0xb2 */\n"
+ "0x80,0x40,0x20,0x50,0x90,0x00, /* LAMBDA 0xb3 */\n"
+ "0x00,0x00,0x50,0x50,0x60,0x80, /* MU 0xb4 */\n"
+ "0x08,0x78,0xD0,0x50,0x50,0x00, /* PI 0xb5 */\n"
+ "0x00,0x20,0x50,0x50,0xA0,0x80, /* RHO 0xb6 */\n"
+ "0x30,0x40,0xA0,0xA0,0x40,0x00, /* SIGMA 0xb7 */\n"
+ "0x00,0x00,0x90,0xB0,0x60,0x00, /* OMEGA 0xb8 */\n"
+ "0x20,0x40,0x80,0x40,0x20,0xE0, /* LESS THAN OR EQUAL 0xb9 */\n"
+ "0x80,0x40,0x20,0x40,0x80,0xE0, /* GREATER THAN OR EQUAL 0xba */\n"
+ "0x20,0x50,0x70,0x50,0x20,0x00, /* THETA 0xbb */\n"
+ "0x30,0x60,0xA0,0x60,0x30,0x00, /* l-embed 0xbc */\n"
+ "0x00,0x60,0x90,0x60,0x00,0x00, /* DEGREE 0xbd */\n"
+ "0xC0,0x60,0x50,0x60,0xC0,0x00, /* r-embed 0xbe */\n"
+ "0xC0,0xA0,0x50,0x50,0xA0,0xC0, /* ANSWER ARROW 0xbf */\n"
+ "0xF8,0x20,0x40,0x40,0x20,0xF8, /* COPYRIGHT 0xc0 */\n"
+ "0x50,0x00,0x00,0x00,0x00,0x00, /* DIERESIS 0xc1 */\n"
+ "0x00,0x70,0x50,0x70,0x00,0x00, /* BOX 0xc2 */\n"
+ "0x00,0x00,0x20,0x00,0x00,0x00, /* INTERPUNCT 0xc3 */\n"
+ "0x20,0x70,0xF8,0x70,0x20,0x00, /* DIAMOND 0xc4 */\n"
+ "0x00,0x50,0x20,0x50,0x00,0x00, /* MULTIPLY 0xc5 */\n"
+ "0x10,0x20,0x00,0x00,0x00,0x00, /* ACUTE ACCENT 0xc6 */\n"
+ "0x00,0x00,0x00,0x08,0x10,0x00, /* CEDILLA 0xc7 */\n"
+ "0x10,0x20,0x00,0x00,0x00,0x00, /* HACEK 0xc8 */\n"
+ "0x20,0x70,0xF8,0x70,0x20,0x00, /* DIAMOND 0xc9 */\n"
+ "0x20,0x20,0x20,0x20,0x20,0x20, /* | 0xca */\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00,\n"
+ "0x00,0x00,0x00,0x00,0x00,0x00\n"
+ "};\n\n");
+
+
+ printf("unsigned int fontptr[]={\n");
+ for (i=0;i<160;i++) {
+ printf("%d,",i*12);
+ if (i % 8 == 7 )
+ printf("\n");
+ }
+ printf("};\n\n"
+ "#endif /* FONT_H */\n");
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+int main(int argc, char *argv[])
+{
+ int i=0;
+ double sx;
+ double sy;
+ double zx;
+ double zy;
+ int rx;
+ int ry;
+
+ if (argc < 3) {
+ fprintf(stderr,"usage: mk_scale x y\n");
+ return 1;
+ }
+
+ sx = strtod(argv[1],NULL) / 512;
+ sy = strtod(argv[2],NULL) / 512;
+ rx = atoi(argv[1])-1;
+ ry = atoi(argv[2])-1;
+ zx = 512 / strtod(argv[1],NULL);
+ zy = 512 / strtod(argv[2],NULL);
+
+ printf(
+ "/* ! Autogenerated by tools/mk_scale.c */\n\n"
+ "#ifndef SCALE_H\n"
+ "#define SCALE_H\n\n"
+ "unsigned short scalex[]={\n");
+
+ for (i=0;i<512;i++) {
+ printf("%d,",(int)ceil(i*sx));
+ if( i % 8 == 7 )
+ printf("\n");
+ }
+ printf("};\n\n");
+
+ printf("unsigned short scaley[]={\n");
+ for (i=511;i>=0;i-=1) {
+ printf("%d,",(int)ceil(i*sy));
+ if (i % 8 == 0 )
+ printf("\n");
+ }
+ printf("};\n\n");
+
+ printf("unsigned short scaletx[]={\n");
+
+ for (i=0;i<rx;i++) {
+ printf("%d,",(int)ceil(i*zx));
+ if( i % 8 == 7 )
+ printf("\n");
+ }
+ printf("};\n\n");
+
+ printf("unsigned short scalety[]={\n");
+ for (i=ry;i>=0;i-=1) {
+ printf("%d,",(int)ceil(i*zy));
+ if (i % 8 == 0 )
+ printf("\n");
+ }
+ printf("};\n\n");
+
+ printf("#endif /* scale_h */\n");
+
+ return 0;
+}
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * touch.c - Touchscreen functions
+ */
+
+#ifndef TOUCH_H
+#define TOUCH_H
+
+#include "protocol.h"
+
+/**
+ * touch_init() - Set up touch screen
+ */
+void touch_init(void);
+
+/**
+ * touch_main() - Main loop for touch screen
+ */
+void touch_main(void);
+
+/**
+ * touch_allow - Set whether touchpanel is active or not.
+ */
+void touch_allow(padBool allow);
+
+/**
+ * handle_mouse - Process mouse events and turn into scaled touch events
+ */
+void handle_mouse(void);
+
+/**
+ * touch_hide() - hide the mouse cursor
+ */
+void touch_hide(void);
+
+/**
+ * touch_done() - Stop the mouse driver
+ */
+void touch_done(void);
+
+#endif /* TOUCH_H */
--- /dev/null
+/**
+ * PLATOTerm64 - A PLATO Terminal for the Commodore 64
+ * Based on Steve Peltz's PAD
+ *
+ * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
+ *
+ * touch.c - Touchscreen functions
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include "touch.h"
+
+static padBool TouchActive;
+
+static uint16_t screen_w;
+static uint16_t screen_h;
+static uint8_t mouse_present=false;
+static uint8_t mou_res=0;
+
+extern uint16_t scaletx[];
+extern uint16_t scalety[];
+
+/**
+ * touch_init() - Set up touch screen
+ */
+void touch_init(void)
+{
+}
+
+/**
+ * touch_allow - Set whether touchpanel is active or not.
+ */
+void touch_allow(padBool allow)
+{
+ TouchActive=allow;
+}
+
+/**
+ * touch_main - Process mouse events and turn into scaled touch events
+ */
+void touch_main(void)
+{
+}
+
+/**
+ * touch_hide() - hide the mouse cursor
+ */
+void touch_hide(void)
+{
+}
+
+/**
+ * touch_done() - Stop the mouse driver
+ */
+void touch_done(void)
+{
+}