From c0fe1ceea5d95172a3a350a77bef510eb816b48b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 27 Aug 2025 00:46:17 +0200 Subject: [PATCH] Implement the line doubling mode selection on the Amstrad PC1512 and PC1640, with None as default, and make the None mode on all 4 cards (the two Amstrads, CGA, and Yamaha V6355) operate like PCem. --- src/include/86box/vid_cga.h | 16 +- src/machine/m_amstrad.c | 350 ++++++++++++++++++++++-------------- src/video/vid_cga.c | 112 ++++++------ src/video/vid_cga_v6355.c | 146 ++------------- 4 files changed, 300 insertions(+), 324 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 2198154ed..3f99e15a9 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -116,13 +116,15 @@ typedef struct cga_t { int double_type; } cga_t; -void cga_init(cga_t *cga); -void cga_out(uint16_t addr, uint8_t val, void *priv); -uint8_t cga_in(uint16_t addr, void *priv); -void cga_write(uint32_t addr, uint8_t val, void *priv); -uint8_t cga_read(uint32_t addr, void *priv); -void cga_recalctimings(cga_t *cga); -void cga_poll(void *priv); +extern void cga_init(cga_t *cga); +extern void cga_out(uint16_t addr, uint8_t val, void *priv); +extern uint8_t cga_in(uint16_t addr, void *priv); +extern void cga_write(uint32_t addr, uint8_t val, void *priv); +extern uint8_t cga_read(uint32_t addr, void *priv); +extern void cga_recalctimings(cga_t *cga); +extern void cga_interpolate_init(void); +extern void cga_do_blit(int vid_xsize, int firstline, int lastline, int double_type); +extern void cga_poll(void *priv); //#ifdef EMU_DEVICE_H //extern const device_config_t cga_config[]; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index b4bc0a54f..809a4a701 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -86,6 +86,11 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 +#define DOUBLE_NONE 0 +#define DOUBLE_SIMPLE 1 +#define DOUBLE_INTERPOLATE_SRGB 2 +#define DOUBLE_INTERPOLATE_LINEAR 3 + typedef struct amsvid_t { rom_t bios_rom; /* 1640 */ cga_t cga; /* 1640/200 */ @@ -123,6 +128,7 @@ typedef struct amsvid_t { int vsynctime; int fullchange; int vadj; + int double_type; uint16_t memaddr; uint16_t memaddr_backup; int dispon; @@ -339,15 +345,12 @@ vid_read_1512(uint32_t addr, void *priv) } static void -vid_poll_1512(void *priv) +ams1512_render(amsvid_t *vid, int line) { - amsvid_t *vid = (amsvid_t *) priv; uint16_t cursoraddr = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; int drawcursor; int x; int c; - int xs_temp; - int ys_temp; uint8_t chr; uint8_t attr; uint16_t dat; @@ -356,7 +359,142 @@ vid_poll_1512(void *priv) uint16_t dat4; int cols[4]; int col; + + for (c = 0; c < 8; c++) { + if ((vid->cgamode & 0x12) == 0x12) { + buffer32->line[line][c] = buffer32->line[(line) + 1][c] = (vid->border & 15) + 16; + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { + buffer32->line[line][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(line) + 1][c + (vid->crtc[1] << 3) + 8] = 0; + } else { + buffer32->line[line][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(line) + 1][c + (vid->crtc[1] << 4) + 8] = 0; + } + } else { + buffer32->line[line][c] = buffer32->line[(line) + 1][c] = (vid->cgacol & 15) + 16; + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { + buffer32->line[line][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(line) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16; + } else { + buffer32->line[line][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(line) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16; + } + } + } + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { + for (x = 0; x < 80; x++) { + chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; + attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; + drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron); + if (vid->cgamode & CGA_MODE_FLAG_BLINK) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + if (drawcursor) + for (c = 0; c < 8; c++) + buffer32->line[line][(x << 3) + c + 8] = + cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + else + for (c = 0; c < 8; c++) + buffer32->line[line][(x << 3) + c + 8] = + cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; + vid->memaddr++; + } + } else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) { + for (x = 0; x < 40; x++) { + chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; + attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; + drawcursor = ((vid->memaddr == cursoraddr) && vid->cursorvisible && vid->cursoron); + + if (vid->cgamode & CGA_MODE_FLAG_BLINK) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((vid->blink & 16) && (attr & 0x80)) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + vid->memaddr++; + if (drawcursor) + for (c = 0; c < 8; c++) + buffer32->line[line][(x << 4) + (c << 1) + 8] = + buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + else + for (c = 0; c < 8; c++) + buffer32->line[line][(x << 4) + (c << 1) + 8] = + buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { + cols[0] = (vid->cgacol & 15) | 16; + col = (vid->cgacol & 16) ? 24 : 16; + if (vid->cgamode & CGA_MODE_FLAG_BW) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (vid->cgacol & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + for (x = 0; x < 40; x++) { + dat = (vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | + vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1]; + vid->memaddr++; + for (c = 0; c < 8; c++) { + buffer32->line[line][(x << 4) + (c << 1) + 8] = + buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + for (x = 0; x < 40; x++) { + cursoraddr = ((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000); + dat = (vid->vram[cursoraddr] << 8) | vid->vram[cursoraddr + 1]; + dat2 = (vid->vram[cursoraddr + 0x4000] << 8) | vid->vram[cursoraddr + 0x4001]; + dat3 = (vid->vram[cursoraddr + 0x8000] << 8) | vid->vram[cursoraddr + 0x8001]; + dat4 = (vid->vram[cursoraddr + 0xc000] << 8) | vid->vram[cursoraddr + 0xc001]; + + vid->memaddr++; + for (c = 0; c < 16; c++) { + buffer32->line[line][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | + ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; + dat <<= 1; + dat2 <<= 1; + dat3 <<= 1; + dat4 <<= 1; + } + } + } +} + +static void +ams1512_render_blank(amsvid_t *vid, int line) +{ + int cols = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; + + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) + hline(buffer32, 0, line, (vid->crtc[1] << 3) + 16, cols); + else + hline(buffer32, 0, line, (vid->crtc[1] << 4) + 16, cols); +} + +static void +vid_poll_1512(void *priv) +{ + amsvid_t *vid = (amsvid_t *) priv; + int x; + int xs_temp; + int ys_temp; int scanline_old; + int old_ma; if (!vid->linepos) { timer_advance_u64(&vid->timer, vid->dispofftime); @@ -369,126 +507,32 @@ vid_poll_1512(void *priv) video_wait_for_buffer(); } vid->lastline = vid->displine; - for (c = 0; c < 8; c++) { - if ((vid->cgamode & 0x12) == 0x12) { - buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->border & 15) + 16; - if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; - } else { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; - } - } else { - buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->cgacol & 15) + 16; - if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16; - } else { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16; - } - } - } - if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { - for (x = 0; x < 80; x++) { - chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; - attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; - drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron); - if (vid->cgamode & CGA_MODE_FLAG_BLINK) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - vid->memaddr++; - } - } else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) { - for (x = 0; x < 40; x++) { - chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; - attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; - drawcursor = ((vid->memaddr == cursoraddr) - && vid->cursorvisible && vid->cursoron); - - if (vid->cgamode & CGA_MODE_FLAG_BLINK) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80)) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - vid->memaddr++; - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { - cols[0] = (vid->cgacol & 15) | 16; - col = (vid->cgacol & 16) ? 24 : 16; - if (vid->cgamode & CGA_MODE_FLAG_BW) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->cgacol & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < 40; x++) { - dat = (vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1]; - vid->memaddr++; - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - for (x = 0; x < 40; x++) { - cursoraddr = ((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000); - dat = (vid->vram[cursoraddr] << 8) | vid->vram[cursoraddr + 1]; - dat2 = (vid->vram[cursoraddr + 0x4000] << 8) | vid->vram[cursoraddr + 0x4001]; - dat3 = (vid->vram[cursoraddr + 0x8000] << 8) | vid->vram[cursoraddr + 0x8001]; - dat4 = (vid->vram[cursoraddr + 0xc000] << 8) | vid->vram[cursoraddr + 0xc001]; - - vid->memaddr++; - for (c = 0; c < 16; c++) { - buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; - dat <<= 1; - dat2 <<= 1; - dat3 <<= 1; - dat4 <<= 1; - } - } - } - } else { - cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; - if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); - } else { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); + switch (vid->double_type) { + default: + ams1512_render(vid, vid->displine << 1); + ams1512_render_blank(vid, (vid->displine << 1) + 1); + break; + case DOUBLE_NONE: + ams1512_render(vid, vid->displine); + break; + case DOUBLE_SIMPLE: + old_ma = vid->memaddr; + ams1512_render(vid, vid->displine << 1); + vid->memaddr = old_ma; + ams1512_render(vid, (vid->displine << 1) + 1); + break; } + } else switch (vid->double_type) { + default: + ams1512_render_blank(vid, vid->displine << 1); + break; + case DOUBLE_NONE: + ams1512_render_blank(vid, vid->displine); + break; + case DOUBLE_SIMPLE: + ams1512_render_blank(vid, vid->displine << 1); + ams1512_render_blank(vid, (vid->displine << 1) + 1); + break; } if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) @@ -496,8 +540,15 @@ vid_poll_1512(void *priv) else x = (vid->crtc[1] << 4) + 16; - video_process_8((x < 64) ? 656 : x, vid->displine << 1); - video_process_8((x < 64) ? 656 : x, (vid->displine << 1) + 1); + switch (vid->double_type) { + default: + video_process_8((x < 64) ? 656 : x, vid->displine << 1); + video_process_8((x < 64) ? 656 : x, (vid->displine << 1) + 1); + break; + case DOUBLE_NONE: + video_process_8((x < 64) ? 656 : x, vid->displine); + break; + } vid->scanline = scanline_old; if (vid->vsynctime) @@ -576,13 +627,7 @@ vid_poll_1512(void *priv) video_force_resize_set(0); } - if (enable_overscan) { - video_blit_memtoscreen(0, (vid->firstline - 4) << 1, - xsize, ((vid->lastline - vid->firstline) + 8) << 1); - } else { - video_blit_memtoscreen(8, vid->firstline << 1, - xsize, (vid->lastline - vid->firstline) << 1); - } + cga_do_blit(xsize, vid->firstline, vid->lastline, vid->double_type); } video_res_x = xsize; @@ -644,6 +689,9 @@ vid_init_1512(amstrad_t *ams) cga_palette = (device_get_config_int("display_type") << 1); cgapal_rebuild(); + vid->double_type = device_get_config_int("double_type"); + cga_interpolate_init(); + ams->vid = vid; } @@ -681,6 +729,23 @@ const device_config_t vid_1512_config[] = { { .description = "" } } }, + { + .name = "double_type", + .description = "Line doubling type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = DOUBLE_NONE, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = DOUBLE_NONE }, + { .description = "Simple doubling", .value = DOUBLE_SIMPLE }, + { .description = "sRGB interpolation", .value = DOUBLE_INTERPOLATE_SRGB }, + { .description = "Linear interpolation", .value = DOUBLE_INTERPOLATE_LINEAR }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "codepage", .description = "Hardware font", @@ -852,6 +917,10 @@ vid_init_1640(amstrad_t *ams) cga_palette = 0; cgapal_rebuild(); + vid->double_type = device_get_config_int("double_type"); + vid->cga.double_type = device_get_config_int("double_type"); + cga_interpolate_init(); + ams->vid = vid; } @@ -875,6 +944,23 @@ vid_speed_changed_1640(void *priv) const device_config_t vid_1640_config[] = { // clang-format off + { + .name = "double_type", + .description = "Line doubling type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = DOUBLE_NONE, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = DOUBLE_NONE }, + { .description = "Simple doubling", .value = DOUBLE_SIMPLE }, + { .description = "sRGB interpolation", .value = DOUBLE_INTERPOLATE_SRGB }, + { .description = "Linear interpolation", .value = DOUBLE_INTERPOLATE_LINEAR }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "language", .description = "BIOS language", diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 01870ae94..8d482b93c 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -454,10 +454,10 @@ cga_interpolate_linear(uint8_t co1, uint8_t co2, double fraction) } static color_t -cga_interpolate_lookup(cga_t *cga, color_t color1, color_t color2, UNUSED(double fraction)) +cga_interpolate_lookup(color_t color1, color_t color2, int double_type) { color_t ret; - uint8_t dt = cga->double_type - DOUBLE_INTERPOLATE_SRGB; + uint8_t dt = double_type - DOUBLE_INTERPOLATE_SRGB; ret.a = 0x00; ret.r = interp_lut[dt][color1.r][color2.r]; @@ -468,10 +468,8 @@ cga_interpolate_lookup(cga_t *cga, color_t color1, color_t color2, UNUSED(double } static void -cga_interpolate(cga_t *cga, int x, int y, int w, int h) +cga_interpolate(int x, int y, int w, int h, int double_type) { - double quotient = 0.5; - for (int i = y; i < (y + h); i++) { if (i & 1) for (int j = x; j < (x + w); j++) { int prev = i - 1; @@ -496,24 +494,57 @@ cga_interpolate(cga_t *cga, int x, int y, int w, int h) else next_color.color = 0x00000000; - interim_1 = cga_interpolate_lookup(cga, prev_color, black, quotient); - interim_2 = cga_interpolate_lookup(cga, black, next_color, quotient); - final = cga_interpolate_lookup(cga, interim_1, interim_2, quotient); + interim_1 = cga_interpolate_lookup(prev_color, black, double_type); + interim_2 = cga_interpolate_lookup(black, next_color, double_type); + final = cga_interpolate_lookup(interim_1, interim_2, double_type); buffer32->line[i][j] = final.color; } } } -static void -cga_blit_memtoscreen(cga_t *cga, int x, int y, int w, int h) +void +cga_interpolate_init(void) { - if (cga->double_type > DOUBLE_SIMPLE) - cga_interpolate(cga, x, y, w, h); + for (uint16_t i = 0; i < 256; i++) { + for (uint16_t j = 0; j < 256; j++) { + interp_lut[0][i][j] = cga_interpolate_srgb(i, j, 0.5); + interp_lut[1][i][j] = cga_interpolate_linear(i, j, 0.5); + } + } +} + +static void +cga_blit_memtoscreen(int x, int y, int w, int h, int double_type) +{ + if (double_type > DOUBLE_SIMPLE) + cga_interpolate(x, y, w, h, double_type); video_blit_memtoscreen(x, y, w, h); } +void +cga_do_blit(int vid_xsize, int firstline, int lastline, int double_type) +{ + if (double_type > DOUBLE_NONE) { + if (enable_overscan) + cga_blit_memtoscreen(0, (firstline - 4) << 1, + vid_xsize, ((lastline - firstline) << 1) + 16, + double_type); + else + cga_blit_memtoscreen(8, firstline << 1, + vid_xsize, (lastline - firstline) << 1, + double_type); + } else { + if (enable_overscan) + video_blit_memtoscreen(0, firstline - 4, + vid_xsize, (lastline - firstline) + 8); + else + video_blit_memtoscreen(8, firstline, + vid_xsize, lastline - firstline); + } +} + void cga_poll(void *priv) { @@ -553,19 +584,17 @@ cga_poll(void *priv) cga_render(cga, (cga->displine << 1) + 1); break; } - } else { - switch (cga->double_type) { - default: - cga_render_blank(cga, cga->displine << 1); - break; - case DOUBLE_NONE: - cga_render_blank(cga, cga->displine); - break; - case DOUBLE_SIMPLE: - cga_render_blank(cga, cga->displine << 1); - cga_render_blank(cga, (cga->displine << 1) + 1); - break; - } + } else switch (cga->double_type) { + default: + cga_render_blank(cga, cga->displine << 1); + break; + case DOUBLE_NONE: + cga_render_blank(cga, cga->displine); + break; + case DOUBLE_SIMPLE: + cga_render_blank(cga, cga->displine << 1); + cga_render_blank(cga, (cga->displine << 1) + 1); + break; } switch (cga->double_type) { @@ -651,9 +680,7 @@ cga_poll(void *priv) cga->lastline++; xs_temp = x; - ys_temp = cga->lastline - cga->firstline; - if (cga->double_type > DOUBLE_NONE) - ys_temp <<= 1; + ys_temp = (cga->lastline - cga->firstline) << 1; if ((xs_temp > 0) && (ys_temp > 0)) { if (xs_temp < 64) @@ -667,30 +694,13 @@ cga_poll(void *priv) (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; - if (cga->double_type > DOUBLE_NONE) - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - else - set_screen_size(xsize, ysize + (enable_overscan ? 8 : 0)); + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); if (video_force_resize_get()) video_force_resize_set(0); } - if (cga->double_type > DOUBLE_NONE) { - if (enable_overscan) - cga_blit_memtoscreen(cga, 0, (cga->firstline - 4) << 1, - xsize, ((cga->lastline - cga->firstline) << 1) + 16); - else - cga_blit_memtoscreen(cga, 8, cga->firstline << 1, - xsize, (cga->lastline - cga->firstline) << 1); - } else { - if (enable_overscan) - video_blit_memtoscreen(0, cga->firstline - 4, - xsize, (cga->lastline - cga->firstline) + 8); - else - video_blit_memtoscreen(8, cga->firstline, - xsize, cga->lastline - cga->firstline); - } + cga_do_blit(xsize, cga->firstline, cga->lastline, cga->double_type); } frames++; @@ -768,13 +778,7 @@ cga_standalone_init(UNUSED(const device_t *info)) update_cga16_color(cga->cgamode); cga->double_type = device_get_config_int("double_type"); - - for (uint16_t i = 0; i < 256; i++) { - for (uint16_t j = 0; j < 256; j++) { - interp_lut[0][i][j] = cga_interpolate_srgb(i, j, 0.5); - interp_lut[1][i][j] = cga_interpolate_linear(i, j, 0.5); - } - } + cga_interpolate_init(); switch(device_get_config_int("font")) { case 0: diff --git a/src/video/vid_cga_v6355.c b/src/video/vid_cga_v6355.c index bdd4b82e6..f534ea89a 100644 --- a/src/video/vid_cga_v6355.c +++ b/src/video/vid_cga_v6355.c @@ -34,6 +34,7 @@ #include <86box/device.h> #include <86box/video.h> #include <86box/vid_v6355.h> +#include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> #include <86box/plat_unused.h> @@ -617,99 +618,6 @@ v6355_render_process(v6355_t *v6355, int line) } } -static uint8_t -v6355_interpolate_srgb(uint8_t co1, uint8_t co2, double fraction) -{ - uint8_t ret = ((co2 - co1) * fraction + co1); - - return ret; -} - -static uint8_t -v6355_interpolate_linear(uint8_t co1, uint8_t co2, double fraction) -{ - double c1, c2; - double r1, r2; - uint8_t ret; - - c1 = ((double) co1) / 255.0; - c1 = pow((co1 >= 0) ? c1 : -c1, 2.19921875); - if (co1 <= 0) - c1 = -c1; - c2 = ((double) co2) / 255.0; - c2 = pow((co2 >= 0) ? c2 : -c2, 2.19921875); - if (co2 <= 0) - c2 = -c2; - r1 = ((c2 - c1) * fraction + c1); - r2 = pow((r1 >= 0.0) ? r1 : -r1, 1.0 / 2.19921875); - if (r1 <= 0.0) - r2 = -r2; - ret = (uint8_t) round(r2 * 255.0); - - return ret; -} - -static color_t -v6355_interpolate_lookup(v6355_t *v6355, color_t color1, color_t color2, UNUSED(double fraction)) -{ - color_t ret; - uint8_t dt = v6355->double_type - DOUBLE_INTERPOLATE_SRGB; - - ret.a = 0x00; - ret.r = interp_lut[dt][color1.r][color2.r]; - ret.g = interp_lut[dt][color1.g][color2.g]; - ret.b = interp_lut[dt][color1.b][color2.b]; - - return ret; -} - -static void -v6355_interpolate(v6355_t *v6355, int x, int y, int w, int h) -{ - double quotient = 0.5; - - for (int i = y; i < (y + h); i++) { - if (i & 1) for (int j = x; j < (x + w); j++) { - int prev = i - 1; - int next = i + 1; - color_t prev_color, next_color; - color_t black; - color_t interim_1, interim_2; - color_t final; - - if (i < 0) - continue; - - black.color = 0x00000000; - - if ((prev >= 0) && (prev < (y + h))) - prev_color.color = buffer32->line[prev][j]; - else - prev_color.color = 0x00000000; - - if ((next >= 0) && (next < (y + h))) - next_color.color = buffer32->line[next][j]; - else - next_color.color = 0x00000000; - - interim_1 = v6355_interpolate_lookup(v6355, prev_color, black, quotient); - interim_2 = v6355_interpolate_lookup(v6355, black, next_color, quotient); - final = v6355_interpolate_lookup(v6355, interim_1, interim_2, quotient); - - buffer32->line[i][j] = final.color; - } - } -} - -static void -v6355_blit_memtoscreen(v6355_t *v6355, int x, int y, int w, int h) -{ - if (v6355->double_type > DOUBLE_SIMPLE) - v6355_interpolate(v6355, x, y, w, h); - - video_blit_memtoscreen(x, y, w, h); -} - static void v6355_poll(void *priv) { @@ -779,19 +687,17 @@ v6355_poll(void *priv) v6355_render(v6355, (v6355->displine << 1) + 1); break; } - } else { - switch (v6355->double_type) { - default: - v6355_render_blank(v6355, v6355->displine << 1); - break; - case DOUBLE_NONE: - v6355_render_blank(v6355, v6355->displine); - break; - case DOUBLE_SIMPLE: - v6355_render_blank(v6355, v6355->displine << 1); - v6355_render_blank(v6355, (v6355->displine << 1) + 1); - break; - } + } else switch (v6355->double_type) { + default: + v6355_render_blank(v6355, v6355->displine << 1); + break; + case DOUBLE_NONE: + v6355_render_blank(v6355, v6355->displine); + break; + case DOUBLE_SIMPLE: + v6355_render_blank(v6355, v6355->displine << 1); + v6355_render_blank(v6355, (v6355->displine << 1) + 1); + break; } switch (v6355->double_type) { @@ -879,9 +785,7 @@ v6355_poll(void *priv) v6355->lastline++; xs_temp = x; - ys_temp = v6355->lastline - v6355->firstline; - if (v6355->double_type > DOUBLE_NONE) - ys_temp <<= 1; + ys_temp = (v6355->lastline - v6355->firstline) << 1; if ((xs_temp > 0) && (ys_temp > 0)) { if (xs_temp < 64) @@ -903,21 +807,7 @@ v6355_poll(void *priv) video_force_resize_set(0); } - if (v6355->double_type > DOUBLE_NONE) { - if (enable_overscan) - v6355_blit_memtoscreen(v6355, 0, (v6355->firstline - 4) << 1, - xsize, ((v6355->lastline - v6355->firstline) << 1) + 16); - else - v6355_blit_memtoscreen(v6355, 8, v6355->firstline << 1, - xsize, (v6355->lastline - v6355->firstline) << 1); - } else { - if (enable_overscan) - video_blit_memtoscreen(0, v6355->firstline - 4, - xsize, (v6355->lastline - v6355->firstline) + 8); - else - video_blit_memtoscreen(8, v6355->firstline, - xsize, v6355->lastline - v6355->firstline); - } + cga_do_blit(xsize, v6355->firstline, v6355->lastline, v6355->double_type); } frames++; @@ -1035,13 +925,7 @@ v6355_standalone_init(const device_t *info) { update_cga16_color(v6355->cgamode); v6355->double_type = device_get_config_int("double_type"); - - for (uint16_t i = 0; i < 256; i++) { - for (uint16_t j = 0; j < 256; j++) { - interp_lut[0][i][j] = v6355_interpolate_srgb(i, j, 0.5); - interp_lut[1][i][j] = v6355_interpolate_linear(i, j, 0.5); - } - } + cga_interpolate_init(); switch(device_get_config_int("font")) { case 0: