From 65a9d17674da8a26e6b43a8a0072d444a9fceeee Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 28 Oct 2017 16:03:44 +0100 Subject: [PATCH] Toshiba T3100e improvements : * Enables [Fn]+key combinations (using right-Ctrl or right-Alt as [Fn]). In particular: * Implements switching the built-in display adapter between the 'internal' plasma display ([Fn]+[Home]) and an 'external' CGA monitor ([Fn]+[End]) * Allows the video font to be toggled between thin and thick ([Fn]+[Right arrow]). * Implements the four hardware fonts of the original, selectable in BIOS setup. * Implements CRTC register 12h (attribute mapping and display type) Patch from John Elliott --- src/keyboard_at.c | 42 +++++++ src/t3100e.c | 19 ++- src/t3100e.h | 2 + src/vid_cga.c | 8 +- src/vid_cga.h | 1 + src/vid_t3100e.c | 288 ++++++++++++++++++++++++++++++++-------------- src/vid_t3100e.h | 1 + src/video.c | 48 +++++--- src/video.h | 4 +- 9 files changed, 297 insertions(+), 116 deletions(-) create mode 100644 src/t3100e.h diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 9fd4050..4866c89 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -5,6 +5,7 @@ #include "pit.h" #include "sound.h" #include "sound_speaker.h" +#include "t3100e.h" #include "timer.h" #include "x86.h" @@ -138,6 +139,29 @@ void keyboard_at_adddata_keyboard(uint8_t val) if (key_1c == 4) output = 3; }*/ + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if (romset == ROM_T3100E && (pcem_key[0xb8] || pcem_key[0x9d])) + { + switch (val) + { + case 0x4f: t3100e_notify_set(0x01); break; /* End */ + case 0x50: t3100e_notify_set(0x02); break; /* Down */ + case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ + case 0x52: t3100e_notify_set(0x04); break; /* Ins */ + case 0x53: t3100e_notify_set(0x05); break; /* Del */ + case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ + case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ + case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ + case 0x47: t3100e_notify_set(0x09); break; /* Home */ + case 0x48: t3100e_notify_set(0x0A); break; /* Up */ + case 0x49: t3100e_notify_set(0x0B); break; /* PgUp */ + case 0x4A: t3100e_notify_set(0x0C); break; /* Keypad -*/ + case 0x4B: t3100e_notify_set(0x0D); break; /* Left */ + case 0x4C: t3100e_notify_set(0x0E); break; /* KP 5 */ + case 0x4D: t3100e_notify_set(0x0F); break; /* Right */ + } + } key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; // pclog("keyboard_at : %02X added to key queue\n", val); @@ -397,6 +421,24 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) } else keyboard_at_adddata(0x00); break; + + /* For the T3100e, 0xB0 is 'turbo on' and 0xB1 is + * 'turbo off' */ + + case 0xb2: /* T3100e: Select external display */ + if (romset == ROM_T3100E) + t3100e_display_set(0x00); + break; + + case 0xb3: /* T3100e: Select internal display */ + if (romset == ROM_T3100E) + t3100e_display_set(0x01); + break; + + case 0xbc: /* T3100e: Reset Fn+Key notification */ + if (romset == ROM_T3100E) + t3100e_notify_set(0x00); + break; case 0xc0: /*Read input port*/ keyboard_at_adddata(keyboard_at.input_port | 4); diff --git a/src/t3100e.c b/src/t3100e.c index 4f03b83..ebfbb8e 100644 --- a/src/t3100e.c +++ b/src/t3100e.c @@ -5,6 +5,7 @@ #include "mouse.h" #include "mem.h" #include "device.h" +#include "t3100e.h" #include "vid_t3100e.h" /* The Toshiba 3100e is a 286-based portable. @@ -156,7 +157,7 @@ struct t3100e_ems_regs uint8_t upper_pages; /* Pages of EMS available from upper RAM */ uint8_t upper_is_ems; /* Upper RAM is EMS? */ mem_mapping_t upper_mapping; - + uint8_t notify; } t3100e_ems; void t3100e_ems_out(uint16_t addr, uint8_t val, void *p); @@ -335,6 +336,7 @@ void t3100e_map_ram(uint8_t val) mem_size * 1024, upper_len); mem_mapping_enable(&t3100e_ems.upper_mapping); + mem_mapping_set_exec(&t3100e_ems.upper_mapping, ram + t3100e_ems.upper_base); } else { @@ -351,13 +353,21 @@ void t3100e_map_ram(uint8_t val) } +void t3100e_notify_set(uint8_t value) +{ + t3100e_ems.notify = value; +} + + uint8_t t3100e_sys_in(uint16_t addr, void *p) { -// struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; + struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; - /* XXX Not implemented. Seems to return 0x0C on real hardware */ + /* The low 4 bits always seem to be 0x0C. The high 4 are a + * notification sent by the keyboard controller when it detects + * an [Fn] key combination */ if (t3100e_log) pclog("IN 0x8084\n"); - return 0x0C; + return 0x0C | (regs->notify << 4); } @@ -411,6 +421,7 @@ void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) if (t3100e_log) pclog("Enabling EMS RAM at %05x\n", page_to_addr(pg)); mem_mapping_enable(®s->mapping[pg]); + mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]); } else { diff --git a/src/t3100e.h b/src/t3100e.h new file mode 100644 index 0000000..d0ada48 --- /dev/null +++ b/src/t3100e.h @@ -0,0 +1,2 @@ +void t3100e_notify_set(uint8_t value); +void t3100e_display_set(uint8_t value); diff --git a/src/vid_cga.c b/src/vid_cga.c index 59aa6ef..eb1e8cf 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -187,12 +187,12 @@ void cga_poll(void *p) if (drawcursor) { for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[cga->displine])[(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff; + ((uint32_t *)buffer32->line[cga->displine])[(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff; } else { for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[cga->displine])[(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + ((uint32_t *)buffer32->line[cga->displine])[(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } cga->ma++; } @@ -221,13 +221,13 @@ void cga_poll(void *p) { for (c = 0; c < 8; c++) ((uint32_t *)buffer32->line[cga->displine])[(x << 4)+(c << 1) + 8] = - ((uint32_t *)buffer32->line[cga->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff; + ((uint32_t *)buffer32->line[cga->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff; } else { for (c = 0; c < 8; c++) ((uint32_t *)buffer32->line[cga->displine])[(x << 4) + (c << 1) + 8] = - ((uint32_t *)buffer32->line[cga->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + ((uint32_t *)buffer32->line[cga->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } } diff --git a/src/vid_cga.h b/src/vid_cga.h index db4355b..7594bf1 100644 --- a/src/vid_cga.h +++ b/src/vid_cga.h @@ -9,6 +9,7 @@ typedef struct cga_t uint8_t cgamode, cgacol; + int fontbase; int linepos, displine; int sc, vc; int cgadispon; diff --git a/src/vid_t3100e.c b/src/vid_t3100e.c index 94078e0..fcd1227 100644 --- a/src/vid_t3100e.c +++ b/src/vid_t3100e.c @@ -7,6 +7,7 @@ #include "mem.h" #include "timer.h" #include "video.h" +#include "vid_cga.h" #include "vid_t3100e.h" #define T3100E_XSIZE 640 @@ -29,6 +30,7 @@ void updatewindowsize(int x, int y); /* Mapping of attributes to colours */ static uint32_t amber, black; +static uint8_t boldcols[256]; /* Which attributes use the bold font */ static uint32_t blinkcols[256][2]; static uint32_t normcols[256][2]; @@ -40,34 +42,37 @@ static uint32_t normcols[256][2]; * Bits 0,1: Font set (not currently implemented) */ static uint8_t st_video_options; +static uint8_t st_display_internal = -1; void t3100e_video_options_set(uint8_t options) { st_video_options = options; } +void t3100e_display_set(uint8_t internal) +{ + st_display_internal = internal; +} + typedef struct t3100e_t { mem_mapping_t mapping; - uint8_t cga_crtc[32]; /* The CRTC as the host PC sees it. Most - * of the registers are ignored by the plasma - * display. */ - int cga_crtcreg; /* Current CRTC register */ - uint8_t cga_ctrl; /* CGA control register */ - uint8_t cga_colour; /* CGA colour register */ - uint8_t cga_stat; /* CGA status (IN 0x3DA) */ + cga_t cga; /* The CGA is used for the external + * display; most of its registers are + * ignored by the plasma display. */ int font; /* Current font, 0-3 */ int enabled; /* Hardware enabled, 0 or 1 */ + int internal; /* Using internal display? */ + uint8_t attrmap; /* Attribute mapping register */ int dispontime, dispofftime; - int vidtime; int linepos, displine; int vc; - int dispon, blink; + int dispon; int vsynctime; uint8_t video_options; @@ -78,6 +83,7 @@ typedef struct t3100e_t void t3100e_recalctimings(t3100e_t *t3100e); void t3100e_write(uint32_t addr, uint8_t val, void *p); uint8_t t3100e_read(uint32_t addr, void *p); +void t3100e_recalcattrs(t3100e_t *t3100e); void t3100e_out(uint16_t addr, uint8_t val, void *p) @@ -87,23 +93,31 @@ void t3100e_out(uint16_t addr, uint8_t val, void *p) { /* Emulated CRTC, register select */ case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - t3100e->cga_crtcreg = val & 31; + cga_out(addr, val, &t3100e->cga); break; /* Emulated CRTC, value */ case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - t3100e->cga_crtc[t3100e->cga_crtcreg] = val; + /* Register 0x12 controls the attribute mappings for the + * plasma screen. */ + if (t3100e->cga.crtcreg == 0x12) + { + t3100e->attrmap = val; + t3100e_recalcattrs(t3100e); + return; + } + cga_out(addr, val, &t3100e->cga); t3100e_recalctimings(t3100e); return; /* CGA control register */ case 0x3D8: - t3100e->cga_ctrl = val; + cga_out(addr, val, &t3100e->cga); return; /* CGA colour register */ case 0x3D9: - t3100e->cga_colour = val; + cga_out(addr, val, &t3100e->cga); return; } } @@ -111,20 +125,20 @@ void t3100e_out(uint16_t addr, uint8_t val, void *p) uint8_t t3100e_in(uint16_t addr, void *p) { t3100e_t *t3100e = (t3100e_t *)p; + uint8_t val; + switch (addr) { - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - return t3100e->cga_crtcreg; - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - return t3100e->cga_crtc[t3100e->cga_crtcreg]; - case 0x3d8: - return t3100e->cga_ctrl; - case 0x3d9: - return t3100e->cga_colour; - case 0x3da: - return t3100e->cga_stat; - } - return 0xff; + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + if (t3100e->cga.crtcreg == 0x12) + { + val = t3100e->attrmap & 0x0F; + if (t3100e->internal) val |= 0x30; /* Plasma / CRT */ + return val; + } + } + + return cga_in(addr, &t3100e->cga); } @@ -159,6 +173,11 @@ void t3100e_recalctimings(t3100e_t *t3100e) double disptime; double _dispontime, _dispofftime; + if (!t3100e->internal) + { + cga_recalctimings(&t3100e->cga); + return; + } disptime = 651; _dispontime = 640; _dispofftime = disptime - _dispontime; @@ -179,42 +198,39 @@ void t3100e_text_row80(t3100e_t *t3100e) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (t3100e->cga_crtc[13] | (t3100e->cga_crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga_crtc[15] | (t3100e->cga_crtc[14] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; sc = (t3100e->displine) & 15; addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; ma += (t3100e->displine >> 4) * 80; - if ((t3100e->cga_crtc[10] & 0x60) == 0x20) + if ((t3100e->cga.crtc[10] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t3100e->cga_crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga_crtc[11] & 0x0F)*2 >= sc); + cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && + ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); } for (x = 0; x < 80; x++) { chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; drawcursor = ((ma == ca) && cursorline && - (t3100e->cga_ctrl & 8) && (t3100e->blink & 16)); + (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - blink = ((t3100e->blink & 16) && (t3100e->cga_ctrl & 0x20) && + blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - /* XXX We should also be taking account of bits 0,1 of - * options to select one of the four ROM character sets; - * but these are not currently emulated. */ - if (t3100e->video_options & 4) - bold = (attr & 8) ? chr + 256 : chr; + bold = boldcols[attr] ? chr + 256 : chr; else - bold = (attr & 8) ? chr : chr + 256; + bold = boldcols[attr] ? chr : chr + 256; + bold += 512 * (t3100e->video_options & 3); - if (t3100e->cga_ctrl & 0x20) /* Blink */ + if (t3100e->cga.cgamode & 0x20) /* Blink */ { cols[1] = blinkcols[attr][1]; cols[0] = blinkcols[attr][0]; @@ -253,37 +269,38 @@ void t3100e_text_row40(t3100e_t *t3100e) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (t3100e->cga_crtc[13] | (t3100e->cga_crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga_crtc[15] | (t3100e->cga_crtc[14] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; sc = (t3100e->displine) & 15; addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; ma += (t3100e->displine >> 4) * 40; - if ((t3100e->cga_crtc[10] & 0x60) == 0x20) + if ((t3100e->cga.crtc[10] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t3100e->cga_crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga_crtc[11] & 0x0F)*2 >= sc); + cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && + ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); } for (x = 0; x < 40; x++) { chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; drawcursor = ((ma == ca) && cursorline && - (t3100e->cga_ctrl & 8) && (t3100e->blink & 16)); + (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - blink = ((t3100e->blink & 16) && (t3100e->cga_ctrl & 0x20) && + blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); if (t3100e->video_options & 4) - bold = (attr & 8) ? chr + 256 : chr; - else bold = (attr & 8) ? chr : chr + 256; + bold = boldcols[attr] ? chr + 256 : chr; + else bold = boldcols[attr] ? chr : chr + 256; + bold += 512 * (t3100e->video_options & 3); - if (t3100e->cga_ctrl & 0x20) /* Blink */ + if (t3100e->cga.cgamode & 0x20) /* Blink */ { cols[1] = blinkcols[attr][1]; cols[0] = blinkcols[attr][0]; @@ -324,12 +341,12 @@ void t3100e_cgaline6(t3100e_t *t3100e) uint8_t dat; uint32_t ink = 0; uint16_t addr; - uint32_t fg = (t3100e->cga_colour & 0x0F) ? amber : black; + uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; uint32_t bg = black; - uint16_t ma = (t3100e->cga_crtc[13] | (t3100e->cga_crtc[12] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - if (t3100e->cga_crtc[9] == 3) /* 640*400 */ + if (t3100e->cga.crtc[9] == 3) /* 640*400 */ { addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + @@ -350,7 +367,7 @@ void t3100e_cgaline6(t3100e_t *t3100e) for (c = 0; c < 8; c++) { ink = (dat & 0x80) ? fg : bg; - if (!(t3100e->cga_ctrl & 8)) ink = black; + if (!(t3100e->cga.cgamode & 8)) ink = black; ((uint32_t *)buffer32->line[t3100e->displine])[x*8+c] = ink; dat = dat << 1; } @@ -367,8 +384,8 @@ void t3100e_cgaline4(t3100e_t *t3100e) uint32_t ink0, ink1; uint16_t addr; - uint16_t ma = (t3100e->cga_crtc[13] | (t3100e->cga_crtc[12] << 8)) & 0x7fff; - if (t3100e->cga_crtc[9] == 3) /* 320*400 undocumented */ + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */ { addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + @@ -389,7 +406,7 @@ void t3100e_cgaline4(t3100e_t *t3100e) for (c = 0; c < 4; c++) { pattern = (dat & 0xC0) >> 6; - if (!(t3100e->cga_ctrl & 8)) pattern = 0; + if (!(t3100e->cga.cgamode & 8)) pattern = 0; switch (pattern & 3) { @@ -439,12 +456,28 @@ void t3100e_poll(void *p) mem_mapping_disable(&t3100e->mapping); else mem_mapping_enable(&t3100e->mapping); + /* Set the font used for the external display */ + t3100e->cga.fontbase = (512 * (t3100e->video_options & 3)) + + ((t3100e->video_options & 4) ? 256 : 0); + } + /* Switch between internal plasma and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != t3100e->internal) + { + t3100e->internal = st_display_internal; + t3100e_recalctimings(t3100e); + } + if (!t3100e->internal) + { + cga_poll(&t3100e->cga); + return; + } + if (!t3100e->linepos) { - t3100e->vidtime += t3100e->dispofftime; - t3100e->cga_stat |= 1; + t3100e->cga.vidtime += t3100e->dispofftime; + t3100e->cga.cgastat |= 1; t3100e->linepos = 1; if (t3100e->dispon) { @@ -454,14 +487,14 @@ void t3100e_poll(void *p) } /* Graphics */ - if (t3100e->cga_ctrl & 0x02) + if (t3100e->cga.cgamode & 0x02) { - if (t3100e->cga_ctrl & 0x10) + if (t3100e->cga.cgamode & 0x10) t3100e_cgaline6(t3100e); else t3100e_cgaline4(t3100e); } else - if (t3100e->cga_ctrl & 0x01) /* High-res text */ + if (t3100e->cga.cgamode & 0x01) /* High-res text */ { t3100e_text_row80(t3100e); } @@ -474,13 +507,13 @@ void t3100e_poll(void *p) /* Hardcode a fixed refresh rate and VSYNC timing */ if (t3100e->displine == 400) /* Start of VSYNC */ { - t3100e->cga_stat |= 8; + t3100e->cga.cgastat |= 8; t3100e->dispon = 0; } if (t3100e->displine == 416) /* End of VSYNC */ { t3100e->displine = 0; - t3100e->cga_stat &= ~8; + t3100e->cga.cgastat &= ~8; t3100e->dispon = 1; } } @@ -488,9 +521,9 @@ void t3100e_poll(void *p) { if (t3100e->dispon) { - t3100e->cga_stat &= ~1; + t3100e->cga.cgastat &= ~1; } - t3100e->vidtime += t3100e->dispontime; + t3100e->cga.vidtime += t3100e->dispontime; t3100e->linepos = 0; if (t3100e->displine == 400) @@ -511,55 +544,109 @@ void t3100e_poll(void *p) video_res_x = T3100E_XSIZE; video_res_y = T3100E_YSIZE; - if (t3100e->cga_ctrl & 0x02) + if (t3100e->cga.cgamode & 0x02) { - if (t3100e->cga_ctrl & 0x10) + if (t3100e->cga.cgamode & 0x10) video_bpp = 1; else video_bpp = 2; } else video_bpp = 0; - t3100e->blink++; + t3100e->cga.cgablink++; } } } -void *t3100e_init() + + +void t3100e_recalcattrs(t3100e_t *t3100e) { - int n; - t3100e_t *t3100e = malloc(sizeof(t3100e_t)); - memset(t3100e, 0, sizeof(t3100e_t)); + int n; - /* 32k video RAM */ - t3100e->vram = malloc(0x8000); - - timer_add(t3100e_poll, &t3100e->vidtime, TIMER_ALWAYS_ENABLED, t3100e); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e); + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold */ /* Set up colours */ amber = makecol(0xf7, 0x7C, 0x34); black = makecol(0x17, 0x0C, 0x00); /* Initialise the attribute mapping. Start by defaulting everything - * to black on amber */ + * to black on amber, and with bold set by bit 3 */ for (n = 0; n < 256; n++) { + boldcols[n] = (n & 8) != 0; blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; } - /* Except 00-0F and 80-8F which are amber on black */ - for (n = 0; n < 16; n++) + + /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always black on + * amber. */ + for (n = 0x11; n <= 0xFF; n++) + { + if ((n & 7) == 0) continue; + if (t3100e->attrmap & 4) /* Inverse */ + { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + blinkcols[n+128][0] = normcols[n+128][0] = amber; + blinkcols[n+128][1] = normcols[n+128][1] = black; + } + else /* Normal */ + { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n+128][0] = normcols[n+128][0] = black; + blinkcols[n+128][1] = normcols[n+128][1] = amber; + } + if (t3100e->attrmap & 8) boldcols[n] = 1; /* Bold */ + } + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8E. */ + for (n = 0x01; n <= 0x0E; n++) + { + if (n == 7) continue; + if (t3100e->attrmap & 1) + { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + blinkcols[n+128][0] = amber; + blinkcols[n+128][1] = black; + } + else + { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n+128][0] = black; + blinkcols[n+128][1] = amber; + } + if (t3100e->attrmap & 2) boldcols[n] = 1; + } + /* Colours 07 and 0F are always amber on black. If blinking is + * enabled so are 87 and 8F. */ + for (n = 0x07; n <= 0x0F; n += 8) { blinkcols[n][0] = normcols[n][0] = black; blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = normcols[n+128][0] = black; - blinkcols[n+128][1] = normcols[n+128][1] = amber; + blinkcols[n+128][0] = black; + blinkcols[n+128][1] = amber; } - /* In the normal range, 00 11 22 .. FF are black */ + /* When not blinking, colours 81-8F are always amber on black. */ + for (n = 0x81; n <= 0x8F; n ++) + { + normcols[n][0] = black; + normcols[n][1] = amber; + boldcols[n] = (n & 0x08) != 0; + } + + + /* Finally do the ones which are solid black. These differ between + * the normal and blinking mappings */ for (n = 0; n <= 0xFF; n += 0x11) { normcols[n][0] = normcols[n][1] = black; @@ -570,9 +657,34 @@ void *t3100e_init() blinkcols[n][0] = blinkcols[n][1] = black; blinkcols[n+128][0] = blinkcols[n+128][1] = black; } +} + + +void *t3100e_init() +{ + t3100e_t *t3100e = malloc(sizeof(t3100e_t)); + memset(t3100e, 0, sizeof(t3100e_t)); + cga_init(&t3100e->cga); + + t3100e->internal = 1; + + /* 32k video RAM */ + t3100e->vram = malloc(0x8000); + + timer_add(t3100e_poll, &t3100e->cga.vidtime, TIMER_ALWAYS_ENABLED, t3100e); + + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e); + + /* Default attribute mapping is 4 */ + t3100e->attrmap = 4; + t3100e_recalcattrs(t3100e); /* Start off in 80x25 text mode */ - t3100e->cga_stat = 0xF4; + t3100e->cga.cgastat = 0xF4; + t3100e->cga.vram = t3100e->vram; t3100e->enabled = 1; t3100e->video_options = 0xFF; return t3100e; diff --git a/src/vid_t3100e.h b/src/vid_t3100e.h index 107cef6..b09688c 100644 --- a/src/vid_t3100e.h +++ b/src/vid_t3100e.h @@ -1,3 +1,4 @@ extern device_t t3100e_device; void t3100e_video_options_set(uint8_t options); +void t3100e_display_set(uint8_t internal); diff --git a/src/video.c b/src/video.c index 784b155..aae872a 100644 --- a/src/video.c +++ b/src/video.c @@ -323,8 +323,8 @@ void video_init() BITMAP *buffer32; -uint8_t fontdat[256][8]; -uint8_t fontdatm[512][16]; +uint8_t fontdat[2048][8]; +uint8_t fontdatm[2048][16]; uint8_t fontdatw[512][32]; /* Wyse700 font */ uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ @@ -420,22 +420,34 @@ void loadfont(char *s, int format) } break; case 5: /* Toshiba 3100e */ - for (c=0;c<256;c++) - { - fread(&fontdatm[c][8], 1, 8, f); - } - for (c=0;c<256;c++) - { - fread(&fontdatm[c+256][8], 1, 8, f); - } - for (c=0;c<256;c++) - { - fread(&fontdatm[c][0], 1, 8, f); - } - for (c=0;c<256;c++) - { - fread(&fontdatm[c+256][0], 1, 8, f); - } + for (d = 0; d < 2048; d += 512) /* Four languages... */ + { + for (c = d; c < d+256; c++) + { + fread(&fontdatm[c][8], 1, 8, f); + } + for (c = d+256; c < d+512; c++) + { + fread(&fontdatm[c][8], 1, 8, f); + } + for (c = d; c < d+256; c++) + { + fread(&fontdatm[c][0], 1, 8, f); + } + for (c = d+256; c < d+512; c++) + { + fread(&fontdatm[c][0], 1, 8, f); + } + fseek(f, 4096, SEEK_CUR); /* Skip blank section */ + for (c = d; c < d+256; c++) + { + fread(&fontdat[c][0], 1, 8, f); + } + for (c = d+256; c < d+512; c++) + { + fread(&fontdat[c][0], 1, 8, f); + } + } break; } diff --git a/src/video.h b/src/video.h index f4ca12a..36bf395 100644 --- a/src/video.h +++ b/src/video.h @@ -48,8 +48,8 @@ extern int egareads,egawrites; extern int fullchange; extern int changeframecount; -extern uint8_t fontdat[256][8]; -extern uint8_t fontdatm[512][16]; +extern uint8_t fontdat[2048][8]; +extern uint8_t fontdatm[2048][16]; extern uint32_t *video_15to32, *video_16to32;