From 3d9f7706034e57a109f851a895b6e1e8c61a6fcb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 28 Oct 2018 08:26:07 +0100 Subject: [PATCH] Implemented the Hercules graphics mode blend. --- src/video/vid_hercules.c | 12 +++++-- src/video/vid_herculesplus.c | 49 ++++++++++++++++++++++--- src/video/video.c | 69 ++++++++++++++++++++++++++++++++++-- src/video/video.h | 8 +++-- 4 files changed, 126 insertions(+), 12 deletions(-) diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 784e6391d..04d3df04f 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.14 2018/10/11 + * Version: @(#)vid_hercules.c 1.0.15 2018/10/28 * * Authors: Sarah Walker, * Miran Grca, @@ -223,8 +223,11 @@ hercules_poll(void *priv) 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++) + for (c = 0; c < 16; c++) { buffer->line[dev->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; + } + for (c = 0; c < 16; c += 8) + video_blend((x << 4) + c, dev->displine); } } else { for (x = 0; x < dev->crtc[1]; x++) { @@ -416,6 +419,8 @@ hercules_init(const device_t *info) cga_palette = 0; cgapal_rebuild(); + herc_blend = device_get_config_int("blend"); + video_inform(VIDEO_FLAG_TYPE_MDA, &timing_hercules); /* Force the LPT3 port to be enabled. */ @@ -470,6 +475,9 @@ static const device_config_t hercules_config[] = { } } }, + { + "blend", "Blend", CONFIG_BINARY, "", 1 + }, { "", "", -1 } diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 5a2ed1f6f..c69424382 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules Plus emulation. * - * Version: @(#)vid_herculesplus.c 1.0.12 2018/10/11 + * Version: @(#)vid_herculesplus.c 1.0.13 2018/10/28 * * Authors: Sarah Walker, * Miran Grca, @@ -440,7 +440,7 @@ text_line(herculesplus_t *dev, uint16_t ca) col = dev->cols[attr][0][1]; for (c = 0; c < cw; c++) - ((uint32_t *)buffer32->line[dev->displine])[x * cw + c] = col; + buffer->line[dev->displine][x * cw + c] = col; } } } @@ -466,8 +466,11 @@ graphics_line(herculesplus_t *dev) for (c = 0; c < 16; c++) { val >>= 1; - ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c] = (val & 1) ? 7 : 0; + buffer->line[dev->displine][(x << 4) + c] = (val & 1) ? 7 : 0; } + + for (c = 0; c < 16; c += 8) + video_blend((x << 4) + c, dev->displine); } } @@ -566,7 +569,7 @@ herculesplus_poll(void *priv) 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); + video_blit_memtoscreen_8(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; @@ -639,6 +642,13 @@ herculesplus_init(const device_t *info) dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; + herc_blend = device_get_config_int("blend"); + + 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_herculesplus); /* Force the LPT3 port to be enabled. */ @@ -672,6 +682,35 @@ speed_changed(void *priv) } +static const device_config_t herculesplus_config[] = { + { + "rgb_type", "Display type", CONFIG_SELECTION, "", 0, + { + { + "Default", 0 + }, + { + "Green", 1 + }, + { + "Amber", 2 + }, + { + "Gray", 3 + }, + { + "" + } + } + }, + { + "blend", "Blend", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } +}; + const device_t herculesplus_device = { "Hercules Plus", DEVICE_ISA, @@ -680,5 +719,5 @@ const device_t herculesplus_device = { NULL, speed_changed, NULL, - NULL + herculesplus_config }; diff --git a/src/video/video.c b/src/video/video.c index ff072679a..2741958a2 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.28 2018/10/22 + * Version: @(#)video.c 1.0.29 2018/10/28 * * Authors: Sarah Walker, * Miran Grca, @@ -78,7 +78,8 @@ dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */ uint32_t pal_lookup[256]; int xsize = 1, ysize = 1; -int cga_palette = 0; +int cga_palette = 0, + herc_blend = 0; uint32_t *video_6to8 = NULL, *video_15to32 = NULL, *video_16to32 = NULL; @@ -106,6 +107,7 @@ int video_grayscale = 0; int video_graytype = 0; static int vid_type; static const video_timings_t *vid_timings; +static uint32_t cga_2_table[16]; PALETTE cgapal = { @@ -323,6 +325,63 @@ video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) } +uint8_t pixels8(uint8_t *pixels) +{ + int i; + uint8_t temp = 0; + + for (i = 0; i < 8; i++) + temp |= (!!*(pixels + i) << (i ^ 7)); + + return temp; +} + + +uint32_t pixel_to_color(uint8_t *pixels32, uint8_t pos) +{ + uint32_t temp; + temp = *(pixels32 + pos) & 0x03; + switch (temp) { + case 0: + default: + return 0x00; + case 1: + return 0x07; + case 2: + return 0x0f; + } +} + + +static unsigned int carry = 0; + + +void +video_blend(int x, int y) +{ + int xx; + + uint32_t pixels32_1, pixels32_2; + unsigned int val1, val2; + + if (!herc_blend) + return; + + if (!x) + carry = 0; + + val1 = pixels8(&(buffer->line[y][x])); + val2 = (val1 >> 1) + carry; + carry = (val1 & 1) << 7; + pixels32_1 = cga_2_table[val1 >> 4] + cga_2_table[val2 >> 4]; + pixels32_2 = cga_2_table[val1 & 0xf] + cga_2_table[val2 & 0xf]; + for (xx = 0; xx < 4; xx++) { + buffer->line[y][x + xx] = pixel_to_color((uint8_t *) &pixels32_1, xx); + buffer->line[y][x + (xx | 4)] = pixel_to_color((uint8_t *) &pixels32_2, xx); + } +} + + void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) { @@ -564,6 +623,12 @@ void video_init(void) { int c, d, e; + uint8_t total[2] = { 0, 1 }; + + for (c = 0; c < 16; c++) { + cga_2_table[c] = (total[(c >> 3) & 1] << 0 ) | (total[(c >> 2) & 1] << 8 ) | + (total[(c >> 1) & 1] << 16) | (total[(c >> 0) & 1] << 24); + } /* Account for overscan. */ buffer32 = create_bitmap(2048, 2048); diff --git a/src/video/video.h b/src/video/video.h index a86cb8df9..e42c122cc 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.35 2018/09/19 + * Version: @(#)video.h 1.0.36 2018/10/28 * * Authors: Sarah Walker, * Miran Grca, @@ -115,7 +115,8 @@ extern int video_res_x, video_res_y, video_bpp; extern int vid_resize; -extern int cga_palette; +extern int cga_palette, + herc_blend; extern int vid_cga_contrast; extern int video_grayscale; extern int video_graytype; @@ -148,8 +149,9 @@ extern int video_get_type(void); extern void video_setblit(void(*blit)(int,int,int,int,int,int)); -extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +extern void video_blend(int x, int y); extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h); +extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); extern void video_blit_complete(void); extern void video_wait_for_blit(void); extern void video_wait_for_buffer(void);