diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 0b8a4efd8..5a43ba76a 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -74,6 +74,7 @@ typedef struct ncr_t { uint8_t output_data; uint8_t tx_data; uint8_t irq_state; + uint8_t isr_reg; uint8_t bus; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 2b26df2f3..3be4ee9e5 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -189,6 +189,7 @@ typedef struct svga_t { void (*render)(struct svga_t *svga); void (*render8514)(struct svga_t *svga); + void (*render_xga)(struct svga_t *svga); void (*recalctimings_ex)(struct svga_t *svga); void (*video_out)(uint16_t addr, uint8_t val, void *priv); @@ -306,6 +307,7 @@ typedef struct svga_t { void * xga; } svga_t; +extern void ibm8514_set_poll(svga_t *svga); extern void ibm8514_poll(void *priv); extern void ibm8514_recalctimings(svga_t *svga); extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv); @@ -328,10 +330,11 @@ extern void ati8514_mca_write(int port, uint8_t val, void *priv); extern void ati8514_pos_write(uint16_t port, uint8_t val, void *priv); extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); -extern void xga_write_test(uint32_t addr, uint8_t val, void *priv); -extern uint8_t xga_read_test(uint32_t addr, void *priv); -extern void xga_poll(void *priv); -extern void xga_recalctimings(svga_t *svga); +extern void xga_write_test(uint32_t addr, uint8_t val, void *priv); +extern uint8_t xga_read_test(uint32_t addr, void *priv); +extern void xga_set_poll(svga_t *svga); +extern void xga_poll(void *priv); +extern void xga_recalctimings(svga_t *svga); extern uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write); @@ -376,6 +379,7 @@ uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); void svga_doblit(int wx, int wy, svga_t *svga); +void svga_set_poll(svga_t *svga); void svga_poll(void *priv); enum { diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index b90b53978..b2001dba9 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -240,8 +240,6 @@ typedef struct xga_t { uint16_t px_map_height[4]; uint32_t px_map_base[4]; } accel; - - int big_endian_linear; } xga_t; #endif /*VIDEO_XGA_H*/ diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 60f60473e..048194a96 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -195,7 +195,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 5: /* start DMA Send */ - pclog("Write: start DMA send register\n"); + ncr5380_log("Write: start DMA send register\n"); /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ scsi_bus->tx_mode = DMA_OUT_TX_BUS; if (ncr->dma_send_ext) @@ -238,7 +238,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr) } else ret = ncr->output_data; - ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x, txmode=%x.\n", CS, cpu_state.pc, ret, scsi_bus->clear_req, scsi_bus->wait_data, scsi_bus->tx_mode); + ncr5380_log("[%04X:%08X]: Data Bus Phase, CMDissued=%d, ret=%02x, clearreq=%d, waitdata=%x, txmode=%x.\n", CS, cpu_state.pc, scsi_bus->command_issued, ret, scsi_bus->clear_req, scsi_bus->wait_data, scsi_bus->tx_mode); } else { /*Return the data from the SCSI bus*/ bus = scsi_bus_read(scsi_bus); @@ -271,10 +271,6 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ret |= BUS_SEL; if (ncr->icr & ICR_BSY) ret |= BUS_BSY; - - /*Note by TC1995: Horrible hack, I know.*/ - (void) scsi_bus_read(scsi_bus); - (void) scsi_bus_read(scsi_bus); break; case 5: /* Bus and Status register */ @@ -319,6 +315,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ret |= STATUS_BUSY_ERROR; } ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); + ncr->isr_reg = ret; break; case 6: diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index a9d07af95..fcfda69e4 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -180,7 +180,10 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) } if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { memset(ncr400->buffer, 0, MIN(128, dev->buffer_length)); - timer_on_auto(&ncr400->timer, scsi_bus->period); + if (ncr400->type == ROM_T130B) + timer_on_auto(&ncr400->timer, 10.0); + else + timer_on_auto(&ncr400->timer, scsi_bus->period); ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, p=%lf enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, scsi_bus->wait_data, scsi_bus->wait_complete, scsi_bus->clear_req, scsi_bus->period, timer_is_enabled(&ncr400->timer)); } else @@ -391,17 +394,20 @@ t130b_in(uint16_t port, void *priv) } static void -ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv), uint8_t val) +ncr53c400_dma_mode_ext(void *priv, void *ext_priv, uint8_t val) { + ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; scsi_bus_t *scsi_bus = &ncr->scsibus; /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - ncr53c400_log("NCR 53c400: BlockCountLoaded=%d, DMA mode enabled=%02x, valDMA=%02x.\n", ncr400->block_count_loaded, ncr->mode & MODE_DMA, val & MODE_DMA); - if (!(val & MODE_DMA) && (ncr->mode & MODE_DMA)) { - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - scsi_bus->tx_mode = PIO_TX_BUS; + ncr53c400_log("NCR 53c400: Loaded?=%d, DMA mode enabled=%02x, valDMA=%02x.\n", ncr400->block_count_loaded, ncr->mode & MODE_DMA, val & MODE_DMA); + if (!ncr400->block_count_loaded) { + if (!(val & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + scsi_bus->tx_mode = PIO_TX_BUS; + } } } @@ -417,8 +423,13 @@ ncr53c400_callback(void *priv) uint8_t temp; uint8_t status; - if (scsi_bus->tx_mode != PIO_TX_BUS) - timer_on_auto(&ncr400->timer, 1.0); + if (scsi_bus->tx_mode != PIO_TX_BUS) { + if (ncr400->type == ROM_T130B) { + ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 200.0); + timer_on_auto(&ncr400->timer, scsi_bus->period / 200.0); + } else + timer_on_auto(&ncr400->timer, 1.0); + } if (scsi_bus->data_wait & 1) { scsi_bus->clear_req = 3; @@ -727,7 +738,6 @@ ncr53c400_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 2.0; scsi_bus->multi = 1.750; - return ncr400; } diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 0e51feae4..470642884 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -301,7 +301,7 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in if ((cmd >= 2) && (dev->accel.cmd & 0x1000)) val = (val >> 8) | (val << 8); } - if ((cmd <= 2) || (cmd == 4) || ((cmd == 6))) { + if ((cmd <= 2) || (cmd == 4) || (cmd == 6)) { if ((dev->accel.cmd & 0x08) && (cmd >= 2)) monoxfer = val; else { @@ -432,6 +432,14 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 2) { dev->accel.short_stroke = val; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; + if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); @@ -1139,16 +1147,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat the NOP command)*/ switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (dev->accel.ssv_state == 0) { - dev->accel.cx = dev->accel.cur_x; - if (dev->accel.cur_x >= 0x600) - dev->accel.cx |= ~0x5ff; - - dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_y >= 0x600) - dev->accel.cy |= ~0x5ff; + if (dev->accel.ssv_state == 0) break; - } if (dev->accel.cmd & 0x08) { while (count-- && dev->accel.ssv_len >= 0) { @@ -3605,6 +3605,12 @@ ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) buffer32->line[dev->displine + svga->y_add][svga->x_add + dev->h_disp + i] = svga->overscan_color; } +void +ibm8514_set_poll(svga_t *svga) +{ + timer_set_callback(&svga->timer, ibm8514_poll); +} + void ibm8514_poll(void *priv) { @@ -3614,7 +3620,7 @@ ibm8514_poll(void *priv) int wx; int wy; - ibm8514_log("IBM 8514/A poll.\n"); + ibm8514_log("IBM 8514/A poll=%x.\n", dev->on); if (dev->on) { ibm8514_log("ON!\n"); if (!dev->linepos) { @@ -3857,7 +3863,7 @@ ibm8514_mca_reset(void *priv) else ibm8514_mca_write(0x102, 0, svga); - timer_set_callback(&svga->timer, svga_poll); + svga_set_poll(svga); } static void * diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index d294f61e9..812885559 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2503,6 +2503,96 @@ ati8514_in(uint16_t addr, void *priv) return temp; } +static void +ati_render_24bpp(svga_t *svga) +{ + mach_t *mach = (mach_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/ + for (int x = 0; x <= dev->h_disp; x += 4) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dev->ma += 12; + } + } else { /*RGB, Red-(23:16), Green-(15:8), Blue-(7:0)*/ + for (int x = 0; x <= dev->h_disp; x += 4) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[x] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + p[x + 1] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + p[x + 2] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + p[x + 3] = dat & 0xffffff; + + dev->ma += 12; + } + } + dev->ma &= dev->vram_mask; + } +} + +static void +ati_render_32bpp(svga_t *svga) +{ + mach_t *mach = (mach_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/ + for (x = 0; x <= dev->h_disp; x++) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + *p++ = ((dat & 0x00ff0000) >> 16) | (dat & 0x0000ff00) | ((dat & 0x000000ff) << 16); + } + } else { /*RGB, Red-(31:24), Green-(23:16), Blue-(15:8)*/ + for (x = 0; x <= dev->h_disp; x++) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + *p++ = ((dat & 0xffffff00) >> 8); + } + } + dev->ma += (x * 4); + dev->ma &= dev->vram_mask; + } +} + void ati8514_recalctimings(svga_t *svga) { @@ -2711,17 +2801,11 @@ mach_recalctimings(svga_t *svga) break; case 24: mach_log("GEConfig24bpp: %03x.\n", mach->accel.ext_ge_config & 0x600); - if (mach->accel.ext_ge_config & 0x400) - svga->render8514 = ibm8514_render_BGR; - else - svga->render8514 = ibm8514_render_24bpp; + svga->render8514 = ati_render_24bpp; break; case 32: mach_log("GEConfig32bpp: %03x.\n", mach->accel.ext_ge_config & 0x600); - if (mach->accel.ext_ge_config & 0x400) - svga->render8514 = ibm8514_render_ABGR8888; - else - svga->render8514 = ibm8514_render_32bpp; + svga->render8514 = ati_render_32bpp; break; default: @@ -5776,7 +5860,7 @@ mach_mca_reset(void *priv) mach_log("MCA reset.\n"); dev->on = 0; mach_mca_write(0x102, 0, mach); - timer_set_callback(&svga->timer, svga_poll); + svga_set_poll(svga); } uint8_t diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index bb5c283ad..7839a602a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -923,6 +923,9 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cmd & 0x1000) { s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); @@ -1785,6 +1788,9 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) s3->accel.short_stroke = val; s3->accel.ssv_state = 1; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cmd & 0x1000) { s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); @@ -7861,7 +7867,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi uint32_t srcbase; uint32_t dstbase; - if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (s3->accel.cmd & (1 << 11))) + if (((s3->chip >= S3_TRIO64) || (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) && (s3->accel.cmd & (1 << 11))) cmd |= 0x08; // SRC-BASE/DST-BASE @@ -7970,11 +7976,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (s3->accel.ssv_state == 0) { - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.ssv_state == 0) break; - } if (s3->accel.cmd & 0x08) { /*Radial*/ while (count-- && s3->accel.ssv_len >= 0) { diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index e6201e4bf..4db2737ca 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -83,26 +83,76 @@ svga_get_pri(void) return svga_pri; } +void +svga_set_poll(svga_t *svga) +{ + svga_log("SVGA Timer activated, enabled?=%x.\n", timer_is_enabled(&svga->timer)); + timer_set_callback(&svga->timer, svga_poll); + if (!timer_is_enabled(&svga->timer)) + timer_enable(&svga->timer); +} + void svga_set_override(svga_t *svga, int val) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret_poll = 0; if (svga->override && !val) svga->fullchange = svga->monitor->mon_changeframecount; + svga->override = val; svga_log("Override=%x.\n", val); - if (ibm8514_active && (svga->dev8514 != NULL)) { - if (dev->on) { - if (svga->override) - timer_set_callback(&svga->timer, svga_poll); - else - timer_set_callback(&svga->timer, ibm8514_poll); - } else - timer_set_callback(&svga->timer, svga_poll); - } else - timer_set_callback(&svga->timer, svga_poll); + if (ibm8514_active && (svga->dev8514 != NULL)) + ret_poll |= 1; + + if (xga_active && (svga->xga != NULL)) + ret_poll |= 2; + + if (svga->override) + svga_set_poll(svga); + else { + switch (ret_poll) { + case 0: + default: + svga_set_poll(svga); + break; + + case 1: + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on) + ibm8514_set_poll(svga); + else + svga_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 2: + if (xga_active && (svga->xga != NULL)) { + if (xga->on) + xga_set_poll(svga); + else + svga_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 3: + if (ibm8514_active && (svga->dev8514 != NULL) && xga_active && (svga->xga != NULL)) { + if (dev->on) + ibm8514_set_poll(svga); + else if (xga->on) + xga_set_poll(svga); + else + svga_set_poll(svga); + } else + svga_set_poll(svga); + break; + } + } #ifdef OVERRIDE_OVERSCAN if (!val) { @@ -241,7 +291,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) if (ibm8514_active && dev) dev->on = (val & 0x01) ? 0 : 1; - svga_log("Write Port 3C3.\n"); + svga_log("Write Port 3C3=%x.\n", val & 0x01); svga_recalctimings(svga); break; case 0x3c4: @@ -612,6 +662,8 @@ void svga_recalctimings(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; + uint8_t set_timer = 0; double crtcconst; double _dispontime; double _dispofftime; @@ -620,6 +672,10 @@ svga_recalctimings(svga_t *svga) double _dispontime8514 = 0.0; double _dispofftime8514 = 0.0; double disptime8514 = 0.0; + double crtcconst_xga = 0.0; + double _dispontime_xga = 0.0; + double _dispofftime_xga = 0.0; + double disptime_xga = 0.0; #ifdef ENABLE_SVGA_LOG int vsyncend; int vblankend; @@ -709,6 +765,12 @@ svga_recalctimings(svga_t *svga) } else svga->render = svga_render_text_80; + if (xga_active && (svga->xga != NULL)) { + if (xga->on) { + if ((svga->mapping.base == 0xb8000) && (xga->aperture_cntl == 1)) /*Some operating systems reset themselves with ctrl-alt-del by going into text mode.*/ + xga->on = 0; + } + } svga->hdisp_old = svga->hdisp; } else { svga->hdisp_old = svga->hdisp; @@ -904,6 +966,10 @@ svga_recalctimings(svga_t *svga) if (dev->on) crtcconst8514 = svga->clock8514; } + if (xga_active && (svga->xga != NULL)) { + if (xga->on) + crtcconst_xga = svga->clock_xga; + } #ifdef ENABLE_SVGA_LOG vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); @@ -952,6 +1018,13 @@ svga_recalctimings(svga_t *svga) } } + if (xga_active && (svga->xga != NULL)) { + if (xga->on) { + disptime_xga = xga->h_total ? xga->h_total : TIMER_USEC; + _dispontime_xga = xga->h_disp; + } + } + if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; @@ -968,25 +1041,84 @@ svga_recalctimings(svga_t *svga) if (svga->dispofftime < TIMER_USEC) svga->dispofftime = TIMER_USEC; - if (ibm8514_active && (svga->dev8514 != NULL)) { - if (dev->on) { - _dispofftime8514 = disptime8514 - _dispontime8514; - _dispontime8514 *= crtcconst8514; - _dispofftime8514 *= crtcconst8514; + if (ibm8514_active && (svga->dev8514 != NULL)) + set_timer |= 1; - dev->dispontime = (uint64_t) (_dispontime8514); - dev->dispofftime = (uint64_t) (_dispofftime8514); - if (dev->dispontime < TIMER_USEC) - dev->dispontime = TIMER_USEC; - if (dev->dispofftime < TIMER_USEC) - dev->dispofftime = TIMER_USEC; + if (xga_active && (svga->xga != NULL)) + set_timer |= 2; - svga_log("IBM 8514/A poll.\n"); - timer_set_callback(&svga->timer, ibm8514_poll); - } else { - svga_log("SVGA poll enabled.\n"); - timer_set_callback(&svga->timer, svga_poll); - } + switch (set_timer) { + default: + case 0: /*VGA only*/ + svga_set_poll(svga); + break; + + case 1: /*Plus 8514/A*/ + if (dev->on) { + _dispofftime8514 = disptime8514 - _dispontime8514; + _dispontime8514 *= crtcconst8514; + _dispofftime8514 *= crtcconst8514; + + dev->dispontime = (uint64_t) (_dispontime8514); + dev->dispofftime = (uint64_t) (_dispofftime8514); + if (dev->dispontime < TIMER_USEC) + dev->dispontime = TIMER_USEC; + if (dev->dispofftime < TIMER_USEC) + dev->dispofftime = TIMER_USEC; + + ibm8514_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 2: /*Plus XGA*/ + if (xga->on) { + _dispofftime_xga = disptime_xga - _dispontime_xga; + _dispontime_xga *= crtcconst_xga; + _dispofftime_xga *= crtcconst_xga; + + xga->dispontime = (uint64_t) (_dispontime_xga); + xga->dispofftime = (uint64_t) (_dispofftime_xga); + if (xga->dispontime < TIMER_USEC) + xga->dispontime = TIMER_USEC; + if (xga->dispofftime < TIMER_USEC) + xga->dispofftime = TIMER_USEC; + + xga_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 3: /*Plus 8514/A and XGA*/ + if (dev->on) { + _dispofftime8514 = disptime8514 - _dispontime8514; + _dispontime8514 *= crtcconst8514; + _dispofftime8514 *= crtcconst8514; + + dev->dispontime = (uint64_t) (_dispontime8514); + dev->dispofftime = (uint64_t) (_dispofftime8514); + if (dev->dispontime < TIMER_USEC) + dev->dispontime = TIMER_USEC; + if (dev->dispofftime < TIMER_USEC) + dev->dispofftime = TIMER_USEC; + + ibm8514_set_poll(svga); + } else if (xga->on) { + _dispofftime_xga = disptime_xga - _dispontime_xga; + _dispontime_xga *= crtcconst_xga; + _dispofftime_xga *= crtcconst_xga; + + xga->dispontime = (uint64_t) (_dispontime_xga); + xga->dispofftime = (uint64_t) (_dispofftime_xga); + if (xga->dispontime < TIMER_USEC) + xga->dispontime = TIMER_USEC; + if (xga->dispofftime < TIMER_USEC) + xga->dispofftime = TIMER_USEC; + + xga_set_poll(svga); + } else + svga_set_poll(svga); + break; } if (!svga->force_old_addr) @@ -1064,7 +1196,6 @@ void svga_poll(void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint32_t x; uint32_t blink_delay; int wx; @@ -1072,15 +1203,6 @@ svga_poll(void *priv) int ret; int old_ma; - if (!svga->override) { - if (xga_active && xga && xga->on) { - if ((xga->disp_cntl_2 & 7) >= 2) { - xga_poll(svga); - return; - } - } - } - svga_log("SVGA Poll.\n"); if (!svga->linepos) { if (svga->displine == ((svga->hwcursor_latch.y < 0) ? 0 : svga->hwcursor_latch.y) && svga->hwcursor_latch.ena) { @@ -2070,6 +2192,8 @@ svga_readw_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_w; if (!linear) { + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); addr = svga_decode_addr(svga, addr, 0); if (addr == 0xffffffff) return 0xffff; @@ -2116,6 +2240,10 @@ svga_readl_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_l; if (!linear) { + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); + (void) xga_read_test(addr + 2, svga); + (void) xga_read_test(addr + 3, svga); addr = svga_decode_addr(svga, addr, 0); if (addr == 0xffffffff) return 0xffffffff; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 852ff6273..8bdc72fc6 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -243,6 +243,26 @@ xga_updatemapping(svga_t *svga) } } +static void +xga_render_blank(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (xga->firstline_draw == 2000) + xga->firstline_draw = xga->displine; + + xga->lastline_draw = xga->displine; + + uint32_t *line_ptr = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + uint32_t line_width = (uint32_t)(xga->h_disp) * sizeof(uint32_t); + + if (xga->h_disp > 0) + memset(line_ptr, 0, line_width); +} + void xga_recalctimings(svga_t *svga) { @@ -272,26 +292,43 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; + xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x, dispcntl2=%02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80, xga->disp_cntl_2 & 0xc0); switch ((xga->clk_sel_1 >> 2) & 3) { case 0: xga_log("HDISP VGA0 = %d, XGA = %d.\n", svga->hdisp, xga->h_disp); if (xga->clk_sel_2 & 0x80) - svga->clock = (cpuclock * (double) (1ULL << 32)) / 41539000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 41539000.0; else - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 25175000.0; break; case 1: xga_log("HDISP VGA1 = %d, XGA = %d.\n", svga->hdisp, xga->h_disp); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 28322000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 28322000.0; break; case 3: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 44900000.0; break; default: break; } + + switch (xga->disp_cntl_2 & 7) { + case 2: + svga->render_xga = xga_render_4bpp; + break; + case 3: + svga->render_xga = xga_render_8bpp; + break; + case 4: + svga->render_xga = xga_render_16bpp; + break; + + default: + svga->render_xga = xga_render_blank; + break; + } } } @@ -2717,8 +2754,10 @@ xga_write_test(uint32_t addr, uint8_t val, void *priv) xga->vram[addr & xga->vram_mask] = val; xga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x, a5test=%d.\n", val, addr, svga->banked_mask, xga->a5_test); } - } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) + } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) { xga->on = 0; + xga_log("OFF XGA write.\n"); + } } } @@ -2824,8 +2863,10 @@ xga_read_test(uint32_t addr, void *priv) addr += xga->read_bank; return xga->vram[addr & xga->vram_mask]; } - } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) + } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) { xga->on = 0; + xga_log("OFF XGA read.\n"); + } } return ret; } @@ -3029,6 +3070,12 @@ xga_readl_linear(uint32_t addr, void *priv) return ret; } +void +xga_set_poll(svga_t *svga) +{ + timer_set_callback(&svga->timer, xga_poll); +} + void xga_poll(void *priv) { @@ -3038,166 +3085,158 @@ xga_poll(void *priv) int wx; int wy; - if (!xga->linepos) { - if (xga->displine == xga->hwcursor_latch.y && xga->hwcursor_latch.ena) { - xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 32 : 0); - xga->hwcursor_oddeven = 0; - } - - if (xga->displine == (xga->hwcursor_latch.y + 1) && xga->hwcursor_latch.ena && xga->interlace) { - xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 33 : 1); - xga->hwcursor_oddeven = 1; - } - - timer_advance_u64(&svga->timer, svga->dispofftime); - svga->cgastat |= 1; - xga->linepos = 1; - - if (xga->dispon) { - xga->h_disp_on = 1; - - xga->ma &= xga->vram_mask; - - if (xga->firstline == 2000) { - xga->firstline = xga->displine; - video_wait_for_buffer_monitor(svga->monitor_index); + xga_log("XGA Poll=%d.\n", xga->on); + if (xga->on) { + if (!xga->linepos) { + if (xga->displine == xga->hwcursor_latch.y && xga->hwcursor_latch.ena) { + xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 32 : 0); + xga->hwcursor_oddeven = 0; } - if (xga->hwcursor_on) - xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; - - switch (xga->disp_cntl_2 & 7) { - case 2: - xga_render_4bpp(svga); - break; - case 3: - xga_render_8bpp(svga); - break; - case 4: - xga_render_16bpp(svga); - break; - default: - break; + if (xga->displine == (xga->hwcursor_latch.y + 1) && xga->hwcursor_latch.ena && xga->interlace) { + xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 33 : 1); + xga->hwcursor_oddeven = 1; } - svga->x_add = (overscan_x >> 1); - xga_render_overscan_left(xga, svga); - xga_render_overscan_right(xga, svga); - svga->x_add = (overscan_x >> 1); + timer_advance_u64(&svga->timer, xga->dispofftime); + svga->cgastat |= 1; + xga->linepos = 1; - if (xga->hwcursor_on) { - xga_hwcursor_draw(svga, xga->displine + svga->y_add); - xga->hwcursor_on--; - if (xga->hwcursor_on && xga->interlace) + if (xga->dispon) { + xga->h_disp_on = 1; + + xga->ma &= xga->vram_mask; + + if (xga->firstline == 2000) { + xga->firstline = xga->displine; + video_wait_for_buffer_monitor(svga->monitor_index); + } + + if (xga->hwcursor_on) + xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; + + svga->render_xga(svga); + + svga->x_add = (overscan_x >> 1); + xga_render_overscan_left(xga, svga); + xga_render_overscan_right(xga, svga); + svga->x_add = (overscan_x >> 1); + + if (xga->hwcursor_on) { + xga_hwcursor_draw(svga, xga->displine + svga->y_add); xga->hwcursor_on--; + if (xga->hwcursor_on && xga->interlace) + xga->hwcursor_on--; + } + + if (xga->lastline < xga->displine) + xga->lastline = xga->displine; } - if (xga->lastline < xga->displine) - xga->lastline = xga->displine; - } - - xga->displine++; - if (xga->interlace) xga->displine++; - if ((svga->cgastat & 8) && ((xga->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) - svga->cgastat &= ~8; - if (xga->displine > 1500) - xga->displine = 0; - } else { - timer_advance_u64(&svga->timer, svga->dispontime); - if (xga->dispon) - svga->cgastat &= ~1; + if (xga->interlace) + xga->displine++; + if ((svga->cgastat & 8) && ((xga->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) + svga->cgastat &= ~8; + if (xga->displine > 1500) + xga->displine = 0; + } else { + timer_advance_u64(&svga->timer, xga->dispontime); + if (xga->dispon) + svga->cgastat &= ~1; - xga->h_disp_on = 0; + xga->h_disp_on = 0; - xga->linepos = 0; - if (xga->dispon) { - if (xga->sc == xga->rowcount) { - xga->sc = 0; + xga->linepos = 0; + if (xga->dispon) { + if (xga->sc == xga->rowcount) { + xga->sc = 0; - xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); - xga->maback += (xga->rowoffset << 3); - if (xga->interlace) + xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); xga->maback += (xga->rowoffset << 3); + if (xga->interlace) + xga->maback += (xga->rowoffset << 3); - xga->maback &= xga->vram_mask; - xga->ma = xga->maback; - } else { - xga->sc++; - xga->sc &= 0x1f; - xga->ma = xga->maback; + xga->maback &= xga->vram_mask; + xga->ma = xga->maback; + } else { + xga->sc++; + xga->sc &= 0x1f; + xga->ma = xga->maback; + } + } + + xga->vc++; + xga->vc &= 0x7ff; + + if (xga->vc == xga->split) { + if (xga->interlace && xga->oddeven) + xga->ma = xga->maback = (xga->rowoffset << 1); + else + xga->ma = xga->maback = 0; + + xga->ma = (xga->ma << 2); + xga->maback = (xga->maback << 2); + + xga->sc = 0; + } + if (xga->vc == xga->dispend) { + xga->dispon = 0; + + for (x = 0; x < ((xga->vram_mask + 1) >> 12); x++) { + if (xga->changedvram[x]) + xga->changedvram[x]--; + } + if (svga->fullchange) + svga->fullchange--; + } + if (xga->vc == xga->v_syncstart) { + xga->dispon = 0; + svga->cgastat |= 8; + x = xga->h_disp; + + if (xga->interlace && !xga->oddeven) + xga->lastline++; + if (xga->interlace && xga->oddeven) + xga->firstline--; + + wx = x; + + wy = xga->lastline - xga->firstline; + svga_doblit(wx, wy, svga); + + xga->firstline = 2000; + xga->lastline = 0; + + xga->firstline_draw = 2000; + xga->lastline_draw = 0; + + xga->oddeven ^= 1; + + svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; + + if (xga->interlace && xga->oddeven) + xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); + else + xga->ma = xga->maback = xga->ma_latch; + + xga->ma = (xga->ma << 2); + xga->maback = (xga->maback << 2); + } + if (xga->vc == xga->v_total) { + xga->vc = 0; + xga->sc = 0; + xga->dispon = 1; + xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; + + svga->x_add = (overscan_x >> 1); + + xga->hwcursor_on = 0; + xga->hwcursor_latch = xga->hwcursor; } } - - xga->vc++; - xga->vc &= 0x7ff; - - if (xga->vc == xga->split) { - if (xga->interlace && xga->oddeven) - xga->ma = xga->maback = (xga->rowoffset << 1); - else - xga->ma = xga->maback = 0; - - xga->ma = (xga->ma << 2); - xga->maback = (xga->maback << 2); - - xga->sc = 0; - } - if (xga->vc == xga->dispend) { - xga->dispon = 0; - - for (x = 0; x < ((xga->vram_mask + 1) >> 12); x++) { - if (xga->changedvram[x]) - xga->changedvram[x]--; - } - if (svga->fullchange) - svga->fullchange--; - } - if (xga->vc == xga->v_syncstart) { - xga->dispon = 0; - svga->cgastat |= 8; - x = xga->h_disp; - - if (xga->interlace && !xga->oddeven) - xga->lastline++; - if (xga->interlace && xga->oddeven) - xga->firstline--; - - wx = x; - - wy = xga->lastline - xga->firstline; - svga_doblit(wx, wy, svga); - - xga->firstline = 2000; - xga->lastline = 0; - - xga->firstline_draw = 2000; - xga->lastline_draw = 0; - - xga->oddeven ^= 1; - - svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; - - if (xga->interlace && xga->oddeven) - xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); - else - xga->ma = xga->maback = xga->ma_latch; - - xga->ma = (xga->ma << 2); - xga->maback = (xga->maback << 2); - } - if (xga->vc == xga->v_total) { - xga->vc = 0; - xga->sc = 0; - xga->dispon = 1; - xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; - - svga->x_add = (overscan_x >> 1); - - xga->hwcursor_on = 0; - xga->hwcursor_latch = xga->hwcursor; - } - } + } else + svga_recalctimings(svga); } static uint8_t @@ -3285,6 +3324,7 @@ xga_reset(void *priv) xga->on = 0; xga->a5_test = 0; mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel); + svga_set_poll(svga); } static uint8_t