From 173b1f7694514076267e4ba6883a6353bcff5f5c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Oct 2018 22:21:55 +0200 Subject: [PATCH] Replaced the Hercules, Hercules Plus, and Hercules InColor emulations with VARCem's, fixes Pictionary in Hercules mode. --- src/video/vid_hercules.c | 774 +++++++++++---------- src/video/vid_herculesplus.c | 1189 ++++++++++++++++---------------- src/video/vid_incolor.c | 1235 +++++++++++++++++----------------- 3 files changed, 1594 insertions(+), 1604 deletions(-) diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index f852469c6..d0ed0d84f 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.12 2018/09/19 + * Version: @(#)vid_hercules.c 1.0.13 2018/10/10 * * Authors: Sarah Walker, * Miran Grca, @@ -18,8 +18,8 @@ */ #include #include -#include #include +#include #include #include "../86box.h" #include "../mem.h" @@ -33,398 +33,450 @@ #include "vid_hercules.h" -typedef struct hercules_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; +typedef struct { + mem_mapping_t mapping; - uint8_t ctrl, ctrl2, stat; + uint8_t crtc[32]; + int crtcreg; - int64_t dispontime, dispofftime; - int64_t vidtime; - - int firstline, lastline; + uint8_t ctrl, + ctrl2, + stat; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + int64_t dispontime, + dispofftime; + int64_t vidtime; - uint8_t *vram; + int firstline, + lastline; + + int linepos, + displine; + int vc, + sc; + uint16_t ma, + maback; + int con, coff, + cursoron; + int dispon, + blink; + int64_t vsynctime; + int vadj; + + int cols[256][2][2]; + + uint8_t *vram; } hercules_t; static video_timings_t timing_hercules = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; -static int mdacols[256][2][2]; -void hercules_recalctimings(hercules_t *hercules); -void hercules_write(uint32_t addr, uint8_t val, void *p); -uint8_t hercules_read(uint32_t addr, void *p); - - -void hercules_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(hercules_t *dev) { - hercules_t *hercules = (hercules_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - hercules->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - hercules->crtc[hercules->crtcreg] = val; - if (hercules->crtc[10] == 6 && hercules->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - hercules->crtc[10] = 0xb; - hercules->crtc[11] = 0xc; - } - hercules_recalctimings(hercules); - return; - case 0x3b8: - hercules->ctrl = val; - return; - case 0x3bf: - hercules->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&hercules->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&hercules->mapping, 0xb0000, 0x08000); - return; - } -} + double disptime; + double _dispontime, _dispofftime; -uint8_t hercules_in(uint16_t addr, void *p) -{ - hercules_t *hercules = (hercules_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return hercules->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - return hercules->crtc[hercules->crtcreg]; - case 0x3ba: - return (hercules->stat & 0xf) | ((hercules->stat & 8) << 4); - } - return 0xff; -} + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; -void hercules_write(uint32_t addr, uint8_t val, void *p) -{ - hercules_t *hercules = (hercules_t *)p; - egawrites++; - hercules->vram[addr & 0xffff] = val; -} - -uint8_t hercules_read(uint32_t addr, void *p) -{ - hercules_t *hercules = (hercules_t *)p; - egareads++; - return hercules->vram[addr & 0xffff]; -} - -void hercules_recalctimings(hercules_t *hercules) -{ - double disptime; - double _dispontime, _dispofftime; - disptime = hercules->crtc[0] + 1; - _dispontime = hercules->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - hercules->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - hercules->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - -void hercules_poll(void *p) -{ - hercules_t *hercules = (hercules_t *)p; - uint16_t ca = (hercules->crtc[15] | (hercules->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint16_t dat; - int oldsc; - int blink; - if (!hercules->linepos) - { - hercules->vidtime += hercules->dispofftime; - hercules->stat |= 1; - hercules->linepos = 1; - oldsc = hercules->sc; - if ((hercules->crtc[8] & 3) == 3) - hercules->sc = (hercules->sc << 1) & 7; - if (hercules->dispon) - { - if (hercules->displine < hercules->firstline) - { - hercules->firstline = hercules->displine; - video_wait_for_buffer(); - } - hercules->lastline = hercules->displine; - if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) - { - ca = (hercules->sc & 3) * 0x2000; - if ((hercules->ctrl & 0x80) && (hercules->ctrl2 & 2)) - ca += 0x8000; -// printf("Draw herc %04X\n",ca); - for (x = 0; x < hercules->crtc[1]; x++) - { - dat = (hercules->vram[((hercules->ma << 1) & 0x1fff) + ca] << 8) | hercules->vram[((hercules->ma << 1) & 0x1fff) + ca + 1]; - hercules->ma++; - for (c = 0; c < 16; c++) - buffer->line[hercules->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; - } - } - else - { - for (x = 0; x < hercules->crtc[1]; x++) - { - chr = hercules->vram[(hercules->ma << 1) & 0xfff]; - attr = hercules->vram[((hercules->ma << 1) + 1) & 0xfff]; - drawcursor = ((hercules->ma == ca) && hercules->con && hercules->cursoron); - blink = ((hercules->blink & 16) && (hercules->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (hercules->sc == 12 && ((attr & 7) == 1)) - { - for (c = 0; c < 9; c++) - buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][1]; - } - else - { - for (c = 0; c < 8; c++) - buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][hercules->sc] & (1 << (c ^ 7))) ? 1 : 0]; - if ((chr & ~0x1f) == 0xc0) buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][hercules->sc] & 1]; - else buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][0]; - } - hercules->ma++; - if (drawcursor) - { - for (c = 0; c < 9; c++) - buffer->line[hercules->displine][(x * 9) + c] ^= mdacols[attr][0][1]; - } - } - } - } - hercules->sc = oldsc; - if (hercules->vc == hercules->crtc[7] && !hercules->sc) - { - hercules->stat |= 8; -// printf("VSYNC on %i %i\n",vc,sc); - } - hercules->displine++; - if (hercules->displine >= 500) - hercules->displine = 0; - } - else - { - hercules->vidtime += hercules->dispontime; - if (hercules->dispon) - hercules->stat &= ~1; - hercules->linepos = 0; - if (hercules->vsynctime) - { - hercules->vsynctime--; - if (!hercules->vsynctime) - { - hercules->stat &= ~8; -// printf("VSYNC off %i %i\n",vc,sc); - } - } - if (hercules->sc == (hercules->crtc[11] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[11] & 31) >> 1))) - { - hercules->con = 0; - hercules->coff = 1; - } - if (hercules->vadj) - { - hercules->sc++; - hercules->sc &= 31; - hercules->ma = hercules->maback; - hercules->vadj--; - if (!hercules->vadj) - { - hercules->dispon = 1; - hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff; - hercules->sc = 0; - } - } - else if (hercules->sc == hercules->crtc[9] || ((hercules->crtc[8] & 3) == 3 && hercules->sc == (hercules->crtc[9] >> 1))) - { - hercules->maback = hercules->ma; - hercules->sc = 0; - oldvc = hercules->vc; - hercules->vc++; - hercules->vc &= 127; - if (hercules->vc == hercules->crtc[6]) - hercules->dispon = 0; - if (oldvc == hercules->crtc[4]) - { -// printf("Display over at %i\n",displine); - hercules->vc = 0; - hercules->vadj = hercules->crtc[5]; - if (!hercules->vadj) hercules->dispon=1; - if (!hercules->vadj) hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff; - if ((hercules->crtc[10] & 0x60) == 0x20) hercules->cursoron = 0; - else hercules->cursoron = hercules->blink & 16; - } - if (hercules->vc == hercules->crtc[7]) - { - hercules->dispon = 0; - hercules->displine = 0; - hercules->vsynctime = 16;//(crtcm[3]>>4)+1; - if (hercules->crtc[7]) - { -// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline); - if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) x = hercules->crtc[1] << 4; - else x = hercules->crtc[1] * 9; - hercules->lastline++; - if ((x != xsize) || ((hercules->lastline - hercules->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = hercules->lastline - hercules->firstline; -// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]); - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, hercules->firstline, 0, ysize, xsize, ysize); - frames++; - if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) - { - video_res_x = hercules->crtc[1] * 16; - video_res_y = hercules->crtc[6] * 4; - video_bpp = 1; - } - else - { - video_res_x = hercules->crtc[1]; - video_res_y = hercules->crtc[6]; - video_bpp = 0; - } - } - hercules->firstline = 1000; - hercules->lastline = 0; - hercules->blink++; - } - } - else - { - hercules->sc++; - hercules->sc &= 31; - hercules->ma = hercules->maback; - } - if ((hercules->sc == (hercules->crtc[10] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[10] & 31) >> 1)))) - { - hercules->con = 1; -// printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]); - } - } + dev->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } -void *hercules_init(const device_t *info) +static void +hercules_out(uint16_t addr, uint8_t val, void *priv) { - int c; - hercules_t *hercules = malloc(sizeof(hercules_t)); - memset(hercules, 0, sizeof(hercules_t)); - video_inform(VIDEO_FLAG_TYPE_MDA, &timing_hercules); + hercules_t *dev = (hercules_t *)priv; - hercules->vram = malloc(0x10000); + switch (addr) { + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: + dev->crtcreg = val & 31; + break; - timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules); - mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, hercules); - io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules); + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + dev->crtc[dev->crtcreg] = val; - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + /* + * Fix for Generic Turbo XT BIOS, which + * sets up cursor registers wrong. + */ + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; + } + recalc_timings(dev); + break; - overscan_x = overscan_y = 0; + case 0x03b8: + dev->ctrl = val; + break; - cga_palette = device_get_config_int("rgb_type") << 1; - if (cga_palette > 6) - { - cga_palette = 0; + case 0x03bf: + dev->ctrl2 = val; + if (val & 0x02) + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + break; + + default: + break; + } +} + + +static uint8_t +hercules_in(uint16_t addr, void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: + ret = dev->crtcreg; + break; + + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x03ba: + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4); + break; + + default: + break; + } + + return(ret); +} + + +static void +hercules_write(uint32_t addr, uint8_t val, void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + + dev->vram[addr & 0xffff] = val; +} + + +static uint8_t +hercules_read(uint32_t addr, void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + + return(dev->vram[addr & 0xffff]); +} + + +static void +hercules_poll(void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + uint8_t chr, attr; + uint16_t ca, dat; + int oldsc, blink; + int x, c, oldvc; + int drawcursor; + + ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { + ca = (dev->sc & 3) * 0x2000; + if ((dev->ctrl & 0x80) && (dev->ctrl2 & 2)) + ca += 0x8000; + + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; + dev->ma++; + for (c = 0; c < 16; c++) + buffer->line[dev->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; + } + } else { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + + if (dev->sc == 12 && ((attr & 7) == 1)) { + for (c = 0; c < 9; c++) + buffer->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][1]; + } else { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; + + if ((chr & ~0x1f) == 0xc0) + buffer->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; + else + buffer->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][0]; + } + dev->ma++; + + if (drawcursor) { + for (c = 0; c < 9; c++) + buffer->line[dev->displine][(x * 9) + c] ^= dev->cols[attr][0][1]; + } + } + } } - cgapal_rebuild(); + dev->sc = oldsc; - lpt3_init(0x3BC); + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; - return hercules; + if (dev->dispon) + dev->stat &= ~1; + + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } + + if (dev->sc == (dev->crtc[11] & 31) || + ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (! dev->vadj) + dev->dispon = 1; + if (! dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16;//(crtcm[3]>>4)+1; + if (dev->crtc[7]) { + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_memtoscreen_8(0, dev->firstline, 0, ysize, xsize, ysize); + frames++; + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + + if ((dev->sc == (dev->crtc[10] & 31) || + ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } } -void hercules_close(void *p) -{ - hercules_t *hercules = (hercules_t *)p; - free(hercules->vram); - free(hercules); +static void * +hercules_init(const device_t *info) +{ + hercules_t *dev; + int c; + + dev = (hercules_t *)malloc(sizeof(hercules_t)); + memset(dev, 0x00, sizeof(hercules_t)); + + dev->vram = (uint8_t *)malloc(0x10000); + + timer_add(hercules_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, + hercules_read,NULL,NULL, hercules_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev); + + for (c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + + if (c & 0x08) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; + } + dev->cols[0x70][0][1] = 16; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = + dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = + dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = + dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = + dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; + dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; + dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; + dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; + + overscan_x = overscan_y = 0; + + cga_palette = device_get_config_int("rgb_type") << 1; + if (cga_palette > 6) + cga_palette = 0; + cgapal_rebuild(); + + video_inform(VIDEO_FLAG_TYPE_MDA, &timing_hercules); + + /* Force the LPT3 port to be enabled. */ + lpt3_init(0x3BC); + + return(dev); } -void hercules_speed_changed(void *p) + +static void +hercules_close(void *priv) { - hercules_t *hercules = (hercules_t *)p; - - hercules_recalctimings(hercules); + hercules_t *dev = (hercules_t *)priv; + + free(dev->vram); + free(dev); } -static const device_config_t hercules_config[] = + +static void +speed_changed(void *priv) { - { - "rgb_type", "Display type", CONFIG_SELECTION, "", 0, - { - { - "Default", 0 - }, - { - "Green", 1 - }, - { - "Amber", 2 - }, - { - "Gray", 3 - }, - { - "" - } - } - }, - { - "", "", -1 - } + hercules_t *dev = (hercules_t *)priv; + + recalc_timings(dev); +} + + +static const device_config_t hercules_config[] = { + { + "rgb_type", "Display type", CONFIG_SELECTION, "", 0, + { + { + "Default", 0 + }, + { + "Green", 1 + }, + { + "Amber", 2 + }, + { + "Gray", 3 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; - -const device_t hercules_device = -{ - "Hercules", - DEVICE_ISA, 0, - hercules_init, hercules_close, NULL, - NULL, - hercules_speed_changed, - NULL, - hercules_config +const device_t hercules_device = { + "Hercules", + DEVICE_ISA, + 0, + hercules_init, hercules_close, NULL, + NULL, + speed_changed, + NULL, + hercules_config }; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 2a91e554b..7f9bb3023 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -6,9 +6,9 @@ * * This file is part of the 86Box distribution. * - * Hercules InColor emulation. + * Hercules Plus emulation. * - * Version: @(#)vid_herculesplus.c 1.0.10 2018/09/19 + * Version: @(#)vid_herculesplus.c 1.0.11 2018/10/10 * * Authors: Sarah Walker, * Miran Grca, @@ -18,8 +18,8 @@ */ #include #include -#include #include +#include #include #include "../86box.h" #include "../io.h" @@ -34,13 +34,12 @@ /* extended CRTC registers */ - #define HERCULESPLUS_CRTC_XMODE 20 /* xMode register */ #define HERCULESPLUS_CRTC_UNDER 21 /* Underline */ #define HERCULESPLUS_CRTC_OVER 22 /* Overstrike */ /* character width */ -#define HERCULESPLUS_CW ((herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9) +#define HERCULESPLUS_CW ((dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9) /* mode control register */ #define HERCULESPLUS_CTRL_GRAPH 0x02 @@ -63,680 +62,618 @@ #define HERCULESPLUS_XMODE_RAMFONT 0x01 #define HERCULESPLUS_XMODE_90COL 0x02 -typedef struct herculesplus_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; - uint8_t ctrl, ctrl2, stat; +typedef struct { + mem_mapping_t mapping; - int64_t dispontime, dispofftime; - int64_t vidtime; + uint8_t crtc[32]; + int crtcreg; - int firstline, lastline; + uint8_t ctrl, ctrl2, stat; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + int64_t dispontime, dispofftime; + int64_t vidtime; - uint8_t *vram; + int firstline, lastline; + + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int64_t vsynctime; + int vadj; + + int cols[256][2][2]; + + uint8_t *vram; } herculesplus_t; static video_timings_t timing_herculesplus = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; -void herculesplus_recalctimings(herculesplus_t *herculesplus); -void herculesplus_write(uint32_t addr, uint8_t val, void *p); -uint8_t herculesplus_read(uint32_t addr, void *p); -static int mdacols[256][2][2]; - -void herculesplus_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(herculesplus_t *dev) { - herculesplus_t *herculesplus = (herculesplus_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - herculesplus->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (herculesplus->crtcreg > 22) return; - herculesplus->crtc[herculesplus->crtcreg] = val; - if (herculesplus->crtc[10] == 6 && herculesplus->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - herculesplus->crtc[10] = 0xb; - herculesplus->crtc[11] = 0xc; - } - herculesplus_recalctimings(herculesplus); - return; - case 0x3b8: - herculesplus->ctrl = val; - return; - case 0x3bf: - herculesplus->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&herculesplus->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&herculesplus->mapping, 0xb0000, 0x08000); - return; - } -} + double disptime; + double _dispontime, _dispofftime; -uint8_t herculesplus_in(uint16_t addr, void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return herculesplus->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (herculesplus->crtcreg > 22) return 0xff; - return herculesplus->crtc[herculesplus->crtcreg]; - case 0x3ba: - /* 0x50: InColor card identity */ - return (herculesplus->stat & 0xf) | ((herculesplus->stat & 8) << 4) | 0x10; - } - return 0xff; -} + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; -void herculesplus_write(uint32_t addr, uint8_t val, void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - - egawrites++; - - addr &= 0xFFFF; - - herculesplus->vram[addr] = val; -} - -uint8_t herculesplus_read(uint32_t addr, void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - - egareads++; - - addr &= 0xFFFF; - return herculesplus->vram[addr]; + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } - -void herculesplus_recalctimings(herculesplus_t *herculesplus) +static void +herculesplus_out(uint16_t port, uint8_t val, void *priv) { - double disptime; - double _dispontime, _dispofftime; - disptime = herculesplus->crtc[0] + 1; - _dispontime = herculesplus->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - herculesplus->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - herculesplus->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} + herculesplus_t *dev = (herculesplus_t *)priv; + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; + return; -static void herculesplus_draw_char_rom(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr) -{ - unsigned i; - int elg, blk; - unsigned ull; - unsigned val; - unsigned ifg, ibg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - - blk = 0; - if (herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK) - { - if (attr & 0x80) - { - blk = (herculesplus->blink & 16); + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 22) return; + dev->crtc[dev->crtcreg] = val; + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + *which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; } - attr &= 0x7f; - } + recalc_timings(dev); + return; - /* MDA-compatible attributes */ - ibg = 0; - ifg = 7; - if ((attr & 0x77) == 0x70) /* Invert */ - { - ifg = 0; - ibg = 7; - } - if (attr & 8) - { - ifg |= 8; /* High intensity FG */ - } - if (attr & 0x80) - { - ibg |= 8; /* High intensity BG */ - } - if ((attr & 0x77) == 0) /* Blank */ - { - ifg = ibg; - } - ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + case 0x3b8: + dev->ctrl = val; + return; - if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - - fnt = &(fontdatm[chr][herculesplus->sc]); - - if (blk) - { - val = 0x000; /* Blinking, draw all background */ - } - else if (herculesplus->sc == ull) - { - val = 0x1ff; /* Underscore, draw all foreground */ - } - else - { - val = fnt[0] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - } - for (i = 0; i < cw; i++) - { - buffer->line[herculesplus->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; - val = val << 1; - } -} - - -static void herculesplus_draw_char_ram4(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr) -{ - unsigned i; - int elg, blk; - unsigned ull; - unsigned val; - unsigned ifg, ibg, cfg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - int blink = herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK; - - blk = 0; - if (blink) - { - if (attr & 0x80) - { - blk = (herculesplus->blink & 16); - } - attr &= 0x7f; - } - - /* MDA-compatible attributes */ - ibg = 0; - ifg = 7; - if ((attr & 0x77) == 0x70) /* Invert */ - { - ifg = 0; - ibg = 7; - } - if (attr & 8) - { - ifg |= 8; /* High intensity FG */ - } - if (attr & 0x80) - { - ibg |= 8; /* High intensity BG */ - } - if ((attr & 0x77) == 0) /* Blank */ - { - ifg = ibg; - } - ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - fnt = herculesplus->vram + 0x4000 + 16 * chr + herculesplus->sc; - - if (blk) - { - /* Blinking, draw all background */ - val = 0x000; - } - else if (herculesplus->sc == ull) - { - /* Underscore, draw all foreground */ - val = 0x1ff; - } - else - { - val = fnt[0x00000] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - } - for (i = 0; i < cw; i++) - { - /* Generate pixel colour */ - cfg = 0; - /* cfg = colour of foreground pixels */ - if ((attr & 0x77) == 0) cfg = ibg; /* 'blank' attribute */ - - buffer->line[herculesplus->displine][x * cw + i] = mdacols[attr][blink][cfg]; - val = val << 1; - } -} - - -static void herculesplus_draw_char_ram48(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr) -{ - unsigned i; - int elg, blk, ul, ol, bld; - unsigned ull, oll, ulc = 0, olc = 0; - unsigned val; - unsigned ibg, cfg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - int blink = herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK; - int font = (attr & 0x0F); - - if (font >= 12) font &= 7; - - blk = 0; - if (blink) - { - if (attr & 0x40) - { - blk = (herculesplus->blink & 16); - } - attr &= 0x7f; - } - /* MDA-compatible attributes */ - if (blink) - { - ibg = (attr & 0x80) ? 8 : 0; - bld = 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } - else - { - bld = (attr & 0x80) ? 1 : 0; - ibg = (attr & 0x40) ? 0x0F : 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } - if (ul) - { - ull = herculesplus->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F; - ulc = (herculesplus->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F; - if (ulc == 0) ulc = 7; - } - else - { - ull = 0xFFFF; - } - if (ol) - { - oll = herculesplus->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F; - olc = (herculesplus->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F; - if (olc == 0) olc = 7; - } - else - { - oll = 0xFFFF; - } - - if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - fnt = herculesplus->vram + 0x4000 + 16 * chr + 4096 * font + herculesplus->sc; - - if (blk) - { - /* Blinking, draw all background */ - val = 0x000; - } - else if (herculesplus->sc == ull) - { - /* Underscore, draw all foreground */ - val = 0x1ff; - } - else - { - val = fnt[0x00000] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - if (bld) - { - val |= (val >> 1); - } - } - for (i = 0; i < cw; i++) - { - /* Generate pixel colour */ - cfg = val & 0x100; - if (herculesplus->sc == oll) - { - cfg = olc ^ ibg; /* Strikethrough */ - } - else if (herculesplus->sc == ull) - { - cfg = ulc ^ ibg; /* Underline */ - } + case 0x3bf: + dev->ctrl2 = val; + if (val & 2) + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); else - { - cfg |= ibg; - } + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + return; + } +} + + +static uint8_t +herculesplus_in(uint16_t port, void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; + + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg <= 22) + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3ba: + /* 0x50: InColor card identity */ + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; + break; + } + + return ret; +} + + +static void +herculesplus_write(uint32_t addr, uint8_t val, void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + + dev->vram[addr & 0xffff] = val; +} + + +static uint8_t +herculesplus_read(uint32_t addr, void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + + return dev->vram[addr & 0xffff]; +} + + +static void +draw_char_rom(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) +{ + unsigned ull, val, ifg, ibg; + const uint8_t *fnt; + int i, elg, blk; + int cw = HERCULESPLUS_CW; + + blk = 0; + if (dev->ctrl & HERCULESPLUS_CTRL_BLINK) { + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; + } + + /* MDA-compatible attributes */ + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; + } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + + fnt = &(fontdatm[chr][dev->sc]); + + if (blk) { + val = 0x000; /* Blinking, draw all background */ + } else if (dev->sc == ull) { + val = 0x1ff; /* Underscore, draw all foreground */ + } else { + val = fnt[0] << 1; + + if (elg) + val |= (val >> 1) & 1; + } + + for (i = 0; i < cw; i++) { + buffer->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; + val = val << 1; + } +} + + +static void +draw_char_ram4(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) +{ + unsigned ull, val, ifg, ibg, cfg; + const uint8_t *fnt; + int i, elg, blk; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; + + blk = 0; + if (blink) { + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; + } + + /* MDA-compatible attributes */ + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; + } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; + + if (blk) { + /* Blinking, draw all background */ + val = 0x000; + } else if (dev->sc == ull) { + /* Underscore, draw all foreground */ + val = 0x1ff; + } else { + val = fnt[0x00000] << 1; + + if (elg) + val |= (val >> 1) & 1; + } + + for (i = 0; i < cw; i++) { + /* Generate pixel colour */ + cfg = 0; + + /* cfg = colour of foreground pixels */ + if ((attr & 0x77) == 0) + cfg = ibg; /* 'blank' attribute */ + + buffer->line[dev->displine][x * cw + i] = dev->cols[attr][blink][cfg]; + val = val << 1; + } +} + + +static void +draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) +{ + int i, elg, blk, ul, ol, bld; + unsigned ull, oll, ulc = 0, olc = 0; + unsigned val, ibg, cfg; + const unsigned char *fnt; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; + int font = (attr & 0x0F); + + if (font >= 12) font &= 7; + + blk = 0; + if (blink) { + if (attr & 0x40) + blk = (dev->blink & 16); + attr &= 0x7f; + } + + /* MDA-compatible attributes */ + if (blink) { + ibg = (attr & 0x80) ? 8 : 0; + bld = 0; + ol = (attr & 0x20) ? 1 : 0; + ul = (attr & 0x10) ? 1 : 0; + } else { + bld = (attr & 0x80) ? 1 : 0; + ibg = (attr & 0x40) ? 0x0F : 0; + ol = (attr & 0x20) ? 1 : 0; + ul = (attr & 0x10) ? 1 : 0; + } + + if (ul) { + ull = dev->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F; + ulc = (dev->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F; + if (ulc == 0) ulc = 7; + } else { + ull = 0xFFFF; + } + + if (ol) { + oll = dev->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F; + olc = (dev->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F; + if (olc == 0) olc = 7; + } else { + oll = 0xFFFF; + } + + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; + + if (blk) { /* Blinking, draw all background */ + val = 0x000; + } else if (dev->sc == ull) { + /* Underscore, draw all foreground */ + val = 0x1ff; + } else { + val = fnt[0x00000] << 1; + + if (elg) + val |= (val >> 1) & 1; + if (bld) + val |= (val >> 1); + } + + for (i = 0; i < cw; i++) { + /* Generate pixel colour */ + cfg = val & 0x100; + if (dev->sc == oll) + cfg = olc ^ ibg; /* Strikethrough */ + else if (dev->sc == ull) + cfg = ulc ^ ibg; /* Underline */ + else + cfg |= ibg; - buffer->line[herculesplus->displine][(x * cw) + i] = mdacols[attr][blink][cfg]; - val = val << 1; - } + buffer->line[dev->displine][(x * cw) + i] = dev->cols[attr][blink][cfg]; + val = val << 1; + } } -static void herculesplus_text_line(herculesplus_t *herculesplus, uint16_t ca) + +static void +text_line(herculesplus_t *dev, uint16_t ca) { - int drawcursor; - int x, c; - uint8_t chr, attr; - uint32_t col; + int drawcursor; + int x, c; + uint8_t chr, attr; + uint32_t col; - for (x = 0; x < herculesplus->crtc[1]; x++) - { - chr = herculesplus->vram[(herculesplus->ma << 1) & 0xfff]; - attr = herculesplus->vram[((herculesplus->ma << 1) + 1) & 0xfff]; + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; - drawcursor = ((herculesplus->ma == ca) && herculesplus->con && herculesplus->cursoron); + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - switch (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & 5) - { - case 0: - case 4: /* ROM font */ - herculesplus_draw_char_rom(herculesplus, x, chr, attr); - break; - case 1: /* 4k RAMfont */ - herculesplus_draw_char_ram4(herculesplus, x, chr, attr); - break; - case 5: /* 48k RAMfont */ - herculesplus_draw_char_ram48(herculesplus, x, chr, attr); - break; + switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) { + case 0: + case 4: /* ROM font */ + draw_char_rom(dev, x, chr, attr); + break; + case 1: /* 4k RAMfont */ + draw_char_ram4(dev, x, chr, attr); + break; + + case 5: /* 48k RAMfont */ + draw_char_ram48(dev, x, chr, attr); + break; + } + ++dev->ma; + + if (drawcursor) { + int cw = HERCULESPLUS_CW; + + col = dev->cols[attr][0][1]; + for (c = 0; c < cw; c++) + ((uint32_t *)buffer32->line[dev->displine])[x * cw + c] = col; + } + } +} + + +static void +graphics_line(herculesplus_t *dev) +{ + uint16_t ca; + int x, c, plane = 0; + uint16_t val; + + /* Graphics mode. */ + ca = (dev->sc & 3) * 0x2000; + if ((dev->ctrl & HERCULESPLUS_CTRL_PAGE1) && (dev->ctrl2 & HERCULESPLUS_CTRL2_PAGE1)) + ca += 0x8000; + + for (x = 0; x < dev->crtc[1]; x++) { + val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) + | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + + dev->ma++; + for (c = 0; c < 16; c++) { + val >>= 1; + + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c] = (val & 1) ? 7 : 0; + } + } +} + + +static void +herculesplus_poll(void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int x, oldvc, oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); } - ++herculesplus->ma; - if (drawcursor) - { - int cw = HERCULESPLUS_CW; + dev->lastline = dev->displine; + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + graphics_line(dev); + else + text_line(dev, ca); + } + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } - col = mdacols[attr][0][1]; - for (c = 0; c < cw; c++) - { - ((uint32_t *)buffer32->line[herculesplus->displine])[x * cw + c] = col; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) dev->dispon=1; + if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + frames++; + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; } + + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } } -static void herculesplus_graphics_line(herculesplus_t *herculesplus) +static void * +herculesplus_init(const device_t *info) { - uint16_t ca; - int x, c, plane = 0; - uint16_t val; + herculesplus_t *dev; + int c; - /* Graphics mode. */ - ca = (herculesplus->sc & 3) * 0x2000; - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_PAGE1) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_PAGE1)) - ca += 0x8000; + dev = (herculesplus_t *)malloc(sizeof(herculesplus_t)); + memset(dev, 0, sizeof(herculesplus_t)); - for (x = 0; x < herculesplus->crtc[1]; x++) - { - val = (herculesplus->vram[((herculesplus->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) - | herculesplus->vram[((herculesplus->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + dev->vram = (uint8_t *)malloc(0x10000); /* 64k VRAM */ - herculesplus->ma++; - for (c = 0; c < 16; c++) - { - val >>= 1; + timer_add(herculesplus_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - ((uint32_t *)buffer32->line[herculesplus->displine])[(x << 4) + c] = (val & 1) ? 7 : 0; - } - } + mem_mapping_add(&dev->mapping, 0xb0000, 0x10000, + herculesplus_read,NULL,NULL, + herculesplus_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + herculesplus_in,NULL, NULL, herculesplus_out,NULL,NULL, dev); + + for (c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + if (c & 8) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; + } + dev->cols[0x70][0][1] = 16; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = + dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = + dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = + dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = + dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; + dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; + dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; + dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; + + video_inform(VIDEO_FLAG_TYPE_MDA, &timing_herculesplus); + + /* Force the LPT3 port to be enabled. */ + lpt3_init(0x3BC); + + return dev; } -void herculesplus_poll(void *p) + +static void +herculesplus_close(void *priv) { - herculesplus_t *herculesplus = (herculesplus_t *)p; - uint16_t ca = (herculesplus->crtc[15] | (herculesplus->crtc[14] << 8)) & 0x3fff; - int x; - int oldvc; - int oldsc; + herculesplus_t *dev = (herculesplus_t *)priv; - if (!herculesplus->linepos) - { - herculesplus->vidtime += herculesplus->dispofftime; - herculesplus->stat |= 1; - herculesplus->linepos = 1; - oldsc = herculesplus->sc; - if ((herculesplus->crtc[8] & 3) == 3) - herculesplus->sc = (herculesplus->sc << 1) & 7; - if (herculesplus->dispon) - { - if (herculesplus->displine < herculesplus->firstline) - { - herculesplus->firstline = herculesplus->displine; - video_wait_for_buffer(); - } - herculesplus->lastline = herculesplus->displine; - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - { - herculesplus_graphics_line(herculesplus); - } - else - { - herculesplus_text_line(herculesplus, ca); - } - } - herculesplus->sc = oldsc; - if (herculesplus->vc == herculesplus->crtc[7] && !herculesplus->sc) - { - herculesplus->stat |= 8; - } - herculesplus->displine++; - if (herculesplus->displine >= 500) - herculesplus->displine = 0; - } - else - { - herculesplus->vidtime += herculesplus->dispontime; - if (herculesplus->dispon) - herculesplus->stat &= ~1; - herculesplus->linepos = 0; - if (herculesplus->vsynctime) - { - herculesplus->vsynctime--; - if (!herculesplus->vsynctime) - { - herculesplus->stat &= ~8; - } - } - if (herculesplus->sc == (herculesplus->crtc[11] & 31) || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == ((herculesplus->crtc[11] & 31) >> 1))) - { - herculesplus->con = 0; - herculesplus->coff = 1; - } - if (herculesplus->vadj) - { - herculesplus->sc++; - herculesplus->sc &= 31; - herculesplus->ma = herculesplus->maback; - herculesplus->vadj--; - if (!herculesplus->vadj) - { - herculesplus->dispon = 1; - herculesplus->ma = herculesplus->maback = (herculesplus->crtc[13] | (herculesplus->crtc[12] << 8)) & 0x3fff; - herculesplus->sc = 0; - } - } - else if (herculesplus->sc == herculesplus->crtc[9] || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == (herculesplus->crtc[9] >> 1))) - { - herculesplus->maback = herculesplus->ma; - herculesplus->sc = 0; - oldvc = herculesplus->vc; - herculesplus->vc++; - herculesplus->vc &= 127; - if (herculesplus->vc == herculesplus->crtc[6]) - herculesplus->dispon = 0; - if (oldvc == herculesplus->crtc[4]) - { - herculesplus->vc = 0; - herculesplus->vadj = herculesplus->crtc[5]; - if (!herculesplus->vadj) herculesplus->dispon=1; - if (!herculesplus->vadj) herculesplus->ma = herculesplus->maback = (herculesplus->crtc[13] | (herculesplus->crtc[12] << 8)) & 0x3fff; - if ((herculesplus->crtc[10] & 0x60) == 0x20) herculesplus->cursoron = 0; - else herculesplus->cursoron = herculesplus->blink & 16; - } - if (herculesplus->vc == herculesplus->crtc[7]) - { - herculesplus->dispon = 0; - herculesplus->displine = 0; - herculesplus->vsynctime = 16; - if (herculesplus->crtc[7]) - { - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - { - x = herculesplus->crtc[1] << 4; - } - else - { - x = herculesplus->crtc[1] * 9; - } - herculesplus->lastline++; - if ((x != xsize) || ((herculesplus->lastline - herculesplus->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = herculesplus->lastline - herculesplus->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, herculesplus->firstline, 0, herculesplus->lastline - herculesplus->firstline, xsize, herculesplus->lastline - herculesplus->firstline); - frames++; - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - { - video_res_x = herculesplus->crtc[1] * 16; - video_res_y = herculesplus->crtc[6] * 4; - video_bpp = 1; - } - else - { - video_res_x = herculesplus->crtc[1]; - video_res_y = herculesplus->crtc[6]; - video_bpp = 0; - } - } - herculesplus->firstline = 1000; - herculesplus->lastline = 0; - herculesplus->blink++; - } - } - else - { - herculesplus->sc++; - herculesplus->sc &= 31; - herculesplus->ma = herculesplus->maback; - } - if ((herculesplus->sc == (herculesplus->crtc[10] & 31) || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == ((herculesplus->crtc[10] & 31) >> 1)))) - { - herculesplus->con = 1; - } - } + free(dev->vram); + free(dev); } -void *herculesplus_init(const device_t *info) + +static void +speed_changed(void *priv) { - int c; - herculesplus_t *herculesplus = malloc(sizeof(herculesplus_t)); - memset(herculesplus, 0, sizeof(herculesplus_t)); - video_inform(VIDEO_FLAG_TYPE_MDA, &timing_herculesplus); + herculesplus_t *dev = (herculesplus_t *)priv; - herculesplus->vram = malloc(0x10000); /* 64k VRAM */ - - timer_add(herculesplus_poll, &herculesplus->vidtime, TIMER_ALWAYS_ENABLED, herculesplus); - mem_mapping_add(&herculesplus->mapping, 0xb0000, 0x10000, herculesplus_read, NULL, NULL, herculesplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, herculesplus); - io_sethandler(0x03b0, 0x0010, herculesplus_in, NULL, NULL, herculesplus_out, NULL, NULL, herculesplus); - - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - - lpt3_init(0x3BC); - - return herculesplus; + recalc_timings(dev); } -void herculesplus_close(void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - free(herculesplus->vram); - free(herculesplus); -} - -void herculesplus_speed_changed(void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - - herculesplus_recalctimings(herculesplus); -} - -const device_t herculesplus_device = -{ - "Hercules Plus", - DEVICE_ISA, 0, - herculesplus_init, herculesplus_close, NULL, - NULL, - herculesplus_speed_changed, - NULL, - NULL +const device_t herculesplus_device = { + "Hercules Plus", + DEVICE_ISA, + 0, + herculesplus_init, herculesplus_close, NULL, + NULL, + speed_changed, + NULL, + NULL }; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 8e1988a40..418579445 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.11 2018/09/19 + * Version: @(#)vid_incolor.c 1.0.12 2018/10/10 * * Authors: Sarah Walker, * Miran Grca, @@ -18,8 +18,8 @@ */ #include #include -#include #include +#include #include #include "../86box.h" #include "../io.h" @@ -45,7 +45,7 @@ #define INCOLOR_CRTC_PALETTE 28 /* Palette */ /* character width */ -#define INCOLOR_CW ((incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) ? 8 : 9) +#define INCOLOR_CW ((dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) ? 8 : 9) /* mode control register */ #define INCOLOR_CTRL_GRAPH 0x02 @@ -81,336 +81,352 @@ /* Default palette */ -static unsigned char defpal[16] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F +static const uint8_t defpal[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; -static uint32_t incolor_rgb[64]; - /* Mapping of inks to RGB */ -static unsigned char init_rgb[64][3] = -{ +static const uint8_t init_rgb[64][3] = { /* rgbRGB */ - { 0x00, 0x00, 0x00 }, /* 000000 */ - { 0x00, 0x00, 0xaa }, /* 000001 */ - { 0x00, 0xaa, 0x00 }, /* 000010 */ - { 0x00, 0xaa, 0xaa }, /* 000011 */ - { 0xaa, 0x00, 0x00 }, /* 000100 */ - { 0xaa, 0x00, 0xaa }, /* 000101 */ - { 0xaa, 0xaa, 0x00 }, /* 000110 */ - { 0xaa, 0xaa, 0xaa }, /* 000111 */ - { 0x00, 0x00, 0x55 }, /* 001000 */ - { 0x00, 0x00, 0xff }, /* 001001 */ - { 0x00, 0xaa, 0x55 }, /* 001010 */ - { 0x00, 0xaa, 0xff }, /* 001011 */ - { 0xaa, 0x00, 0x55 }, /* 001100 */ - { 0xaa, 0x00, 0xff }, /* 001101 */ - { 0xaa, 0xaa, 0x55 }, /* 001110 */ - { 0xaa, 0xaa, 0xff }, /* 001111 */ - { 0x00, 0x55, 0x00 }, /* 010000 */ - { 0x00, 0x55, 0xaa }, /* 010001 */ - { 0x00, 0xff, 0x00 }, /* 010010 */ - { 0x00, 0xff, 0xaa }, /* 010011 */ - { 0xaa, 0x55, 0x00 }, /* 010100 */ - { 0xaa, 0x55, 0xaa }, /* 010101 */ - { 0xaa, 0xff, 0x00 }, /* 010110 */ - { 0xaa, 0xff, 0xaa }, /* 010111 */ - { 0x00, 0x55, 0x55 }, /* 011000 */ - { 0x00, 0x55, 0xff }, /* 011001 */ - { 0x00, 0xff, 0x55 }, /* 011010 */ - { 0x00, 0xff, 0xff }, /* 011011 */ - { 0xaa, 0x55, 0x55 }, /* 011100 */ - { 0xaa, 0x55, 0xff }, /* 011101 */ - { 0xaa, 0xff, 0x55 }, /* 011110 */ - { 0xaa, 0xff, 0xff }, /* 011111 */ - { 0x55, 0x00, 0x00 }, /* 100000 */ - { 0x55, 0x00, 0xaa }, /* 100001 */ - { 0x55, 0xaa, 0x00 }, /* 100010 */ - { 0x55, 0xaa, 0xaa }, /* 100011 */ - { 0xff, 0x00, 0x00 }, /* 100100 */ - { 0xff, 0x00, 0xaa }, /* 100101 */ - { 0xff, 0xaa, 0x00 }, /* 100110 */ - { 0xff, 0xaa, 0xaa }, /* 100111 */ - { 0x55, 0x00, 0x55 }, /* 101000 */ - { 0x55, 0x00, 0xff }, /* 101001 */ - { 0x55, 0xaa, 0x55 }, /* 101010 */ - { 0x55, 0xaa, 0xff }, /* 101011 */ - { 0xff, 0x00, 0x55 }, /* 101100 */ - { 0xff, 0x00, 0xff }, /* 101101 */ - { 0xff, 0xaa, 0x55 }, /* 101110 */ - { 0xff, 0xaa, 0xff }, /* 101111 */ - { 0x55, 0x55, 0x00 }, /* 110000 */ - { 0x55, 0x55, 0xaa }, /* 110001 */ - { 0x55, 0xff, 0x00 }, /* 110010 */ - { 0x55, 0xff, 0xaa }, /* 110011 */ - { 0xff, 0x55, 0x00 }, /* 110100 */ - { 0xff, 0x55, 0xaa }, /* 110101 */ - { 0xff, 0xff, 0x00 }, /* 110110 */ - { 0xff, 0xff, 0xaa }, /* 110111 */ - { 0x55, 0x55, 0x55 }, /* 111000 */ - { 0x55, 0x55, 0xff }, /* 111001 */ - { 0x55, 0xff, 0x55 }, /* 111010 */ - { 0x55, 0xff, 0xff }, /* 111011 */ - { 0xff, 0x55, 0x55 }, /* 111100 */ - { 0xff, 0x55, 0xff }, /* 111101 */ - { 0xff, 0xff, 0x55 }, /* 111110 */ - { 0xff, 0xff, 0xff }, /* 111111 */ + { 0x00, 0x00, 0x00 }, /* 000000 */ + { 0x00, 0x00, 0xaa }, /* 000001 */ + { 0x00, 0xaa, 0x00 }, /* 000010 */ + { 0x00, 0xaa, 0xaa }, /* 000011 */ + { 0xaa, 0x00, 0x00 }, /* 000100 */ + { 0xaa, 0x00, 0xaa }, /* 000101 */ + { 0xaa, 0xaa, 0x00 }, /* 000110 */ + { 0xaa, 0xaa, 0xaa }, /* 000111 */ + { 0x00, 0x00, 0x55 }, /* 001000 */ + { 0x00, 0x00, 0xff }, /* 001001 */ + { 0x00, 0xaa, 0x55 }, /* 001010 */ + { 0x00, 0xaa, 0xff }, /* 001011 */ + { 0xaa, 0x00, 0x55 }, /* 001100 */ + { 0xaa, 0x00, 0xff }, /* 001101 */ + { 0xaa, 0xaa, 0x55 }, /* 001110 */ + { 0xaa, 0xaa, 0xff }, /* 001111 */ + { 0x00, 0x55, 0x00 }, /* 010000 */ + { 0x00, 0x55, 0xaa }, /* 010001 */ + { 0x00, 0xff, 0x00 }, /* 010010 */ + { 0x00, 0xff, 0xaa }, /* 010011 */ + { 0xaa, 0x55, 0x00 }, /* 010100 */ + { 0xaa, 0x55, 0xaa }, /* 010101 */ + { 0xaa, 0xff, 0x00 }, /* 010110 */ + { 0xaa, 0xff, 0xaa }, /* 010111 */ + { 0x00, 0x55, 0x55 }, /* 011000 */ + { 0x00, 0x55, 0xff }, /* 011001 */ + { 0x00, 0xff, 0x55 }, /* 011010 */ + { 0x00, 0xff, 0xff }, /* 011011 */ + { 0xaa, 0x55, 0x55 }, /* 011100 */ + { 0xaa, 0x55, 0xff }, /* 011101 */ + { 0xaa, 0xff, 0x55 }, /* 011110 */ + { 0xaa, 0xff, 0xff }, /* 011111 */ + { 0x55, 0x00, 0x00 }, /* 100000 */ + { 0x55, 0x00, 0xaa }, /* 100001 */ + { 0x55, 0xaa, 0x00 }, /* 100010 */ + { 0x55, 0xaa, 0xaa }, /* 100011 */ + { 0xff, 0x00, 0x00 }, /* 100100 */ + { 0xff, 0x00, 0xaa }, /* 100101 */ + { 0xff, 0xaa, 0x00 }, /* 100110 */ + { 0xff, 0xaa, 0xaa }, /* 100111 */ + { 0x55, 0x00, 0x55 }, /* 101000 */ + { 0x55, 0x00, 0xff }, /* 101001 */ + { 0x55, 0xaa, 0x55 }, /* 101010 */ + { 0x55, 0xaa, 0xff }, /* 101011 */ + { 0xff, 0x00, 0x55 }, /* 101100 */ + { 0xff, 0x00, 0xff }, /* 101101 */ + { 0xff, 0xaa, 0x55 }, /* 101110 */ + { 0xff, 0xaa, 0xff }, /* 101111 */ + { 0x55, 0x55, 0x00 }, /* 110000 */ + { 0x55, 0x55, 0xaa }, /* 110001 */ + { 0x55, 0xff, 0x00 }, /* 110010 */ + { 0x55, 0xff, 0xaa }, /* 110011 */ + { 0xff, 0x55, 0x00 }, /* 110100 */ + { 0xff, 0x55, 0xaa }, /* 110101 */ + { 0xff, 0xff, 0x00 }, /* 110110 */ + { 0xff, 0xff, 0xaa }, /* 110111 */ + { 0x55, 0x55, 0x55 }, /* 111000 */ + { 0x55, 0x55, 0xff }, /* 111001 */ + { 0x55, 0xff, 0x55 }, /* 111010 */ + { 0x55, 0xff, 0xff }, /* 111011 */ + { 0xff, 0x55, 0x55 }, /* 111100 */ + { 0xff, 0x55, 0xff }, /* 111101 */ + { 0xff, 0xff, 0x55 }, /* 111110 */ + { 0xff, 0xff, 0xff }, /* 111111 */ }; +typedef struct { + mem_mapping_t mapping; -typedef struct incolor_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; + uint8_t crtc[32]; + int crtcreg; - uint8_t ctrl, ctrl2, stat; + uint8_t ctrl, ctrl2, stat; - int64_t dispontime, dispofftime; - int64_t vidtime; - - int firstline, lastline; + int64_t dispontime, dispofftime; + int64_t vidtime; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + int firstline, lastline; - uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ - uint8_t palette_idx; /* Palette write index */ - uint8_t latch[4]; /* Memory read/write latches */ - uint8_t *vram; + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int64_t vsynctime; + int vadj; + + uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ + uint8_t palette_idx; /* Palette write index */ + uint8_t latch[4]; /* Memory read/write latches */ + + uint32_t rgb[64]; + + uint8_t *vram; } incolor_t; static video_timings_t timing_incolor = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; -void incolor_recalctimings(incolor_t *incolor); -void incolor_write(uint32_t addr, uint8_t val, void *p); -uint8_t incolor_read(uint32_t addr, void *p); - -void incolor_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(incolor_t *dev) { - incolor_t *incolor = (incolor_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - incolor->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (incolor->crtcreg > 28) return; - /* Palette load register */ - if (incolor->crtcreg == INCOLOR_CRTC_PALETTE) - { - incolor->palette[incolor->palette_idx % 16] = val; - ++incolor->palette_idx; - } - incolor->crtc[incolor->crtcreg] = val; - if (incolor->crtc[10] == 6 && incolor->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - incolor->crtc[10] = 0xb; - incolor->crtc[11] = 0xc; - } - incolor_recalctimings(incolor); - return; - case 0x3b8: - incolor->ctrl = val; - return; - case 0x3bf: - incolor->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&incolor->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&incolor->mapping, 0xb0000, 0x08000); - return; - } + double disptime; + double _dispontime, _dispofftime; + + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } -uint8_t incolor_in(uint16_t addr, void *p) + +static void +incolor_out(uint16_t port, uint8_t val, void *priv) { - incolor_t *incolor = (incolor_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return incolor->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (incolor->crtcreg > 28) return 0xff; - incolor->palette_idx = 0; /* Read resets the palette index */ - return incolor->crtc[incolor->crtcreg]; - case 0x3ba: - /* 0x50: InColor card identity */ - return (incolor->stat & 0xf) | ((incolor->stat & 8) << 4) | 0x50; - } - return 0xff; -} + incolor_t *dev = (incolor_t *)priv; -void incolor_write(uint32_t addr, uint8_t val, void *p) -{ - incolor_t *incolor = (incolor_t *)p; - - int plane; - - unsigned char wmask = incolor->crtc[INCOLOR_CRTC_MASK]; - unsigned char wmode = incolor->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_WRMODE; - unsigned char fg = incolor->crtc[INCOLOR_CRTC_RWCOL] & 0x0F; - unsigned char bg = (incolor->crtc[INCOLOR_CRTC_RWCOL] >> 4)&0x0F; - unsigned char w = 0; - unsigned char vmask; /* Mask of bit within byte */ - unsigned char pmask; /* Mask of plane within colour value */ - unsigned char latch; - - egawrites++; - - addr &= 0xFFFF; - - /* In text mode, writes to the bottom 16k always touch all 4 planes */ - if (!(incolor->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) - { - incolor->vram[addr] = val; + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; return; - } - /* There are four write modes: - * 0: 1 => foreground, 0 => background - * 1: 1 => foreground, 0 => source latch - * 2: 1 => source latch, 0 => background - * 3: 1 => source latch, 0 => ~source latch - */ - pmask = 1; - for (plane = 0; plane < 4; pmask <<= 1, wmask >>= 1, addr += 0x10000, - plane++) - { - if (wmask & 0x10) /* Ignore writes to selected plane */ - { - continue; + case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + if (dev->crtcreg > 28) return; + /* Palette load register */ + if (dev->crtcreg == INCOLOR_CRTC_PALETTE) { + dev->palette[dev->palette_idx % 16] = val; + ++dev->palette_idx; + } + dev->crtc[dev->crtcreg] = val; + + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + * which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; } - latch = incolor->latch[plane]; - for (vmask = 0x80; vmask != 0; vmask >>= 1) - { - switch (wmode) - { - case 0x00: - if (val & vmask) w = (fg & pmask); - else w = (bg & pmask); - break; - case 0x10: - if (val & vmask) w = (fg & pmask); - else w = (latch & vmask); - break; - case 0x20: - if (val & vmask) w = (latch & vmask); - else w = (bg & pmask); - break; - case 0x30: - if (val & vmask) w = (latch & vmask); - else w = ((~latch) & vmask); - break; - } + recalc_timings(dev); + return; + + case 0x3b8: + dev->ctrl = val; + return; + + case 0x3bf: + dev->ctrl2 = val; + if (val & 2) + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + return; + } +} + + +static uint8_t +incolor_in(uint16_t port, void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; + + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 28) break; + + dev->palette_idx = 0; /* Read resets the palette index */ + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3ba: + /* 0x50: InColor card identity */ + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50; + break; + + default: + break; + } + + return ret; +} + + +static void +incolor_write(uint32_t addr, uint8_t val, void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + unsigned char wmask = dev->crtc[INCOLOR_CRTC_MASK]; + unsigned char wmode = dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_WRMODE; + unsigned char fg = dev->crtc[INCOLOR_CRTC_RWCOL] & 0x0F; + unsigned char bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4)&0x0F; + unsigned char w = 0; + unsigned char vmask; /* Mask of bit within byte */ + unsigned char pmask; /* Mask of plane within colour value */ + unsigned char latch; + int plane; + + addr &= 0xffff; + + /* In text mode, writes to the bottom 16k always touch all 4 planes */ + if (!(dev->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) { + dev->vram[addr] = val; + return; + } + + /* There are four write modes: + * 0: 1 => foreground, 0 => background + * 1: 1 => foreground, 0 => source latch + * 2: 1 => source latch, 0 => background + * 3: 1 => source latch, 0 => ~source latch + */ + pmask = 1; + for (plane = 0; plane < 4; pmask <<= 1, wmask >>= 1, addr += 0x10000, plane++) { + if (wmask & 0x10) /* Ignore writes to selected plane */ + { + continue; + } + latch = dev->latch[plane]; + for (vmask = 0x80; vmask != 0; vmask >>= 1) { + switch (wmode) { + case 0x00: + if (val & vmask) w = (fg & pmask); + else w = (bg & pmask); + break; + + case 0x10: + if (val & vmask) w = (fg & pmask); + else w = (latch & vmask); + break; + + case 0x20: + if (val & vmask) w = (latch & vmask); + else w = (bg & pmask); + break; + + case 0x30: + if (val & vmask) w = (latch & vmask); + else w = ((~latch) & vmask); + break; + } + /* w is nonzero to write a 1, zero to write a 0 */ - if (w) incolor->vram[addr] |= vmask; - else incolor->vram[addr] &= ~vmask; + if (w) dev->vram[addr] |= vmask; + else dev->vram[addr] &= ~vmask; + } + } +} + + +static uint8_t +incolor_read(uint32_t addr, void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + unsigned plane; + unsigned char lp = dev->crtc[INCOLOR_CRTC_PROTECT]; + unsigned char value = 0; + unsigned char dc; /* "don't care" register */ + unsigned char bg; /* background colour */ + unsigned char fg; + unsigned char mask, pmask; + + addr &= 0xffff; + + /* Read the four planes into latches */ + for (plane = 0; plane < 4; plane++, addr += 0x10000) { + dev->latch[plane] &= lp; + dev->latch[plane] |= (dev->vram[addr] & ~lp); + } + addr &= 0xffff; + + /* In text mode, reads from the bottom 16k assume all planes have + * the same contents */ + if (!(dev->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) { + return dev->latch[0]; + } + + /* For each pixel, work out if its colour matches the background */ + for (mask = 0x80; mask != 0; mask >>= 1) { + fg = 0; + dc = dev->crtc[INCOLOR_CRTC_RWCTRL] & 0x0F; + bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; + for (plane = 0, pmask = 1; plane < 4; plane++, pmask <<= 1) { + if (dc & pmask) { + fg |= (bg & pmask); + } else if (dev->latch[plane] & mask) { + fg |= pmask; } - } -} + } + if (bg == fg) value |= mask; + } -uint8_t incolor_read(uint32_t addr, void *p) -{ - incolor_t *incolor = (incolor_t *)p; - unsigned plane; - unsigned char lp = incolor->crtc[INCOLOR_CRTC_PROTECT]; - unsigned char value = 0; - unsigned char dc; /* "don't care" register */ - unsigned char bg; /* background colour */ - unsigned char fg; - unsigned char mask, pmask; + if (dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_POLARITY) + value = ~value; - egareads++; - - addr &= 0xFFFF; - /* Read the four planes into latches */ - for (plane = 0; plane < 4; plane++, addr += 0x10000) - { - incolor->latch[plane] &= lp; - incolor->latch[plane] |= (incolor->vram[addr] & ~lp); - } - addr &= 0xFFFF; - /* In text mode, reads from the bottom 16k assume all planes have - * the same contents */ - if (!(incolor->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) - { - return incolor->latch[0]; - } - /* For each pixel, work out if its colour matches the background */ - for (mask = 0x80; mask != 0; mask >>= 1) - { - fg = 0; - dc = incolor->crtc[INCOLOR_CRTC_RWCTRL] & 0x0F; - bg = (incolor->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; - for (plane = 0, pmask = 1; plane < 4; plane++, pmask <<= 1) - { - if (dc & pmask) - { - fg |= (bg & pmask); - } - else if (incolor->latch[plane] & mask) - { - fg |= pmask; - } - } - if (bg == fg) value |= mask; - } - if (incolor->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_POLARITY) - { - value = ~value; - } - return value; + return value; } - -void incolor_recalctimings(incolor_t *incolor) +static void +draw_char_rom(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - double disptime; - double _dispontime, _dispofftime; - disptime = incolor->crtc[0] + 1; - _dispontime = incolor->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - incolor->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - incolor->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_t attr) -{ - unsigned i; - int elg, blk; - unsigned ull; - unsigned val; + int i; + int elg, blk; + unsigned ull; + unsigned val; unsigned ifg, ibg; const unsigned char *fnt; uint32_t fg, bg; int cw = INCOLOR_CW; blk = 0; - if (incolor->ctrl & INCOLOR_CTRL_BLINK) + if (dev->ctrl & INCOLOR_CTRL_BLINK) { if (attr & 0x80) { - blk = (incolor->blink & 16); + blk = (dev->blink & 16); } attr &= 0x7f; } - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) { /* MDA-compatible attributes */ ibg = 0; @@ -441,19 +457,19 @@ static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_ ifg = attr & 0x0F; ibg = (attr >> 4) & 0x0F; } - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) { - fg = incolor_rgb[incolor->palette[ifg]]; - bg = incolor_rgb[incolor->palette[ibg]]; + fg = dev->rgb[dev->palette[ifg]]; + bg = dev->rgb[dev->palette[ibg]]; } else { - fg = incolor_rgb[defpal[ifg]]; - bg = incolor_rgb[defpal[ibg]]; + fg = dev->rgb[defpal[ifg]]; + bg = dev->rgb[defpal[ibg]]; } /* ELG set to stretch 8px character to 9px */ - if (incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { elg = 0; } @@ -462,13 +478,13 @@ static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_ elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = &(fontdatm[chr][incolor->sc]); + fnt = &(fontdatm[chr][dev->sc]); if (blk) { val = 0x000; /* Blinking, draw all background */ } - else if (incolor->sc == ull) + else if (dev->sc == ull) { val = 0x1ff; /* Underscore, draw all foreground */ } @@ -483,32 +499,33 @@ static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_ } for (i = 0; i < cw; i++) { - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + i] = (val & 0x100) ? fg : bg; + ((uint32_t *)buffer32->line[dev->displine])[x * cw + i] = (val & 0x100) ? fg : bg; val = val << 1; } } -static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8_t attr) +static void +draw_char_ram4(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - unsigned i; - int elg, blk; - unsigned ull; - unsigned val[4]; + int i; + int elg, blk; + unsigned ull; + unsigned val[4]; unsigned ifg, ibg, cfg, pmask, plane; const unsigned char *fnt; uint32_t fg; int cw = INCOLOR_CW; - int blink = incolor->ctrl & INCOLOR_CTRL_BLINK; - int altattr = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; - int palette = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; + int blink = dev->ctrl & INCOLOR_CTRL_BLINK; + int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; + int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; blk = 0; if (blink) { if (attr & 0x80) { - blk = (incolor->blink & 16); + blk = (dev->blink & 16); } attr &= 0x7f; } @@ -544,7 +561,7 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 ifg = attr & 0x0F; ibg = (attr >> 4) & 0x0F; } - if (incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { elg = 0; } @@ -552,14 +569,14 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 { elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = incolor->vram + 0x4000 + 16 * chr + incolor->sc; + fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; if (blk) { /* Blinking, draw all background */ val[0] = val[1] = val[2] = val[3] = 0x000; } - else if (incolor->sc == ull) + else if (dev->sc == ull) { /* Underscore, draw all foreground */ val[0] = val[1] = val[2] = val[3] = 0x1ff; @@ -593,14 +610,14 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 if (altattr && (attr & 0x77) == 0) cfg = ibg; /* 'blank' attribute */ if (palette) { - fg = incolor_rgb[incolor->palette[cfg]]; + fg = dev->rgb[dev->palette[cfg]]; } else { - fg = incolor_rgb[defpal[cfg]]; + fg = dev->rgb[defpal[cfg]]; } - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + i] = fg; + ((uint32_t *)buffer32->line[dev->displine])[x * cw + i] = fg; val[0] = val[0] << 1; val[1] = val[1] << 1; val[2] = val[2] << 1; @@ -609,19 +626,20 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 } -static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint8_t attr) +static void +draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - unsigned i; - int elg, blk, ul, ol, bld; - unsigned ull, oll, ulc = 0, olc = 0; - unsigned val[4]; + int i; + int elg, blk, ul, ol, bld; + unsigned ull, oll, ulc = 0, olc = 0; + unsigned val[4]; unsigned ifg = 0, ibg, cfg, pmask, plane; const unsigned char *fnt; uint32_t fg; int cw = INCOLOR_CW; - int blink = incolor->ctrl & INCOLOR_CTRL_BLINK; - int altattr = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; - int palette = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; + int blink = dev->ctrl & INCOLOR_CTRL_BLINK; + int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; + int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; int font = (attr & 0x0F); if (font >= 12) font &= 7; @@ -631,7 +649,7 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint { if (attr & 0x40) { - blk = (incolor->blink & 16); + blk = (dev->blink & 16); } attr &= 0x7f; } @@ -664,8 +682,8 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } if (ul) { - ull = incolor->crtc[INCOLOR_CRTC_UNDER] & 0x0F; - ulc = (incolor->crtc[INCOLOR_CRTC_UNDER] >> 4) & 0x0F; + ull = dev->crtc[INCOLOR_CRTC_UNDER] & 0x0F; + ulc = (dev->crtc[INCOLOR_CRTC_UNDER] >> 4) & 0x0F; if (ulc == 0) ulc = 7; } else @@ -674,8 +692,8 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } if (ol) { - oll = incolor->crtc[INCOLOR_CRTC_OVER] & 0x0F; - olc = (incolor->crtc[INCOLOR_CRTC_OVER] >> 4) & 0x0F; + oll = dev->crtc[INCOLOR_CRTC_OVER] & 0x0F; + olc = (dev->crtc[INCOLOR_CRTC_OVER] >> 4) & 0x0F; if (olc == 0) olc = 7; } else @@ -683,7 +701,7 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint oll = 0xFFFF; } - if (incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { elg = 0; } @@ -691,14 +709,14 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint { elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = incolor->vram + 0x4000 + 16 * chr + 4096 * font + incolor->sc; + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; if (blk) { /* Blinking, draw all background */ val[0] = val[1] = val[2] = val[3] = 0x000; } - else if (incolor->sc == ull) + else if (dev->sc == ull) { /* Underscore, draw all foreground */ val[0] = val[1] = val[2] = val[3] = 0x1ff; @@ -730,11 +748,11 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint /* Generate pixel colour */ cfg = 0; pmask = 1; - if (incolor->sc == oll) + if (dev->sc == oll) { cfg = olc ^ ibg; /* Strikethrough */ } - else if (incolor->sc == ull) + else if (dev->sc == ull) { cfg = ulc ^ ibg; /* Underline */ } @@ -752,14 +770,14 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } if (palette) { - fg = incolor_rgb[incolor->palette[cfg]]; + fg = dev->rgb[dev->palette[cfg]]; } else { - fg = incolor_rgb[defpal[cfg]]; + fg = dev->rgb[defpal[cfg]]; } - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + i] = fg; + ((uint32_t *)buffer32->line[dev->displine])[x * cw + i] = fg; val[0] = val[0] << 1; val[1] = val[1] << 1; val[2] = val[2] << 1; @@ -768,319 +786,302 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } - - - - -static void incolor_text_line(incolor_t *incolor, uint16_t ca) +static void +text_line(incolor_t *dev, uint16_t ca) { - int drawcursor; - int x, c; - uint8_t chr, attr; - uint32_t col; + int drawcursor; + int x, c; + uint8_t chr, attr; + uint32_t col; - for (x = 0; x < incolor->crtc[1]; x++) - { - chr = incolor->vram[(incolor->ma << 1) & 0xfff]; - attr = incolor->vram[((incolor->ma << 1) + 1) & 0xfff]; + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; - drawcursor = ((incolor->ma == ca) && incolor->con && incolor->cursoron); + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - switch (incolor->crtc[INCOLOR_CRTC_XMODE] & 5) + switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) { + case 0: + case 4: /* ROM font */ + draw_char_rom(dev, x, chr, attr); + break; + + case 1: /* 4k RAMfont */ + draw_char_ram4(dev, x, chr, attr); + break; + + case 5: /* 48k RAMfont */ + draw_char_ram48(dev, x, chr, attr); + break; + } + ++dev->ma; + + if (drawcursor) { + int cw = INCOLOR_CW; + uint8_t ink = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_CURSOR; + if (ink == 0) ink = (attr & 0x08) | 7; + + /* In MDA-compatible mode, cursor brightness comes from + * background */ + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) { - case 0: - case 4: /* ROM font */ - incolor_draw_char_rom(incolor, x, chr, attr); - break; - case 1: /* 4k RAMfont */ - incolor_draw_char_ram4(incolor, x, chr, attr); - break; - case 5: /* 48k RAMfont */ - incolor_draw_char_ram48(incolor, x, chr, attr); - break; - + ink = (attr & 0x08) | (ink & 7); } - ++incolor->ma; - if (drawcursor) - { - int cw = INCOLOR_CW; - uint8_t ink = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_CURSOR; - if (ink == 0) ink = (attr & 0x08) | 7; - - /* In MDA-compatible mode, cursor brightness comes from - * background */ - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) - { - ink = (attr & 0x08) | (ink & 7); - } - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - { - col = incolor_rgb[incolor->palette[ink]]; - } - else - { - col = incolor_rgb[defpal[ink]]; - } - for (c = 0; c < cw; c++) - { - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + c] = col; - } - } - } -} - - -static void incolor_graphics_line(incolor_t *incolor) -{ - uint8_t mask; - uint16_t ca; - int x, c, plane, col; - uint8_t ink; - uint16_t val[4]; - - /* Graphics mode. */ - ca = (incolor->sc & 3) * 0x2000; - if ((incolor->ctrl & INCOLOR_CTRL_PAGE1) && (incolor->ctrl2 & INCOLOR_CTRL2_PAGE1)) - ca += 0x8000; - - for (x = 0; x < incolor->crtc[1]; x++) - { - mask = incolor->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ - for (plane = 0; plane < 4; plane++, mask = mask >> 1) + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) { - if (mask & 1) - val[plane] = (incolor->vram[((incolor->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | - incolor->vram[((incolor->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; - else val[plane] = 0; - } - incolor->ma++; - for (c = 0; c < 16; c++) + col = dev->rgb[dev->palette[ink]]; + } + else { - ink = 0; - for (plane = 0; plane < 4; plane++) - { - ink = ink >> 1; - if (val[plane] & 0x8000) ink |= 8; - val[plane] = val[plane] << 1; - } - /* Is palette in use? */ - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - col = incolor->palette[ink]; - else col = defpal[ink]; - - ((uint32_t *)buffer32->line[incolor->displine])[(x << 4) + c] = incolor_rgb[col]; + col = dev->rgb[defpal[ink]]; + } + for (c = 0; c < cw; c++) + { + ((uint32_t *)buffer32->line[dev->displine])[x * cw + c] = col; } } + } } -void incolor_poll(void *p) + +static void +graphics_line(incolor_t *dev) { - incolor_t *incolor = (incolor_t *)p; - uint16_t ca = (incolor->crtc[15] | (incolor->crtc[14] << 8)) & 0x3fff; - int x; - int oldvc; - int oldsc; + uint8_t mask; + uint16_t ca; + int x, c, plane, col; + uint8_t ink; + uint16_t val[4]; - if (!incolor->linepos) - { - incolor->vidtime += incolor->dispofftime; - incolor->stat |= 1; - incolor->linepos = 1; - oldsc = incolor->sc; - if ((incolor->crtc[8] & 3) == 3) - incolor->sc = (incolor->sc << 1) & 7; - if (incolor->dispon) - { - if (incolor->displine < incolor->firstline) - { - incolor->firstline = incolor->displine; - video_wait_for_buffer(); - } - incolor->lastline = incolor->displine; - if ((incolor->ctrl & INCOLOR_CTRL_GRAPH) && (incolor->ctrl2 & INCOLOR_CTRL2_GRAPH)) - { - incolor_graphics_line(incolor); - } - else - { - incolor_text_line(incolor, ca); - } - } - incolor->sc = oldsc; - if (incolor->vc == incolor->crtc[7] && !incolor->sc) - { - incolor->stat |= 8; - } - incolor->displine++; - if (incolor->displine >= 500) - incolor->displine = 0; - } - else - { - incolor->vidtime += incolor->dispontime; - if (incolor->dispon) - incolor->stat &= ~1; - incolor->linepos = 0; - if (incolor->vsynctime) - { - incolor->vsynctime--; - if (!incolor->vsynctime) - { - incolor->stat &= ~8; - } - } - if (incolor->sc == (incolor->crtc[11] & 31) || ((incolor->crtc[8] & 3) == 3 && incolor->sc == ((incolor->crtc[11] & 31) >> 1))) - { - incolor->con = 0; - incolor->coff = 1; - } - if (incolor->vadj) - { - incolor->sc++; - incolor->sc &= 31; - incolor->ma = incolor->maback; - incolor->vadj--; - if (!incolor->vadj) - { - incolor->dispon = 1; - incolor->ma = incolor->maback = (incolor->crtc[13] | (incolor->crtc[12] << 8)) & 0x3fff; - incolor->sc = 0; - } - } - else if (incolor->sc == incolor->crtc[9] || ((incolor->crtc[8] & 3) == 3 && incolor->sc == (incolor->crtc[9] >> 1))) - { - incolor->maback = incolor->ma; - incolor->sc = 0; - oldvc = incolor->vc; - incolor->vc++; - incolor->vc &= 127; - if (incolor->vc == incolor->crtc[6]) - incolor->dispon = 0; - if (oldvc == incolor->crtc[4]) - { - incolor->vc = 0; - incolor->vadj = incolor->crtc[5]; - if (!incolor->vadj) incolor->dispon=1; - if (!incolor->vadj) incolor->ma = incolor->maback = (incolor->crtc[13] | (incolor->crtc[12] << 8)) & 0x3fff; - if ((incolor->crtc[10] & 0x60) == 0x20) incolor->cursoron = 0; - else incolor->cursoron = incolor->blink & 16; - } - if (incolor->vc == incolor->crtc[7]) - { - incolor->dispon = 0; - incolor->displine = 0; - incolor->vsynctime = 16; - if (incolor->crtc[7]) - { - if ((incolor->ctrl & INCOLOR_CTRL_GRAPH) && (incolor->ctrl2 & INCOLOR_CTRL2_GRAPH)) - { - x = incolor->crtc[1] << 4; - } - else - { - x = incolor->crtc[1] * 9; - } - incolor->lastline++; - if ((x != xsize) || ((incolor->lastline - incolor->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = incolor->lastline - incolor->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + /* Graphics mode. */ + ca = (dev->sc & 3) * 0x2000; + if ((dev->ctrl & INCOLOR_CTRL_PAGE1) && (dev->ctrl2 & INCOLOR_CTRL2_PAGE1)) + ca += 0x8000; - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, incolor->firstline, 0, incolor->lastline - incolor->firstline, xsize, incolor->lastline - incolor->firstline); - frames++; - if ((incolor->ctrl & INCOLOR_CTRL_GRAPH) && (incolor->ctrl2 & INCOLOR_CTRL2_GRAPH)) - { - video_res_x = incolor->crtc[1] * 16; - video_res_y = incolor->crtc[6] * 4; - video_bpp = 1; - } - else - { - video_res_x = incolor->crtc[1]; - video_res_y = incolor->crtc[6]; - video_bpp = 0; - } - } - incolor->firstline = 1000; - incolor->lastline = 0; - incolor->blink++; - } - } - else - { - incolor->sc++; - incolor->sc &= 31; - incolor->ma = incolor->maback; - } - if ((incolor->sc == (incolor->crtc[10] & 31) || ((incolor->crtc[8] & 3) == 3 && incolor->sc == ((incolor->crtc[10] & 31) >> 1)))) - { - incolor->con = 1; - } - } -} - -void *incolor_init(const device_t *info) -{ - int c; - incolor_t *incolor = malloc(sizeof(incolor_t)); - memset(incolor, 0, sizeof(incolor_t)); - video_inform(VIDEO_FLAG_TYPE_MDA, &timing_incolor); - - incolor->vram = malloc(0x40000); /* 4 planes of 64k */ - - timer_add(incolor_poll, &incolor->vidtime, TIMER_ALWAYS_ENABLED, incolor); - mem_mapping_add(&incolor->mapping, 0xb0000, 0x08000, incolor_read, NULL, NULL, incolor_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, incolor); - io_sethandler(0x03b0, 0x0010, incolor_in, NULL, NULL, incolor_out, NULL, NULL, incolor); - - for (c = 0; c < 64; c++) + for (x = 0; x < dev->crtc[1]; x++) { + mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ + for (plane = 0; plane < 4; plane++, mask = mask >> 1) { - incolor_rgb[c] = makecol32(init_rgb[c][0], init_rgb[c][1], init_rgb[c][2]); + if (mask & 1) + val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + else val[plane] = 0; + } + dev->ma++; + + for (c = 0; c < 16; c++) + { + ink = 0; + for (plane = 0; plane < 4; plane++) + { + ink = ink >> 1; + if (val[plane] & 0x8000) ink |= 8; + val[plane] = val[plane] << 1; + } + /* Is palette in use? */ + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) + col = dev->palette[ink]; + else col = defpal[ink]; + + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c] = dev->rgb[col]; + } + } +} + + +static void +incolor_poll(void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int x; + int oldvc; + int oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) + graphics_line(dev); + else + text_line(dev, ca); + } + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; } -/* Initialise CRTC regs to safe values */ - incolor->crtc[INCOLOR_CRTC_MASK ] = 0x0F; /* All planes displayed */ - incolor->crtc[INCOLOR_CRTC_RWCTRL] = INCOLOR_RWCTRL_POLARITY; - incolor->crtc[INCOLOR_CRTC_RWCOL ] = 0x0F; /* White on black */ - incolor->crtc[INCOLOR_CRTC_EXCEPT] = INCOLOR_EXCEPT_ALTATTR; - for (c = 0; c < 16; c++) - { - incolor->palette[c] = defpal[c]; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; } - incolor->palette_idx = 0; - lpt3_init(0x3BC); + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) dev->dispon=1; + if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) dev->cursoron = 0; + else dev->cursoron = dev->blink & 16; + } - return incolor; + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + frames++; + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } } -void incolor_close(void *p) -{ - incolor_t *incolor = (incolor_t *)p; - free(incolor->vram); - free(incolor); +static void * +incolor_init(const device_t *info) +{ + incolor_t *dev; + int c; + + dev = (incolor_t *)malloc(sizeof(incolor_t)); + memset(dev, 0x00, sizeof(incolor_t)); + + dev->vram = (uint8_t *)malloc(0x40000); /* 4 planes of 64k */ + + timer_add(incolor_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, + incolor_read,NULL,NULL, incolor_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + incolor_in,NULL,NULL, incolor_out,NULL,NULL, dev); + + for (c = 0; c < 64; c++) { + dev->rgb[c] = makecol32(init_rgb[c][0], init_rgb[c][1], init_rgb[c][2]); + } + + /* Initialise CRTC regs to safe values */ + dev->crtc[INCOLOR_CRTC_MASK ] = 0x0F; /* All planes displayed */ + dev->crtc[INCOLOR_CRTC_RWCTRL] = INCOLOR_RWCTRL_POLARITY; + dev->crtc[INCOLOR_CRTC_RWCOL ] = 0x0F; /* White on black */ + dev->crtc[INCOLOR_CRTC_EXCEPT] = INCOLOR_EXCEPT_ALTATTR; + for (c = 0; c < 16; c++) + dev->palette[c] = defpal[c]; + dev->palette_idx = 0; + + video_inform(VIDEO_FLAG_TYPE_MDA, &timing_incolor); + + /* Force the LPT3 port to be enabled. */ + lpt3_init(0x3BC); + + return dev; } -void incolor_speed_changed(void *p) + +static void +incolor_close(void *priv) { - incolor_t *incolor = (incolor_t *)p; - - incolor_recalctimings(incolor); + incolor_t *dev = (incolor_t *)priv; + + free(dev->vram); + free(dev); } -const device_t incolor_device = + +static void +speed_changed(void *priv) { - "Hercules InColor", - DEVICE_ISA, 0, - incolor_init, incolor_close, NULL, - NULL, - incolor_speed_changed, - NULL, - NULL + incolor_t *dev = (incolor_t *)priv; + + recalc_timings(dev); +} + + +const device_t incolor_device = { + "Hercules InColor", + DEVICE_ISA, + 0, + incolor_init, incolor_close, NULL, + NULL, + speed_changed, + NULL, + NULL };