svga->crtc[svga->crtcreg] = val;
if (svga->crtcreg == 0x11) {
- if (!(val & 0x10))
- gd5429->vblank_irq = -1;
- else if (gd5429->vblank_irq < 0)
+ if (!(val & 0x10)) {
+ if (gd5429->vblank_irq > 0)
+ gd5429->vblank_irq = -1;
+ } else if (gd5429->vblank_irq < 0) {
gd5429->vblank_irq = 0;
+ }
gd5429_update_irqs(gd5429);
}
svga->interlace = svga->crtc[0x1a] & 1;
- if (svga->seqregs[7] & 0x01)
+ svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
+
+ if (svga->seqregs[7] & 0x01) {
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_8bpp_lowres;
+ else
svga->render = svga_render_8bpp_highres;
+ }
svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | (((svga->crtc[0x1b] >> 2) & 3) << 17);
if (gd5429->type >= CL_TYPE_GD5436) {
switch (gd5429->hidden_dac_reg & 0xf)
{
case 0x0:
- svga->render = svga_render_15bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_15bpp_lowres;
+ else
+ svga->render = svga_render_15bpp_highres;
svga->bpp = 15;
break;
case 0x1:
- svga->render = svga_render_16bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_16bpp_lowres;
+ else
+ svga->render = svga_render_16bpp_highres;
svga->bpp = 16;
break;
case 0x5:
if (gd5429->type >= CL_TYPE_GD5434 && (svga->seqregs[7] & 8))
{
- svga->render = svga_render_32bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_32bpp_lowres;
+ else
+ svga->render = svga_render_32bpp_highres;
svga->bpp = 32;
svga->rowoffset *= 2;
}
else
{
- svga->render = svga_render_24bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_24bpp_lowres;
+ else
+ svga->render = svga_render_24bpp_highres;
svga->bpp = 24;
}
break;
}
else
{
- svga->render = svga_render_15bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_15bpp_lowres;
+ else
+ svga->render = svga_render_15bpp_highres;
svga->bpp = 15;
}
}
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
int line_offset = (svga->seqregs[0x12] & 0x04) ? 16 : 4;
+ offset <<= svga->horizontal_linedbl;
+
if (svga->interlace && svga->hwcursor_oddeven)
svga->hwcursor_latch.addr += line_offset;
int fg_col = gd5429->blt.fg_col;
int bg_col = gd5429->blt.bg_col;
int x_max = 0;
+ int bplcnt = 0;
+ int bpp;
+ uint8_t dststore[4];
+ int maskstore = 0;
switch (gd5429->blt.depth)
{
case BLIT_DEPTH_8:
x_max = 8;
+ bpp = 1;
break;
case BLIT_DEPTH_16:
x_max = 16;
blt_mask *= 2;
+ bpp = 2;
break;
case BLIT_DEPTH_24:
x_max = 24;
blt_mask *= 3;
+ bpp = 3;
break;
case BLIT_DEPTH_32:
x_max = 32;
blt_mask *= 4;
+ bpp = 4;
break;
}
gd5429->blt.y_count = gd5429->blt.src_addr & 7;
else
gd5429->blt.y_count = 0;
-// pclog("gd5429_start_blit : size %i, %i %i %02x %02x %02x %02x\n",
-// gd5429->blt.width, gd5429->blt.height, gd5429->blt.x_count, gd5429->blt.rop, gd5429->blt.mode, gd5429->blt.extensions, gd5429->blt.mask);
+// pclog("gd5429_start_blit : size %i, %i %i %02x %02x %02x %02x %d\n",
+// gd5429->blt.width, gd5429->blt.height, gd5429->blt.x_count, gd5429->blt.rop, gd5429->blt.mode, gd5429->blt.extensions, gd5429->blt.mask, gd5429->blt.depth);
if (gd5429->blt.mode & 0x04)
{
case 0xda: dst = ~(src & dst); break;
}
+ dststore[bplcnt++] = dst;
+ maskstore |= mask;
+ if (bplcnt >= bpp) {
+ if (bpp == 1) {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ !((gd5429->blt.mode & 0x08) && !mask))
+ svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+ } else if (bpp == 2) {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ !((gd5429->blt.mode & 0x08) && !maskstore)) {
+ svga->vram[(gd5429->blt.dst_addr + 0) & svga->vram_mask] = dststore[0];
+ svga->vram[(gd5429->blt.dst_addr + 1) & svga->vram_mask] = dststore[1];
+ }
+ } else if (bpp == 3) {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ !((gd5429->blt.mode & 0x08) && !maskstore)) {
+ svga->vram[(gd5429->blt.dst_addr + 0) & svga->vram_mask] = dststore[0];
+ svga->vram[(gd5429->blt.dst_addr + 1) & svga->vram_mask] = dststore[1];
+ svga->vram[(gd5429->blt.dst_addr + 2) & svga->vram_mask] = dststore[2];
+ }
+ } else if (bpp == 3) {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ !((gd5429->blt.mode & 0x08) && !maskstore)) {
+ svga->vram[(gd5429->blt.dst_addr + 0) & svga->vram_mask] = dststore[0];
+ svga->vram[(gd5429->blt.dst_addr + 1) & svga->vram_mask] = dststore[1];
+ svga->vram[(gd5429->blt.dst_addr + 2) & svga->vram_mask] = dststore[2];
+ svga->vram[(gd5429->blt.dst_addr + 3) & svga->vram_mask] = dststore[3];
+ }
+ }
+ gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -bpp : bpp);
+ bplcnt = 0;
+ maskstore = 0;
+ }
+#if 0
if (0 && gd5429->type <= CL_TYPE_GD5428)
{
if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
!((gd5429->blt.mode & 0x08) && !mask))
svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
}
-
gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
+#endif
gd5429->blt.x_count++;
if (gd5429->blt.x_count == x_max)
fifo_entry_t fifo[FIFO_SIZE];
volatile int fifo_read_idx, fifo_write_idx;
+ volatile int fifo_thread_state;
thread_t *fifo_thread;
event_t *wake_fifo_thread;
event_t *fifo_not_full_event;
{
s3_t *s3 = (s3_t *)param;
- while (1)
+ s3->fifo_thread_state = 1;
+ while (s3->fifo_thread_state > 0)
{
thread_set_event(s3->fifo_not_full_event);
thread_wait_event(s3->wake_fifo_thread, -1);
s3->subsys_stat |= INT_FIFO_EMP;
s3_update_irqs(s3);
}
+ s3->fifo_thread_state = 0;
}
static void s3_vblank_start(svga_t *svga)
svga->interlace = svga->crtc[0x42] & 0x20;
//svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock(clk_sel, s3->getclock_p);
+ svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
+
switch (svga->crtc[0x67] >> 4)
{
case 3: case 5: case 7:
switch (svga->bpp)
{
case 8:
- svga->render = svga_render_8bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_8bpp_lowres;
+ else
+ svga->render = svga_render_8bpp_highres;
break;
case 15:
- svga->render = svga_render_15bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_15bpp_lowres;
+ else
+ svga->render = svga_render_15bpp_highres;
svga->hdisp /= 2;
break;
case 16:
- svga->render = svga_render_16bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_16bpp_lowres;
+ else
+ svga->render = svga_render_16bpp_highres;
svga->hdisp /= 2;
break;
case 24:
- svga->render = svga_render_24bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_24bpp_lowres;
+ else
+ svga->render = svga_render_24bpp_highres;
svga->hdisp /= 3;
break;
case 32:
- svga->render = svga_render_32bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_32bpp_lowres;
+ else
+ svga->render = svga_render_32bpp_highres;
if (s3->chip != S3_TRIO32 && s3->chip != S3_TRIO64)
svga->hdisp /= 4;
break;
int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
uint32_t rd_mask = s3->accel.rd_mask;
int cmd = s3->accel.cmd >> 13;
+ uint32_t srcbase, dstbase;
if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11)))
cmd |= 8;
+ // SRC-BASE/DST-BASE
+ if ((s3->accel.multifunc[13] >> 4) & 7) {
+ srcbase = 0x100000 * ((s3->accel.multifunc[13] >> 4) & 3);
+ } else {
+ srcbase = 0x100000 * ((s3->accel.multifunc[14] >> 2) & 3);
+ }
+ if ((s3->accel.multifunc[13] >> 0) & 7) {
+ dstbase = 0x100000 * ((s3->accel.multifunc[13] >> 0) & 3);
+ } else {
+ dstbase = 0x100000 * ((s3->accel.multifunc[14] >> 0) & 3);
+ }
+ if (s3->bpp == 1) {
+ srcbase >>= 1;
+ dstbase >>= 1;
+ } else if (s3->bpp == 3) {
+ srcbase >>= 2;
+ dstbase >>= 2;
+ }
+
// Amiga CGX4 driver sets all clipping values to FFF.
if (clip_t == 0xfff)
clip_t = 0;
clip_l = 0;
s3->force_busy = 1;
-//return;
-// if (!cpu_input) pclog("Start S3 command %i %i, %i %i, %i (clip %i, %i to %i, %i %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0] & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
-// else pclog(" S3 command %i, %i, %08x %08x\n", s3->accel.cmd >> 13, count, mix_dat, cpu_dat);
+ //return;
+ //if (!cpu_input) pclog("Start S3 command %i %i, %i %i, %i (clip %i, %i to %i, %i %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0] & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
+ //else pclog(" S3 command %i, %i, %08x %08x\n", s3->accel.cmd >> 13, count, mix_dat, cpu_dat);
if (!cpu_input) s3->accel.dat_count = 0;
if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80)
{
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
- s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
{
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
{
{
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
- s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
{
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
{
s3->accel.cy = s3->accel.cur_y;
if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
- s3->accel.dest = s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.cy * s3->width;
// pclog("Dest %08X (%i, %i) %04X %04X\n", s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.cur_x, s3->accel.cur_x & 0x1000);
}
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
- s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
{
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
{
if (s3->accel.cmd & 0x80) s3->accel.cy++;
else s3->accel.cy--;
- s3->accel.dest = s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.cy * s3->width;
s3->accel.sy--;
if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
s3->accel.cy = s3->accel.cur_y & 0xfff;
if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
- s3->accel.src = s3->accel.cy * s3->width;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
// pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
}
{
while (1)
{
- if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
- s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+ (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
{
READ_SRC(s3->accel.src + s3->accel.cx, src_dat);
READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
s3->accel.cy++;
s3->accel.dy++;
- s3->accel.src = s3->accel.cy * s3->width;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.sy--;
{
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
- s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+ (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
{
if (vram_mask)
{
s3->accel.dy--;
}
- s3->accel.src = s3->accel.cy * s3->width;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.sy--;
// s3->accel.cy = (s3->accel.cy & ~7) | (s3->accel.dy & 7);
s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.cx = s3->accel.dx & 7;
s3->accel.cy = s3->accel.dy & 7;
- s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
+ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
// pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
// dumpregs();
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
- s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+ (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
{
if (vram_mask)
{
s3->accel.dy--;
}
- s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.sy--;
int y = s3->accel.poly_cy;
int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
- s3->accel.dest = y * s3->width;
+ s3->accel.dest = dstbase + y * s3->width;
while (x_count-- && count--)
{
- if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
- s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+ if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r &&
+ (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b)
{
switch (frgd_mix)
{
int y = s3->accel.poly_cy;
int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
- s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width);
- s3->accel.dest = y * s3->width;
+ s3->accel.src = srcbase + s3->accel.pattern + ((y & 7) * s3->width);
+ s3->accel.dest = dstbase + y * s3->width;
while (x_count-- && count--)
{
int pat_x = s3->accel.poly_x & 7;
- if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
- s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+ if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r &&
+ (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b)
{
if (vram_mask)
{
int xx;
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
uint32_t fg = 0, bg = 0;
-
+
+ offset <<= svga->horizontal_linedbl;
+
switch (svga->bpp)
{
case 15:
svga_close(&s3->svga);
- thread_kill(s3->fifo_thread);
+ if (s3->fifo_thread_state) {
+ s3->fifo_thread_state = -1;
+ wake_fifo_thread(s3);
+ while (s3->fifo_thread_state == -1) {
+ thread_sleep(1);
+ }
+ thread_kill(s3->fifo_thread);
+ }
thread_destroy_event(s3->wake_fifo_thread);
thread_destroy_event(s3->fifo_not_full_event);
int pixel_count, tri_count;
thread_t *render_thread;
+ volatile int render_thread_state;
event_t *wake_render_thread;
event_t *wake_main_thread;
event_t *not_full_event;
volatile int fifo_read_idx, fifo_write_idx;
thread_t *fifo_thread;
+ volatile int fifo_thread_state;
event_t *wake_fifo_thread;
event_t *fifo_not_full_event;
int virge_busy;
uint8_t subsys_stat, subsys_cntl;
+ int vblank_irq;
} virge_t;
static inline void wake_fifo_thread(virge_t *virge)
#define INT_3DF_EMP (1 << 6)
#define INT_MASK 0xff
+static int vsync_enabled(virge_t *virge)
+{
+ if ((virge->svga.crtc[0x32] & 0x10) && ((!(virge->svga.crtc[0x11] & 0x20) && virge->vblank_irq > 0) || (virge->subsys_stat & virge->subsys_cntl & INT_MASK)))
+ return 1;
+ return 0;
+}
+
static void s3_virge_update_irqs(virge_t *virge)
{
- if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK))
+ if (vsync_enabled(virge))
pci_set_irq(virge->card, PCI_INTA);
else
pci_clear_irq(virge->card, PCI_INTA);
svga->crtc[svga->crtcreg] = val;
switch (svga->crtcreg)
{
+ case 0x11:
+ if (!(val & 0x10)) {
+ if (virge->vblank_irq > 0)
+ virge->vblank_irq = -1;
+ } else if (virge->vblank_irq < 0) {
+ virge->vblank_irq = 0;
+ }
+ s3_virge_update_irqs(virge);
+ break;
case 0x31:
virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4);
break;
case 0x3c2:
ret = svga_in(addr, svga);
ret |= (virge->subsys_stat & INT_VSY) ? 0x80 : 0x00;
+ ret |= virge->vblank_irq > 0 ? 0x80 : 0x00;
break;
//case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
// pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc);
}
}
+ svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
{
switch (svga->bpp)
{
case 8:
- svga->render = svga_render_8bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_8bpp_lowres;
+ else
+ svga->render = svga_render_8bpp_highres;
break;
case 15:
- svga->render = svga_render_15bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_15bpp_lowres;
+ else
+ svga->render = svga_render_15bpp_highres;
break;
case 16:
- svga->render = svga_render_16bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_16bpp_lowres;
+ else
+ svga->render = svga_render_16bpp_highres;
break;
- case 24:
- svga->render = svga_render_24bpp_highres;
+ case 24:
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_24bpp_lowres;
+ else
+ svga->render = svga_render_24bpp_highres;
break;
case 32:
- svga->render = svga_render_32bpp_highres;
+ if (svga->horizontal_linedbl)
+ svga->render = svga_render_32bpp_lowres;
+ else
+ svga->render = svga_render_32bpp_highres;
break;
}
}
{
virge_t *virge = (virge_t *)svga->p;
+ if (virge->vblank_irq >= 0) {
+ virge->vblank_irq = 1;
+ }
virge->subsys_stat |= INT_VSY;
s3_virge_update_irqs(virge);
}
{
virge_t *virge = (virge_t *)param;
- while (1)
+ virge->fifo_thread_state = 1;
+ while (virge->fifo_thread_state > 0)
{
thread_set_event(virge->fifo_not_full_event);
thread_wait_event(virge->wake_fifo_thread, -1);
virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP;
s3_virge_update_irqs(virge);
}
+ virge->fifo_thread_state = 0;
}
static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)
{
virge_t *virge = (virge_t *)param;
- while (1)
+ virge->render_thread_state = 1;
+ while (virge->render_thread_state > 0)
{
thread_wait_event(virge->wake_render_thread, -1);
thread_reset_event(virge->wake_render_thread);
virge->subsys_stat |= INT_S3D_DONE;
s3_virge_update_irqs(virge);
}
+ virge->render_thread_state = 0;
}
static void queue_triangle(virge_t *virge)
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
uint32_t fg, bg;
+ offset <<= svga->horizontal_linedbl;
+
// pclog("HWcursor %i %i %08x %08x\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y, virge->hwcursor_col[0],virge->hwcursor_col[1]);
switch (svga->bpp)
{
#endif
#endif
- thread_kill(virge->render_thread);
+ if (virge->render_thread_state) {
+ virge->render_thread_state = -1;
+ thread_set_event(virge->wake_render_thread);
+ while (virge->render_thread_state == -1) {
+ thread_sleep(1);
+ }
+ thread_kill(virge->render_thread);
+ }
thread_destroy_event(virge->not_full_event);
thread_destroy_event(virge->wake_main_thread);
thread_destroy_event(virge->wake_render_thread);
- thread_kill(virge->fifo_thread);
+ if (virge->fifo_thread_state) {
+ virge->fifo_thread_state = -1;
+ thread_set_event(virge->wake_fifo_thread);
+ while (virge->fifo_thread_state == -1) {
+ thread_sleep(1);
+ }
+ thread_kill(virge->fifo_thread);
+ }
thread_destroy_event(virge->wake_fifo_thread);
thread_destroy_event(virge->fifo_not_full_event);
int svga_get_vtotal(void)
{
- return svga_pri->vtotal;
+ int v = svga_pri->vtotal;
+ if (svga_pri->crtc[0x17] & 4)
+ v *= 2;
+ return v;
}
void *svga_get_object(void)
svga->split = svga->crtc[0x18];
svga->vblankstart = svga->crtc[0x15];
- if (svga->crtc[7] & 1) svga->vtotal |= 0x100;
- if (svga->crtc[7] & 32) svga->vtotal |= 0x200;
+ if (svga->crtc[7] & 1)
+ svga->vtotal |= 0x100;
+ if (svga->crtc[7] & 0x20)
+ svga->vtotal |= 0x200;
svga->vtotal += 2;
- if (svga->crtc[7] & 2) svga->dispend |= 0x100;
- if (svga->crtc[7] & 64) svga->dispend |= 0x200;
+ if (svga->crtc[7] & 2)
+ svga->dispend |= 0x100;
+ if (svga->crtc[7] & 0x40)
+ svga->dispend |= 0x200;
svga->dispend++;
- if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100;
- if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200;
+ if (svga->crtc[7] & 4)
+ svga->vsyncstart |= 0x100;
+ if (svga->crtc[7] & 0x80)
+ svga->vsyncstart |= 0x200;
svga->vsyncstart++;
- if (svga->crtc[7] & 0x10) svga->split|=0x100;
- if (svga->crtc[9] & 0x40) svga->split|=0x200;
+ if (svga->crtc[7] & 0x10)
+ svga->split|=0x100;
+ if (svga->crtc[9] & 0x40)
+ svga->split|=0x200;
svga->split++;
- if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100;
- if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200;
+ if (svga->crtc[7] & 0x08)
+ svga->vblankstart |= 0x100;
+ if (svga->crtc[9] & 0x20)
+ svga->vblankstart |= 0x200;
svga->vblankstart++;
svga->hdisp = svga->crtc[1];
svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1;
svga->lowres = svga->attrregs[0x10] & 0x40;
+
+ svga->horizontal_linedbl = 0;
svga->interlace = 0;
svga->hdisp_time = svga->hdisp;
svga->render = svga_render_blank;
+
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
{
if (svga->seqregs[1] & 8) /*40 column*/
svga->hsync_divisor = !svga->hsync_divisor;
if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
- return 1;
+ return eod;
svga->vc++;
svga->vc &= 2047;
svga->render == svga_render_15bpp_lowres ||
svga->render == svga_render_16bpp_lowres ||
svga->render == svga_render_24bpp_lowres ||
- svga->render == svga_render_32bpp_lowres)
+ svga->render == svga_render_32bpp_lowres) {
+ if (svga->horizontal_linedbl)
+ svga->video_res_x *= 2;
+ else
svga->video_res_x /= 2;
+ }
switch (svga->gdcreg[5] & 0x60)
{
{
xsize=wx;
ysize=wy+1;
- if (xsize<64) xsize=0;
+ if (xsize<128) xsize=0;
if (ysize<32) ysize=0;
- if (svga->vertical_linedbl)
- updatewindowsize(xsize,ysize*2);
- else
- updatewindowsize(xsize,ysize);
+ updatewindowsize(xsize * (svga->horizontal_linedbl ? 2 : 1), ysize * (svga->vertical_linedbl ? 2 : 1));
}
if (vid_resize)
{
xsize = wx;
ysize = wy + 1;
}
- video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
+ video_blit_memtoscreen(32, 0, y1, y2, xsize << svga->horizontal_linedbl, ysize);
// pclog("svga_doblit end\n");
}
uint8_t ksc5601_sbyte_mask;
int vertical_linedbl;
+ int horizontal_linedbl;
/*Used to implement CRTC[0x17] bit 2 hsync divisor*/
int hsync_divisor;
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 16)
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 16)
{
uint8_t edat[4];
uint8_t dat;
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 8)
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 8)
{
uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 4)
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + x) & svga->vram_display_mask]);
- p[x] = video_15to32[dat & 0xffff];
- p[x + 1] = video_15to32[dat >> 16];
-
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
-
- p[x] = video_15to32[dat & 0xffff];
- p[x + 1] = video_15to32[dat >> 16];
+ p[x] = p[x + 1] = video_15to32[dat & 0xffff];
+ p[x + 2] = p[x + 3] = video_15to32[dat >> 16];
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 4)
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
-
- p[x] = video_16to32[dat & 0xffff];
- p[x + 1] = video_16to32[dat >> 16];
-
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + x) & svga->vram_display_mask]);
- p[x] = video_16to32[dat & 0xffff];
- p[x + 1] = video_16to32[dat >> 16];
+ p[x] = p[x + 1] = video_16to32[dat & 0xffff];
+ p[x + 2] = p[x + 3] = video_16to32[dat >> 16];
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
offset = (8 - (svga->scrollcache & 6)) + 24;
if (svga->swaprb) {
- for (x = 0; x <= svga->hdisp; x++) {
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) {
fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
svga->ma += 3;
svga->ma &= svga->vram_display_mask;
((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
}
} else {
- for (x = 0; x <= svga->hdisp; x++)
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
{
- fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
+ fg = svga->vram[svga->ma] | (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | (svga->vram[(svga->ma + 2) & svga->vram_display_mask] << 16);
svga->ma += 3;
svga->ma &= svga->vram_display_mask;
((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
uint32_t dat;
for (x = 0; x <= svga->hdisp; x++)
{
- dat = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
+ dat = svga->vram[(svga->ma + 2) &svga->vram_display_mask] | (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | (svga->vram[svga->ma + 0] << 16);
p[x] = dat;
svga->ma += 3;
svga->ma &= svga->vram_display_mask;
}
} else {
- for (x = 0; x <= svga->hdisp; x += 4)
- {
- uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
- p[x] = dat & 0xffffff;
+ if ((svga->ma & svga->vram_display_mask) + svga->hdisp * 3 + 3 > svga->vram_display_mask) {
+ for (x = 0; x <= svga->hdisp; x++) {
+ uint32_t dat = (svga->vram[(svga->ma + 0) & svga->vram_display_mask] << 0) |
+ (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) |
+ (svga->vram[(svga->ma + 2) & svga->vram_display_mask] << 16);
+ p[x] = dat;
+ svga->ma += 3;
+ }
+ } else {
+ for (x = 0; x <= svga->hdisp; x += 4) {
+ uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+ p[x] = dat & 0xffffff;
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
- p[x + 1] = dat & 0xffffff;
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
+ p[x + 1] = dat & 0xffffff;
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
- p[x + 2] = dat & 0xffffff;
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
+ p[x + 2] = dat & 0xffffff;
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
- p[x + 3] = dat & 0xffffff;
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
+ p[x + 3] = dat & 0xffffff;
- svga->ma += 12;
+ svga->ma += 12;
+ }
}
}
svga->ma &= svga->vram_display_mask;
offset = (8 - (svga->scrollcache & 6)) + 24;
- for (x = 0; x <= svga->hdisp; x++)
+ for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
{
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 4;