Initial S3 ViRGE video overlay emulation.
This commit is contained in:
parent
62afac2a71
commit
f1e1cc0b25
15 changed files with 381 additions and 28 deletions
|
|
@ -130,6 +130,7 @@ void *ati18800_init()
|
|||
svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/
|
||||
NULL,
|
||||
ati18800_in, ati18800_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ void *ati28800_init()
|
|||
svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
|
||||
ati28800_recalctimings,
|
||||
ati28800_in, ati28800_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x01ce, 0x0002, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, ati28800);
|
||||
|
|
|
|||
|
|
@ -2204,7 +2204,8 @@ void *mach64gx_init()
|
|||
svga_init(&mach64->svga, mach64, 1 << 22, /*4mb*/
|
||||
mach64_recalctimings,
|
||||
mach64_in, mach64_out,
|
||||
mach64_hwcursor_draw);
|
||||
mach64_hwcursor_draw,
|
||||
NULL);
|
||||
|
||||
rom_init(&mach64->bios_rom, "roms/mach64gx/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
|
|
|
|||
|
|
@ -824,7 +824,8 @@ void *gd5429_init()
|
|||
svga_init(&gd5429->svga, gd5429, 1 << 21, /*2mb*/
|
||||
gd5429_recalctimings,
|
||||
gd5429_in, gd5429_out,
|
||||
gd5429_hwcursor_draw);
|
||||
gd5429_hwcursor_draw,
|
||||
NULL);
|
||||
|
||||
mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL);
|
||||
mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ void *et4000_init()
|
|||
svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/
|
||||
et4000_recalctimings,
|
||||
et4000_in, et4000_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return et4000;
|
||||
|
|
|
|||
|
|
@ -1016,7 +1016,8 @@ void *et4000w32p_init()
|
|||
svga_init(&et4000->svga, et4000, 1 << 21, /*2mb*/
|
||||
et4000w32p_recalctimings,
|
||||
et4000w32p_in, et4000w32p_out,
|
||||
et4000w32p_hwcursor_draw);
|
||||
et4000w32p_hwcursor_draw,
|
||||
NULL);
|
||||
|
||||
rom_init(&et4000->bios_rom, "roms/et4000w32.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ void *oti067_common_init(char *bios_fn)
|
|||
svga_init(&oti067->svga, oti067, 1 << 19, /*512kb*/
|
||||
oti067_recalctimings,
|
||||
oti067_in, oti067_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ void *paradise_pvga1a_init()
|
|||
svga_init(¶dise->svga, paradise, 1 << 18, /*256kb*/
|
||||
NULL,
|
||||
paradise_in, paradise_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
|
||||
|
|
@ -294,6 +295,7 @@ void *paradise_wd90c11_init()
|
|||
svga_init(¶dise->svga, paradise, 1 << 19, /*512kb*/
|
||||
paradise_recalctimings,
|
||||
paradise_in, paradise_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
|
||||
|
|
|
|||
|
|
@ -1881,7 +1881,8 @@ static void *s3_init(char *bios_fn)
|
|||
svga_init(&s3->svga, s3, 1 << 22, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/
|
||||
s3_recalctimings,
|
||||
s3_in, s3_out,
|
||||
s3_hwcursor_draw);
|
||||
s3_hwcursor_draw,
|
||||
NULL);
|
||||
|
||||
svga->crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5);
|
||||
svga->crtc[0x37] = 1 | (7 << 5);
|
||||
|
|
|
|||
|
|
@ -123,15 +123,20 @@ typedef struct virge_t
|
|||
uint32_t sec_fb0, sec_fb1;
|
||||
uint32_t sec_stride;
|
||||
uint32_t overlay_ctrl;
|
||||
uint32_t k1_vert_scale;
|
||||
uint32_t k2_vert_scale;
|
||||
uint32_t dda_vert_accumulator;
|
||||
int32_t k1_vert_scale;
|
||||
int32_t k2_vert_scale;
|
||||
int32_t dda_vert_accumulator;
|
||||
int32_t k1_horiz_scale;
|
||||
int32_t k2_horiz_scale;
|
||||
int32_t dda_horiz_accumulator;
|
||||
uint32_t fifo_ctrl;
|
||||
uint32_t pri_start;
|
||||
uint32_t pri_size;
|
||||
uint32_t sec_start;
|
||||
uint32_t sec_size;
|
||||
|
||||
int sdif;
|
||||
|
||||
int pri_x, pri_y, pri_w, pri_h;
|
||||
int sec_x, sec_y, sec_w, sec_h;
|
||||
} streams;
|
||||
|
|
@ -224,14 +229,16 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
|
|||
//return;
|
||||
|
||||
case 0x3d4:
|
||||
svga->crtcreg = val & 0x7f;
|
||||
svga->crtcreg = val;// & 0x7f;
|
||||
return;
|
||||
case 0x3d5:
|
||||
// pclog("Write CRTC R%02X %02X\n", svga->crtcreg, val);
|
||||
//pclog("Write CRTC R%02X %02X %04x(%08x):%08x\n", svga->crtcreg, val, CS, cs, pc);
|
||||
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80)
|
||||
return;
|
||||
if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48)
|
||||
return;
|
||||
if (svga->crtcreg >= 0x80)
|
||||
return;
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
switch (svga->crtcreg)
|
||||
|
|
@ -350,7 +357,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p)
|
|||
ret = svga->crtcreg;
|
||||
break;
|
||||
case 0x3D5:
|
||||
// pclog("Read CRTC R%02X %04X:%04X (%02x)\n", svga->crtcreg, CS, pc, svga->crtc[svga->crtcreg]);
|
||||
//pclog("Read CRTC R%02X %04X:%04X (%02x)\n", svga->crtcreg, CS, pc, svga->crtc[svga->crtcreg]);
|
||||
switch (svga->crtcreg)
|
||||
{
|
||||
case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/
|
||||
|
|
@ -391,7 +398,7 @@ static void s3_virge_recalctimings(svga_t *svga)
|
|||
if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
|
||||
{
|
||||
svga->ma_latch |= (virge->ma_ext << 16);
|
||||
pclog("VGA mode\n");
|
||||
//pclog("VGA mode\n");
|
||||
if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4;
|
||||
else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100;
|
||||
if (!svga->rowoffset) svga->rowoffset = 256;
|
||||
|
|
@ -428,6 +435,7 @@ pclog("VGA mode\n");
|
|||
{
|
||||
svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/
|
||||
}
|
||||
//pclog("VGA mode x_disp=%i dispend=%i vtotal=%i\n", svga->hdisp, svga->dispend, svga->vtotal);
|
||||
}
|
||||
else /*Streams mode*/
|
||||
{
|
||||
|
|
@ -436,8 +444,21 @@ pclog("VGA mode\n");
|
|||
else
|
||||
svga->ma_latch = virge->streams.pri_fb0 >> 2;
|
||||
|
||||
svga->hdisp = virge->streams.pri_w;
|
||||
pclog("Streams mode x_disp=%i\n", svga->hdisp);
|
||||
svga->hdisp = virge->streams.pri_w + 1;
|
||||
svga->dispend = virge->streams.pri_h;
|
||||
|
||||
svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x;
|
||||
svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y;
|
||||
svga->overlay.ysize = virge->streams.sec_h;
|
||||
|
||||
if (virge->streams.buffer_ctrl & 2)
|
||||
svga->overlay.addr = virge->streams.sec_fb1;
|
||||
else
|
||||
svga->overlay.addr = virge->streams.sec_fb0;
|
||||
|
||||
svga->overlay.ena = (svga->overlay.x >= 0);
|
||||
svga->overlay.v_acc = virge->streams.dda_vert_accumulator;
|
||||
//pclog("Streams mode x_disp=%i dispend=%i vtotal=%i x=%i y=%i ysize=%i\n", svga->hdisp, svga->dispend, svga->vtotal, svga->overlay.x, svga->overlay.y, svga->overlay.ysize);
|
||||
svga->rowoffset = virge->streams.pri_stride >> 3;
|
||||
|
||||
switch ((virge->streams.pri_ctrl >> 24) & 0x7)
|
||||
|
|
@ -778,7 +799,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
virge_t *virge = (virge_t *)p;
|
||||
svga_t *svga = &virge->svga;
|
||||
reg_writes++;
|
||||
// if ((addr & 0xfffc) >= 0x8000)
|
||||
// if ((addr & 0xfffc) >= 0x8000 && (addr & 0xfffc) < 0x8400)
|
||||
// pclog("New MMIO writel %08X %08X %04x(%08x):%08x\n", addr, val, CS, cs, pc);
|
||||
|
||||
if ((addr & 0xfffc) < 0x8000)
|
||||
|
|
@ -800,12 +821,22 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
break;
|
||||
case 0x8190:
|
||||
virge->streams.sec_ctrl = val;
|
||||
virge->streams.dda_horiz_accumulator = val & 0xfff;
|
||||
if (val & (1 << 11))
|
||||
virge->streams.dda_horiz_accumulator |= 0xfffff800;
|
||||
virge->streams.sdif = (val >> 24) & 7;
|
||||
break;
|
||||
case 0x8194:
|
||||
virge->streams.chroma_upper_bound = val;
|
||||
break;
|
||||
case 0x8198:
|
||||
virge->streams.sec_filter = val;
|
||||
virge->streams.k1_horiz_scale = val & 0x7ff;
|
||||
if (val & (1 << 10))
|
||||
virge->streams.k1_horiz_scale |= 0xfffff800;
|
||||
virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff;
|
||||
if ((val >> 16) & (1 << 10))
|
||||
virge->streams.k2_horiz_scale |= 0xfffff800;
|
||||
break;
|
||||
case 0x81a0:
|
||||
virge->streams.blend_ctrl = val;
|
||||
|
|
@ -832,24 +863,36 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
break;
|
||||
case 0x81d0:
|
||||
virge->streams.sec_fb0 = val;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81d4:
|
||||
virge->streams.sec_fb1 = val;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81d8:
|
||||
virge->streams.sec_stride = val;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81dc:
|
||||
virge->streams.overlay_ctrl = val;
|
||||
break;
|
||||
case 0x81e0:
|
||||
virge->streams.k1_vert_scale = val;
|
||||
virge->streams.k1_vert_scale = val & 0x7ff;
|
||||
if (val & (1 << 10))
|
||||
virge->streams.k1_vert_scale |= 0xfffff800;
|
||||
break;
|
||||
case 0x81e4:
|
||||
virge->streams.k2_vert_scale = val;
|
||||
virge->streams.k2_vert_scale = val & 0x7ff;
|
||||
if (val & (1 << 10))
|
||||
virge->streams.k2_vert_scale |= 0xfffff800;
|
||||
break;
|
||||
case 0x81e8:
|
||||
virge->streams.dda_vert_accumulator = val;
|
||||
virge->streams.dda_vert_accumulator = val & 0xfff;
|
||||
if (val & (1 << 11))
|
||||
virge->streams.dda_vert_accumulator |= 0xfffff800;
|
||||
break;
|
||||
case 0x81ec:
|
||||
virge->streams.fifo_ctrl = val;
|
||||
|
|
@ -872,11 +915,15 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
virge->streams.sec_start = val;
|
||||
virge->streams.sec_x = (val >> 16) & 0x7ff;
|
||||
virge->streams.sec_y = val & 0x7ff;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81fc:
|
||||
virge->streams.sec_size = val;
|
||||
virge->streams.sec_w = (val >> 16) & 0x7ff;
|
||||
virge->streams.sec_h = val & 0x7ff;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
|
||||
case 0xa000: case 0xa004: case 0xa008: case 0xa00c:
|
||||
|
|
@ -2547,6 +2594,279 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine)
|
|||
}
|
||||
}
|
||||
|
||||
#define DECODE_YCbCr() \
|
||||
do \
|
||||
{ \
|
||||
int c; \
|
||||
\
|
||||
for (c = 0; c < 2; c++) \
|
||||
{ \
|
||||
uint8_t y1, y2; \
|
||||
int8_t Cr, Cb; \
|
||||
int dR, dG, dB; \
|
||||
\
|
||||
y1 = src[0]; \
|
||||
Cr = src[1] - 0x80; \
|
||||
y2 = src[2]; \
|
||||
Cb = src[3] - 0x80; \
|
||||
src += 4; \
|
||||
\
|
||||
dR = (359*Cr) >> 8; \
|
||||
dG = (88*Cb + 183*Cr) >> 8; \
|
||||
dB = (453*Cb) >> 8; \
|
||||
\
|
||||
r[x_write] = y1 + dR; \
|
||||
CLAMP(r[x_write]); \
|
||||
g[x_write] = y1 - dG; \
|
||||
CLAMP(g[x_write]); \
|
||||
b[x_write] = y1 + dB; \
|
||||
CLAMP(b[x_write]); \
|
||||
\
|
||||
r[x_write+1] = y2 + dR; \
|
||||
CLAMP(r[x_write+1]); \
|
||||
g[x_write+1] = y2 - dG; \
|
||||
CLAMP(g[x_write+1]); \
|
||||
b[x_write+1] = y2 + dB; \
|
||||
CLAMP(b[x_write+1]); \
|
||||
\
|
||||
x_write = (x_write + 2) & 7; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*Both YUV formats are untested*/
|
||||
#define DECODE_YUV211() \
|
||||
do \
|
||||
{ \
|
||||
uint8_t y1, y2, y3, y4; \
|
||||
int8_t U, V; \
|
||||
int dR, dG, dB; \
|
||||
\
|
||||
U = src[0] - 0x80; \
|
||||
y1 = (298 * (src[1] - 16)) >> 8; \
|
||||
y2 = (298 * (src[2] - 16)) >> 8; \
|
||||
V = src[3] - 0x80; \
|
||||
y3 = (298 * (src[4] - 16)) >> 8; \
|
||||
y4 = (298 * (src[5] - 16)) >> 8; \
|
||||
src += 6; \
|
||||
\
|
||||
dR = (309*V) >> 8; \
|
||||
dG = (100*U + 208*V) >> 8; \
|
||||
dB = (516*U) >> 8; \
|
||||
\
|
||||
r[x_write] = y1 + dR; \
|
||||
CLAMP(r[x_write]); \
|
||||
g[x_write] = y1 - dG; \
|
||||
CLAMP(g[x_write]); \
|
||||
b[x_write] = y1 + dB; \
|
||||
CLAMP(b[x_write]); \
|
||||
\
|
||||
r[x_write+1] = y2 + dR; \
|
||||
CLAMP(r[x_write+1]); \
|
||||
g[x_write+1] = y2 - dG; \
|
||||
CLAMP(g[x_write+1]); \
|
||||
b[x_write+1] = y2 + dB; \
|
||||
CLAMP(b[x_write+1]); \
|
||||
\
|
||||
r[x_write+2] = y2 + dR; \
|
||||
CLAMP(r[x_write+2]); \
|
||||
g[x_write+2] = y2 - dG; \
|
||||
CLAMP(g[x_write+2]); \
|
||||
b[x_write+2] = y2 + dB; \
|
||||
CLAMP(b[x_write+2]); \
|
||||
\
|
||||
r[x_write+3] = y2 + dR; \
|
||||
CLAMP(r[x_write+3]); \
|
||||
g[x_write+3] = y2 - dG; \
|
||||
CLAMP(g[x_write+3]); \
|
||||
b[x_write+3] = y2 + dB; \
|
||||
CLAMP(b[x_write+3]); \
|
||||
\
|
||||
x_write = (x_write + 4) & 7; \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_YUV422() \
|
||||
do \
|
||||
{ \
|
||||
int c; \
|
||||
\
|
||||
for (c = 0; c < 2; c++) \
|
||||
{ \
|
||||
uint8_t y1, y2; \
|
||||
int8_t U, V; \
|
||||
int dR, dG, dB; \
|
||||
\
|
||||
U = src[0] - 0x80; \
|
||||
y1 = (298 * (src[1] - 16)) >> 8; \
|
||||
V = src[2] - 0x80; \
|
||||
y2 = (298 * (src[3] - 16)) >> 8; \
|
||||
src += 4; \
|
||||
\
|
||||
dR = (309*V) >> 8; \
|
||||
dG = (100*U + 208*V) >> 8; \
|
||||
dB = (516*U) >> 8; \
|
||||
\
|
||||
r[x_write] = y1 + dR; \
|
||||
CLAMP(r[x_write]); \
|
||||
g[x_write] = y1 - dG; \
|
||||
CLAMP(g[x_write]); \
|
||||
b[x_write] = y1 + dB; \
|
||||
CLAMP(b[x_write]); \
|
||||
\
|
||||
r[x_write+1] = y2 + dR; \
|
||||
CLAMP(r[x_write+1]); \
|
||||
g[x_write+1] = y2 - dG; \
|
||||
CLAMP(g[x_write+1]); \
|
||||
b[x_write+1] = y2 + dB; \
|
||||
CLAMP(b[x_write+1]); \
|
||||
\
|
||||
x_write = (x_write + 2) & 7; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_RGB555() \
|
||||
do \
|
||||
{ \
|
||||
int c; \
|
||||
\
|
||||
for (c = 0; c < 4; c++) \
|
||||
{ \
|
||||
uint16_t dat; \
|
||||
\
|
||||
dat = *(uint16_t *)src; \
|
||||
src += 2; \
|
||||
\
|
||||
r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \
|
||||
g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \
|
||||
b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \
|
||||
} \
|
||||
x_write = (x_write + 4) & 7; \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_RGB565() \
|
||||
do \
|
||||
{ \
|
||||
int c; \
|
||||
\
|
||||
for (c = 0; c < 4; c++) \
|
||||
{ \
|
||||
uint16_t dat; \
|
||||
\
|
||||
dat = *(uint16_t *)src; \
|
||||
src += 2; \
|
||||
\
|
||||
r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \
|
||||
g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \
|
||||
b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \
|
||||
} \
|
||||
x_write = (x_write + 4) & 7; \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_RGB888() \
|
||||
do \
|
||||
{ \
|
||||
int c; \
|
||||
\
|
||||
for (c = 0; c < 4; c++) \
|
||||
{ \
|
||||
r[x_write + c] = src[0]; \
|
||||
g[x_write + c] = src[1]; \
|
||||
b[x_write + c] = src[2]; \
|
||||
src += 3; \
|
||||
} \
|
||||
x_write = (x_write + 4) & 7; \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_XRGB8888() \
|
||||
do \
|
||||
{ \
|
||||
int c; \
|
||||
\
|
||||
for (c = 0; c < 4; c++) \
|
||||
{ \
|
||||
r[x_write + c] = src[0]; \
|
||||
g[x_write + c] = src[1]; \
|
||||
b[x_write + c] = src[2]; \
|
||||
src += 4; \
|
||||
} \
|
||||
x_write = (x_write + 4) & 7; \
|
||||
} while (0)
|
||||
|
||||
#define OVERLAY_SAMPLE() \
|
||||
do \
|
||||
{ \
|
||||
switch (virge->streams.sdif) \
|
||||
{ \
|
||||
case 1: \
|
||||
DECODE_YCbCr(); \
|
||||
break; \
|
||||
case 2: \
|
||||
DECODE_YUV422(); \
|
||||
break; \
|
||||
case 3: \
|
||||
DECODE_RGB555(); \
|
||||
break; \
|
||||
case 4: \
|
||||
DECODE_YUV211(); \
|
||||
break; \
|
||||
case 5: \
|
||||
DECODE_RGB565(); \
|
||||
break; \
|
||||
case 6: \
|
||||
DECODE_RGB888(); \
|
||||
break; \
|
||||
case 7: \
|
||||
default: \
|
||||
DECODE_XRGB8888(); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void s3_virge_overlay_draw(svga_t *svga, int displine)
|
||||
{
|
||||
virge_t *virge = (virge_t *)svga->p;
|
||||
int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1;
|
||||
int h_acc = virge->streams.dda_horiz_accumulator;
|
||||
int r[8], g[8], b[8];
|
||||
int r_samp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int g_samp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int b_samp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int x_size, x_read = 4, x_write = 4;
|
||||
int x;
|
||||
uint32_t *p;
|
||||
uint8_t *src = &svga->vram[svga->overlay_latch.addr];
|
||||
|
||||
p = &((uint32_t *)buffer32->line[displine])[offset + 32];
|
||||
|
||||
if ((offset + virge->streams.sec_w) > virge->streams.pri_w)
|
||||
x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1;
|
||||
else
|
||||
x_size = virge->streams.sec_w + 1;
|
||||
|
||||
OVERLAY_SAMPLE();
|
||||
|
||||
for (x = 0; x < x_size; x++)
|
||||
{
|
||||
*p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16);
|
||||
|
||||
h_acc += virge->streams.k1_horiz_scale;
|
||||
if (h_acc >= 0)
|
||||
{
|
||||
if ((x_read ^ (x_read + 1)) & ~3)
|
||||
OVERLAY_SAMPLE();
|
||||
x_read = (x_read + 1) & 7;
|
||||
|
||||
h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale);
|
||||
}
|
||||
}
|
||||
|
||||
svga->overlay_latch.v_acc += virge->streams.k1_vert_scale;
|
||||
if (svga->overlay_latch.v_acc >= 0)
|
||||
{
|
||||
svga->overlay_latch.v_acc += (virge->streams.k2_vert_scale - virge->streams.k1_vert_scale);
|
||||
svga->overlay_latch.addr += virge->streams.sec_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t s3_virge_pci_read(int func, int addr, void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
|
|
@ -2658,7 +2978,8 @@ static void *s3_virge_init()
|
|||
svga_init(&virge->svga, virge, 1 << 22, /*4mb*/
|
||||
s3_virge_recalctimings,
|
||||
s3_virge_in, s3_virge_out,
|
||||
s3_virge_hwcursor_draw);
|
||||
s3_virge_hwcursor_draw,
|
||||
s3_virge_overlay_draw);
|
||||
|
||||
rom_init(&virge->bios_rom, "roms/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
|
|
@ -2728,7 +3049,8 @@ static void *s3_virge_375_init()
|
|||
svga_init(&virge->svga, virge, 1 << 22, /*4mb*/
|
||||
s3_virge_recalctimings,
|
||||
s3_virge_in, s3_virge_out,
|
||||
s3_virge_hwcursor_draw);
|
||||
s3_virge_hwcursor_draw,
|
||||
s3_virge_overlay_draw);
|
||||
|
||||
rom_init(&virge->bios_rom, "roms/86c375_1.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
|
|
|
|||
|
|
@ -400,7 +400,11 @@ void svga_poll(void *p)
|
|||
{
|
||||
// if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount());
|
||||
if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena)
|
||||
svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
|
||||
svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
|
||||
|
||||
if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena)
|
||||
svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
|
||||
|
||||
svga->vidtime += svga->dispofftime;
|
||||
// if (output) printf("Display off %f\n",vidtime);
|
||||
svga->cgastat |= 1;
|
||||
|
|
@ -414,11 +418,17 @@ void svga_poll(void *p)
|
|||
if (svga->firstline == 2000)
|
||||
svga->firstline = svga->displine;
|
||||
|
||||
if (svga->hwcursor_on)
|
||||
if (svga->hwcursor_on || svga->overlay_on)
|
||||
svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = 2;
|
||||
|
||||
svga->render(svga);
|
||||
|
||||
if (svga->overlay_on)
|
||||
{
|
||||
svga->overlay_draw(svga, svga->displine);
|
||||
svga->overlay_on--;
|
||||
}
|
||||
|
||||
if (svga->hwcursor_on)
|
||||
{
|
||||
svga->hwcursor_draw(svga, svga->displine);
|
||||
|
|
@ -594,6 +604,9 @@ void svga_poll(void *p)
|
|||
|
||||
svga->hwcursor_on = 0;
|
||||
svga->hwcursor_latch = svga->hwcursor;
|
||||
|
||||
svga->overlay_on = 0;
|
||||
svga->overlay_latch = svga->overlay;
|
||||
// pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
|
||||
|
||||
// pclog("ADDR %08X\n",hwcursor_addr);
|
||||
|
|
@ -609,7 +622,8 @@ int svga_init(svga_t *svga, void *p, int memsize,
|
|||
void (*recalctimings_ex)(struct svga_t *svga),
|
||||
uint8_t (*video_in) (uint16_t addr, void *p),
|
||||
void (*video_out)(uint16_t addr, uint8_t val, void *p),
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine))
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine),
|
||||
void (*overlay_draw)(struct svga_t *svga, int displine))
|
||||
{
|
||||
int c, d, e;
|
||||
|
||||
|
|
@ -639,6 +653,7 @@ int svga_init(svga_t *svga, void *p, int memsize,
|
|||
svga->video_in = video_in;
|
||||
svga->video_out = video_out;
|
||||
svga->hwcursor_draw = hwcursor_draw;
|
||||
svga->overlay_draw = overlay_draw;
|
||||
// _svga_recalctimings(svga);
|
||||
|
||||
mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, 0, svga);
|
||||
|
|
|
|||
|
|
@ -82,10 +82,13 @@ typedef struct svga_t
|
|||
int ena;
|
||||
int x, y;
|
||||
int xoff, yoff;
|
||||
int ysize;
|
||||
uint32_t addr;
|
||||
} hwcursor, hwcursor_latch;
|
||||
int v_acc, h_acc;
|
||||
} hwcursor, hwcursor_latch, overlay, overlay_latch;
|
||||
|
||||
int hwcursor_on;
|
||||
int overlay_on;
|
||||
|
||||
void (*render)(struct svga_t *svga);
|
||||
void (*recalctimings_ex)(struct svga_t *svga);
|
||||
|
|
@ -94,6 +97,8 @@ typedef struct svga_t
|
|||
uint8_t (*video_in) (uint16_t addr, void *p);
|
||||
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine);
|
||||
|
||||
void (*overlay_draw)(struct svga_t *svga, int displine);
|
||||
|
||||
void *p;
|
||||
} svga_t;
|
||||
|
|
@ -102,13 +107,11 @@ extern int svga_init(svga_t *svga, void *p, int memsize,
|
|||
void (*recalctimings_ex)(struct svga_t *svga),
|
||||
uint8_t (*video_in) (uint16_t addr, void *p),
|
||||
void (*video_out)(uint16_t addr, uint8_t val, void *p),
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine));
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine),
|
||||
void (*overlay_draw)(struct svga_t *svga, int displine));
|
||||
extern void svga_recalctimings(svga_t *svga);
|
||||
|
||||
|
||||
extern int svga_hwcursor_on;
|
||||
extern void (*svga_hwcursor_draw)(int displine);
|
||||
|
||||
uint8_t svga_read(uint32_t addr, void *p);
|
||||
uint16_t svga_readw(uint32_t addr, void *p);
|
||||
uint32_t svga_readl(uint32_t addr, void *p);
|
||||
|
|
|
|||
|
|
@ -475,7 +475,8 @@ void *tgui9440_init()
|
|||
svga_init(&tgui->svga, tgui, 1 << 21, /*2mb*/
|
||||
tgui_recalctimings,
|
||||
tgui_in, tgui_out,
|
||||
tgui_hwcursor_draw);
|
||||
tgui_hwcursor_draw,
|
||||
NULL);
|
||||
|
||||
mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &tgui->svga);
|
||||
mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, 0, tgui);
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ void *tvga8900d_init()
|
|||
svga_init(&tvga->svga, tvga, 1 << 20, /*1mb - chip supports 2mb, but drivers are buggy*/
|
||||
tvga_recalctimings,
|
||||
tvga_in, tvga_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga);
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ void *vga_init()
|
|||
svga_init(&vga->svga, vga, 1 << 18, /*256kb*/
|
||||
NULL,
|
||||
vga_in, vga_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
|
||||
|
|
|
|||
Loading…
Reference in a new issue