Implemented it for the PCjr as well.

This commit is contained in:
OBattler
2025-08-27 01:47:41 +02:00
parent 97b122b143
commit 120a6e8b8b
6 changed files with 306 additions and 251 deletions

View File

@@ -22,6 +22,11 @@
#define PCJR_RGB_NO_BROWN 4 #define PCJR_RGB_NO_BROWN 4
#define PCJR_RGB_IBM_5153 5 #define PCJR_RGB_IBM_5153 5
#define DOUBLE_NONE 0
#define DOUBLE_SIMPLE 1
#define DOUBLE_INTERPOLATE_SRGB 2
#define DOUBLE_INTERPOLATE_LINEAR 3
typedef struct pcjr_s typedef struct pcjr_s
{ {
/* Video Controller stuff. */ /* Video Controller stuff. */
@@ -56,6 +61,7 @@ typedef struct pcjr_s
int lastline; int lastline;
int composite; int composite;
int apply_hd; int apply_hd;
int double_type;
/* Keyboard Controller stuff. */ /* Keyboard Controller stuff. */
int latched; int latched;

View File

@@ -123,6 +123,7 @@ extern void cga_write(uint32_t addr, uint8_t val, void *priv);
extern uint8_t cga_read(uint32_t addr, void *priv); extern uint8_t cga_read(uint32_t addr, void *priv);
extern void cga_recalctimings(cga_t *cga); extern void cga_recalctimings(cga_t *cga);
extern void cga_interpolate_init(void); extern void cga_interpolate_init(void);
extern void cga_blit_memtoscreen(int x, int y, int w, int h, int double_type);
extern void cga_do_blit(int vid_xsize, int firstline, int lastline, int double_type); extern void cga_do_blit(int vid_xsize, int firstline, int lastline, int double_type);
extern void cga_poll(void *priv); extern void cga_poll(void *priv);

View File

@@ -789,6 +789,23 @@ static const device_config_t pcjr_config[] = {
{ .description = "" } { .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 = "apply_hd", .name = "apply_hd",
.description = "Apply overscan deltas", .description = "Apply overscan deltas",

View File

@@ -514,7 +514,7 @@ cga_interpolate_init(void)
} }
} }
static void void
cga_blit_memtoscreen(int x, int y, int w, int h, int double_type) cga_blit_memtoscreen(int x, int y, int w, int h, int double_type)
{ {
if (double_type > DOUBLE_SIMPLE) if (double_type > DOUBLE_SIMPLE)

View File

@@ -113,8 +113,6 @@ static uint8_t crtcmask[32] = {
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
static uint8_t interp_lut[2][256][256];
static video_timings_t timing_v6355 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static video_timings_t timing_v6355 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
static uint8_t mdamap[256][2][2]; static uint8_t mdamap[256][2][2];
@@ -798,10 +796,7 @@ v6355_poll(void *priv)
if (((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { if (((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp; xsize = xs_temp;
ysize = ys_temp; ysize = ys_temp;
if (v6355->double_type > DOUBLE_NONE) set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
else
set_screen_size(xsize, ysize + (enable_overscan ? 8 : 0));
if (video_force_resize_get()) if (video_force_resize_get())
video_force_resize_set(0); video_force_resize_set(0);

View File

@@ -283,21 +283,29 @@ vid_get_h_overscan_delta(pcjr_t *pcjr)
} }
static void static void
vid_blit_h_overscan(pcjr_t *pcjr) vid_blit_v_overscan(pcjr_t *pcjr)
{ {
int cols = (pcjr->array[2] & 0xf) + 16;; int cols = (pcjr->array[2] & 0xf) + 16;
int y0 = pcjr->firstline << 1; int y0 = pcjr->firstline;
int y = (pcjr->lastline << 1) + 16; int y = pcjr->lastline + 8;
int h = 8;
int ho_s = vid_get_h_overscan_size(pcjr); int ho_s = vid_get_h_overscan_size(pcjr);
int i; int i;
int x; int x;
if (pcjr->double_type > DOUBLE_NONE) {
y0 <<= 1;
y <<= 1;
h <<= 1;
}
if (pcjr->array[0] & 1) if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s; x = (pcjr->crtc[1] << 3) + ho_s;
else else
x = (pcjr->crtc[1] << 4) + ho_s; x = (pcjr->crtc[1] << 4) + ho_s;
for (i = 0; i < 16; i++) { for (i = 0; i < h; i++) {
hline(buffer32, 0, y0 + i, x, cols); hline(buffer32, 0, y0 + i, x, cols);
hline(buffer32, 0, y + i, x, cols); hline(buffer32, 0, y + i, x, cols);
@@ -312,23 +320,222 @@ vid_blit_h_overscan(pcjr_t *pcjr)
} }
static void static void
vid_poll(void *priv) vid_render(pcjr_t *pcjr, int line, int ho_s, int ho_d)
{ {
pcjr_t *pcjr = (pcjr_t *) priv;
uint16_t cursoraddr = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; uint16_t cursoraddr = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff;
int drawcursor; int drawcursor;
int x;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr; uint8_t chr;
uint8_t attr; uint8_t attr;
uint16_t dat; uint16_t dat;
int cols[4]; int cols[4];
uint16_t offset = 0;
uint16_t mask = 0x1fff;
int x;
cols[0] = (pcjr->array[2] & 0xf) + 16;
if (pcjr->array[0] & 1)
hline(buffer32, 0, line, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
else
hline(buffer32, 0, line, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
switch (pcjr->addr_mode) {
case 0: /*Alpha*/
offset = 0;
mask = 0x3fff;
break;
case 1: /*Low resolution graphics*/
offset = (pcjr->scanline & 1) * 0x2000;
break;
case 3: /*High resolution graphics*/
offset = (pcjr->scanline & 3) * 0x2000;
break;
default:
break;
}
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
buffer32->line[line][ef_x] = buffer32->line[line][ef_x + 1] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][ef_x + 2] = buffer32->line[line][ef_x + 3] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][ef_x + 4] = buffer32->line[line][ef_x + 5] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][ef_x + 6] = buffer32->line[line][ef_x + 7] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x12: /*160x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
buffer32->line[line][ef_x] = buffer32->line[line][ef_x + 1] =
buffer32->line[line][ef_x + 2] = buffer32->line[line][ef_x + 3] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][ef_x + 4] = buffer32->line[line][ef_x + 5] =
buffer32->line[line][ef_x + 6] = buffer32->line[line][ef_x + 7] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][ef_x + 8] = buffer32->line[line][ef_x + 9] =
buffer32->line[line][ef_x + 10] = buffer32->line[line][ef_x + 11] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][ef_x + 12] = buffer32->line[line][ef_x + 13] =
buffer32->line[line][ef_x + 14] = buffer32->line[line][ef_x + 15] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x03: /*640x200x4*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
pcjr->memaddr++;
for (uint8_t c = 0; c < 8; c++) {
chr = (dat >> 7) & 1;
chr |= ((dat >> 14) & 2);
buffer32->line[line][ef_x + c] = pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16;
dat <<= 1;
}
}
break;
case 0x01: /*80 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
if (pcjr->scanline & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[line][ef_x + c] = cols[0];
else for (uint8_t c = 0; c < 8; c++)
buffer32->line[line][ef_x + c] = cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor) for (uint8_t c = 0; c < 8; c++)
buffer32->line[line][ef_x + c] ^= 15;
pcjr->memaddr++;
}
break;
case 0x00: /*40 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
pcjr->memaddr++;
if (pcjr->scanline & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[line][ef_x + (c << 1)] =
buffer32->line[line][ef_x + (c << 1) + 1] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[line][ef_x + (c << 1)] =
buffer32->line[line][ef_x + (c << 1) + 1] = cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor) for (uint8_t c = 0; c < 16; c++)
buffer32->line[line][ef_x + c] ^= 15;
}
break;
case 0x02: /*320x200x4*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
cols[2] = pcjr->array[2 + 16] + 16;
cols[3] = pcjr->array[3 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
for (uint8_t c = 0; c < 8; c++)
buffer32->line[line][ef_x + (c << 1)] = buffer32->line[line][ef_x + (c << 1) + 1] = dat <<= 2;
}
break;
case 0x102: /*640x200x2*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[line][ef_x + c] = cols[dat >> 15];
dat <<= 1;
}
}
break;
default:
break;
}
}
static void
vid_render_blank(pcjr_t *pcjr, int line, int ho_s)
{
if (pcjr->array[3] & 4) {
if (pcjr->array[0] & 1)
hline(buffer32, 0, line, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
else
hline(buffer32, 0, line, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
} else {
if (pcjr->array[0] & 1)
hline(buffer32, 0, line, (pcjr->crtc[1] << 3) + ho_s, pcjr->array[0 + 16] + 16);
else
hline(buffer32, 0, line, (pcjr->crtc[1] << 4) + ho_s, pcjr->array[0 + 16] + 16);
}
}
static void
vid_render_process(pcjr_t *pcjr, int line, int ho_s)
{
int x;
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
if (pcjr->composite)
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[line]);
else
video_process_8(x, line);
}
static void
vid_poll(void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
int x;
int xs_temp;
int ys_temp;
int oldvc;
int scanline_old; int scanline_old;
int l = (pcjr->displine << 1) + 16; int l = pcjr->displine + 8;
int ho_s = vid_get_h_overscan_size(pcjr); int ho_s = vid_get_h_overscan_size(pcjr);
int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2); int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2);
int old_ma;
if (!pcjr->linepos) { if (!pcjr->linepos) {
timer_advance_u64(&pcjr->timer, pcjr->dispofftime); timer_advance_u64(&pcjr->timer, pcjr->dispofftime);
@@ -338,239 +545,49 @@ vid_poll(void *priv)
if ((pcjr->crtc[8] & 3) == 3) if ((pcjr->crtc[8] & 3) == 3)
pcjr->scanline = (pcjr->scanline << 1) & 7; pcjr->scanline = (pcjr->scanline << 1) & 7;
if (pcjr->dispon) { if (pcjr->dispon) {
uint16_t offset = 0;
uint16_t mask = 0x1fff;
if (pcjr->displine < pcjr->firstline) { if (pcjr->displine < pcjr->firstline) {
pcjr->firstline = pcjr->displine; pcjr->firstline = pcjr->displine;
video_wait_for_buffer(); video_wait_for_buffer();
} }
pcjr->lastline = pcjr->displine; pcjr->lastline = pcjr->displine;
cols[0] = (pcjr->array[2] & 0xf) + 16; switch (pcjr->double_type) {
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
switch (pcjr->addr_mode) {
case 0: /*Alpha*/
offset = 0;
mask = 0x3fff;
break;
case 1: /*Low resolution graphics*/
offset = (pcjr->scanline & 1) * 0x2000;
break;
case 3: /*High resolution graphics*/
offset = (pcjr->scanline & 3) * 0x2000;
break;
default: default:
vid_render(pcjr, l << 1, ho_s, ho_d);
vid_render_blank(pcjr, (l << 1) + 1, ho_s);
break;
case DOUBLE_NONE:
vid_render(pcjr, l, ho_s, ho_d);
break;
case DOUBLE_SIMPLE:
old_ma = pcjr->memaddr;
vid_render(pcjr, l << 1, ho_s, ho_d);
pcjr->memaddr = old_ma;
vid_render(pcjr, (l << 1) + 1, ho_s, ho_d);
break; break;
} }
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { } else switch (pcjr->double_type) {
case 0x13: /*320x200x16*/ default:
for (x = 0; x < pcjr->crtc[1]; x++) { vid_render_blank(pcjr, l << 1, ho_s);
int ef_x = (x << 3) + ho_d; break;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) | case DOUBLE_NONE:
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; vid_render_blank(pcjr, l, ho_s);
pcjr->memaddr++; break;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = case DOUBLE_SIMPLE:
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = vid_render_blank(pcjr, l << 1, ho_s);
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; vid_render_blank(pcjr, (l << 1) + 1, ho_s);
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = break;
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = }
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x12: /*160x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] =
buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] =
buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] =
buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] =
buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] =
buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] =
buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x03: /*640x200x4*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
pcjr->memaddr++;
for (uint8_t c = 0; c < 8; c++) {
chr = (dat >> 7) & 1;
chr |= ((dat >> 14) & 2);
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16;
dat <<= 1;
}
}
break;
case 0x01: /*80 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
if (pcjr->scanline & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] =
cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
pcjr->memaddr++;
}
break;
case 0x00: /*40 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
pcjr->memaddr++;
if (pcjr->scanline & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] =
cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
}
break;
case 0x02: /*320x200x4*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
cols[2] = pcjr->array[2 + 16] + 16;
cols[3] = pcjr->array[3 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14];
dat <<= 2;
}
}
break;
case 0x102: /*640x200x2*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
cols[dat >> 15];
dat <<= 1;
}
}
break;
default: switch (pcjr->double_type) {
break; default:
} vid_render_process(pcjr, l << 1, ho_s);
} else { vid_render_process(pcjr, (l << 1) + 1, ho_s);
if (pcjr->array[3] & 4) { break;
if (pcjr->array[0] & 1) { case DOUBLE_NONE:
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); vid_render_process(pcjr, l, ho_s);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); break;
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
}
} else {
cols[0] = pcjr->array[0 + 16] + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
}
}
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]);
} else {
video_process_8(x, l);
video_process_8(x, l + 1);
} }
pcjr->scanline = scanline_old; pcjr->scanline = scanline_old;
if (pcjr->vc == pcjr->crtc[7] && !pcjr->scanline) { if (pcjr->vc == pcjr->crtc[7] && !pcjr->scanline) {
pcjr->status |= 8; pcjr->status |= 8;
@@ -657,17 +674,33 @@ vid_poll(void *priv)
video_force_resize_set(0); video_force_resize_set(0);
} }
vid_blit_h_overscan(pcjr); vid_blit_v_overscan(pcjr);
if (enable_overscan) { if (pcjr->double_type > DOUBLE_NONE) {
video_blit_memtoscreen(0, pcjr->firstline << 1, if (enable_overscan) {
xsize, actual_ys + 32); cga_blit_memtoscreen(0, pcjr->firstline << 1,
} else if (pcjr->apply_hd) { xsize, actual_ys + 32,
video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16, pcjr->double_type);
xsize, actual_ys); } else if (pcjr->apply_hd) {
cga_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16,
xsize, actual_ys,
pcjr->double_type);
} else {
cga_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16,
xsize, actual_ys,
pcjr->double_type);
}
} else { } else {
video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16, if (enable_overscan) {
xsize, actual_ys); video_blit_memtoscreen(0, pcjr->firstline,
xsize, (actual_ys >> 1) + 16);
} else if (pcjr->apply_hd) {
video_blit_memtoscreen(ho_s / 2, pcjr->firstline + 8,
xsize, actual_ys >> 1);
} else {
video_blit_memtoscreen(ho_d, pcjr->firstline + 8,
xsize, actual_ys >> 1);
}
} }
} }
@@ -720,5 +753,8 @@ pcjr_vid_init(pcjr_t *pcjr)
cga_palette = (display_type << 1); cga_palette = (display_type << 1);
cgapal_rebuild(); cgapal_rebuild();
pcjr->double_type = device_get_config_int("double_type");
cga_interpolate_init();
monitors[monitor_index_global].mon_composite = !!pcjr->composite; monitors[monitor_index_global].mon_composite = !!pcjr->composite;
} }