From 69aac09b6ca4cd73b5ce09d5b10dd77f29166ce9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 13 Aug 2018 00:38:13 +0100 Subject: [PATCH] trs80m1: add initial test UDG support Needs emulator work to test properly --- Kernel/platform-trs80m1/devgfx.c | 148 ++++++++++++++++++++++++++++++ Kernel/platform-trs80m1/discard.c | 28 +++++- Kernel/platform-trs80m1/trs80.h | 8 ++ 3 files changed, 182 insertions(+), 2 deletions(-) diff --git a/Kernel/platform-trs80m1/devgfx.c b/Kernel/platform-trs80m1/devgfx.c index 4a3621f5..7f958562 100644 --- a/Kernel/platform-trs80m1/devgfx.c +++ b/Kernel/platform-trs80m1/devgfx.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -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; +} diff --git a/Kernel/platform-trs80m1/discard.c b/Kernel/platform-trs80m1/discard.c index 6f54b650..11e4d67d 100644 --- a/Kernel/platform-trs80m1/discard.c +++ b/Kernel/platform-trs80m1/discard.c @@ -6,6 +6,7 @@ #include "devfd3.h" #include "devgfx.h" #include +#include #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 + * 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; } - diff --git a/Kernel/platform-trs80m1/trs80.h b/Kernel/platform-trs80m1/trs80.h index 32003102..f6d4eb77 100644 --- a/Kernel/platform-trs80m1/trs80.h +++ b/Kernel/platform-trs80m1/trs80.h @@ -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 * -- 2.34.1