trs80m1: add initial test UDG support
authorAlan Cox <alan@linux.intel.com>
Sun, 12 Aug 2018 23:38:13 +0000 (00:38 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 12 Aug 2018 23:38:13 +0000 (00:38 +0100)
Needs emulator work to test properly

Kernel/platform-trs80m1/devgfx.c
Kernel/platform-trs80m1/discard.c
Kernel/platform-trs80m1/trs80.h

index 4a3621f..7f95856 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <kernel.h>
 #include <kdata.h>
+#include <tty.h>
 #include <vt.h>
 #include <graphics.h>
 #include <devgfx.h>
@@ -22,6 +23,8 @@ __sfr __at 0xEC le18_data;
 __sfr __at 0xEF le18_ctrl;
 __sfr __at 0xFF ioctrl;
 
+uint8_t trs80_udg;
+
 uint8_t has_hrg1;
 uint8_t has_chroma;    /* and thus 2 joystick ports */
 uint8_t video_mode;
@@ -161,11 +164,16 @@ static struct videomap trsmap[6] = {
 
 static uint8_t displaymap[4] = {0, 0, 0, 0};
 
+static int8_t udg_ioctl(uarg_t arg, char *ptr);
+
 /* TODO: Arbitrate graphics between tty 1 and tty 2 */
 int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
 {
   uint8_t m;
 
+  if (minor <= 2 && (arg == VTFONTINFO || arg == VTSETFONT || arg == VTSETUDG))
+    return udg_ioctl(arg, ptr);
+
   if (minor > 2 || (arg >> 8 != 0x03))
     return vt_ioctl(minor, arg, ptr);
 
@@ -253,3 +261,143 @@ void gfx_init(void)
     has_chroma = 1;
   }
 }
+
+/*
+ *     UDG drivers
+ *
+ *     We don't currently address UDG fitted without lower case. That gets
+ *     deeply weird because you get disjoint ranges with one bit magically
+ *     invented by logic. For the UDG only ones we just halve the range, but
+ *     for the PCG80 what about full font ?
+ *
+ *     (The Tandy (Microfirma) one requires lowercase is fitted according
+ *     to the manual)
+ *
+ *     One other corner case to consider is that if you have no lower case
+ *     we ought to requisition the UDG and load a font into it then use
+ *     128-159 for lower case.
+ */
+
+static struct fontinfo fonti[4] = {
+  { 0, },
+  { 0, 255, 0, 255, FONT_INFO_6X12P16 },
+  { 128, 191, 128, 191, FONT_INFO_6X12P16 },
+  { 128, 255, 128, 255, FONT_INFO_6X12P16 }
+};
+
+__sfr __at 130 trshg_nowrite;
+__sfr __at 140 trshg_write;
+__sfr __at 150 trshg_gfxoff;
+__sfr __at 155 trshg_gfxon;
+__sfr __at 0xFE pcg80;
+__sfr __at 0xFF p80gfx;
+
+static uint8_t old_pcg80;
+static uint8_t old_p80gfx;
+static uint8_t udgflag;                /* So we know what fonts are loaded */
+#define SOFTFONT_UDG   1
+#define SOFTFONT_ALL   2
+
+static void load_char_pcg80(uint8_t ch, uint8_t *cdata)
+{
+  uint8_t bank = ch >> 6;
+  uint8_t *addr = (uint8_t *)0x3C00 + ((ch & 0x3F) << 4);
+  uint8_t i;
+
+  pcg80 = old_pcg80 | 0x60 | bank;     /* Programming mode on */
+
+  for (i = 0; i < 16; i++)
+    *addr++ = *cdata++ << 1 | 0x80;
+  pcg80 = old_pcg80;
+}
+
+static void load_char_80gfx(uint8_t ch, uint8_t *cdata)
+{
+  uint8_t *addr = (uint8_t *)0x3C00 + ((ch & 0x3F) << 4);
+  uint8_t i;
+
+  p80gfx = old_p80gfx | 0x60;
+  for (i = 0; i < 16; i++)
+    *addr++ = *cdata++ << 1 | 0x80;
+  p80gfx = old_p80gfx;
+}
+
+static void load_char_trs(uint8_t ch, uint8_t *cdata)
+{
+  uint8_t *addr = (uint8_t *)0x3C00 + ((ch & 0x3F) << 4);
+  uint8_t i;
+
+  trshg_write = 1;
+  for (i = 0; i < 16; i++)
+    *addr++ = *cdata++ << 1 | 0x80;
+  trshg_nowrite = 1;
+}
+
+void (*load_char[4])(uint8_t, uint8_t *) = {
+  NULL,
+  load_char_pcg80,
+  load_char_80gfx,
+  load_char_trs,
+};
+
+static void udg_config(void)
+{
+  switch(trs80_udg) {
+  case UDG_PCG80:
+    if (udgflag & SOFTFONT_UDG)
+      old_pcg80 |= 0x80;       /* 128-255 soft font */
+    if (udgflag & SOFTFONT_ALL)
+      old_pcg80 |= 0x88;
+    pcg80 = old_pcg80 | 0x20;
+    break;
+  case UDG_80GFX:
+    if (udgflag & SOFTFONT_UDG)
+      old_p80gfx |= 0x80;
+    p80gfx = old_p80gfx | 0x20;
+    break;
+  case UDG_MICROFIRMA:
+    if (udgflag & SOFTFONT_UDG)
+      trshg_gfxon = 1;
+    break;
+  }
+}
+
+static int8_t udg_ioctl(uarg_t arg, char *ptr)
+{
+  uint8_t base = fonti[trs80_udg].udg_low;
+  uint8_t limit = fonti[trs80_udg].udg_high;
+  int i;
+
+  /* Not supported */
+  if (trs80_udg == UDG_NONE) {
+    udata.u_error = EOPNOTSUPP;
+    return -1;
+  }
+  /* No lower case available */
+  if (!video_lower)
+    limit = 191;
+
+  switch(arg) {
+  case VTFONTINFO:
+    return uput(fonti + trs80_udg, ptr, sizeof(struct fontinfo));
+  case VTSETFONT:
+    base = fonti[trs80_udg].font_low;
+    limit = fonti[trs80_udg].font_high;
+    /* Fall through */
+  case VTSETUDG:
+    for (i = base; i <= limit; i++) {
+      uint8_t c[16];
+      if (uget(c, ptr, 16) == -1)
+        return -1;
+      ptr += 16;
+      load_char[trs80_udg](i, c);
+    }
+    if (arg == VTSETUDG)
+      udgflag |= SOFTFONT_UDG;
+    else
+      udgflag |= SOFTFONT_ALL;
+    udg_config();
+    return 0;
+  }
+  return -1;
+}
index 6f54b65..11e4d67 100644 (file)
@@ -6,6 +6,7 @@
 #include "devfd3.h"
 #include "devgfx.h"
 #include <devstringy.h>
+#include <devide.h>
 #include "trs80.h"
 
 void device_init(void)
@@ -65,9 +66,32 @@ void pagemap_init(void)
   pagemap_init_supermem();
 }
 
+/* string.c
+ * Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+static int strcmp(const char *d, const char *s)
+{
+       register char *s1 = (char *) d, *s2 = (char *) s, c1, c2;
+
+       while ((c1 = *s1++) == (c2 = *s2++) && c1);
+       return c1 - c2;
+}
+
 uint8_t platform_param(char *p)
 {
-    used(p);
+    if (strcmp(p, "pcg80") == 0) {
+     trs80_udg = UDG_PCG80;
+     return 1;
+    }
+    if (strcmp(p, "80gfx") == 0) {
+     trs80_udg = UDG_80GFX;
+     return 1;
+    }
+    if (strcmp(p, "micro") == 0) {
+     trs80_udg = UDG_MICROFIRMA;
+     return 1;
+    }
     return 0;
 }
-
index 3200310..f6d4eb7 100644 (file)
@@ -9,6 +9,14 @@ extern uint8_t trs80_mapper;
 #define MAP_SUPERMEM   0       /* Alpha Supermem and compatibles */
 #define MAP_SELECTOR   1       /* Selector */
 
+extern uint8_t trs80_udg;      /* User defined graphics module */
+#define UDG_NONE       0
+#define UDG_PCG80      1       /* Orcim PCG80 */
+#define UDG_80GFX      2       /* Programma 80-Grafix */
+#define UDG_MICROFIRMA 3       /* External box option for UK TRS80 Model 1 */
+
+extern uint8_t video_lower;    /* Lowercase available */
+
 /*
  *     Differences versus model 1
  *