Mystique: Don't do busmastering until SOFTRAP status is read

MSICUBE sample for Windows 9x no longer freezes the entire VM after a while
This commit is contained in:
Cacodemon345
2023-12-25 14:05:07 +06:00
parent 373d369000
commit 278661c41c

View File

@@ -440,7 +440,10 @@ typedef struct mystique_t {
uint32_t vram_mask, vram_mask_w, vram_mask_l, uint32_t vram_mask, vram_mask_w, vram_mask_l,
lfb_base, ctrl_base, iload_base, lfb_base, ctrl_base, iload_base,
ma_latch_old, maccess, mctlwtst, maccess_running, ma_latch_old, maccess, mctlwtst, maccess_running,
status, softrap_pending_val; softrap_pending_val;
atomic_uint status;
atomic_bool softrap_status_read;
uint64_t blitter_time, status_time; uint64_t blitter_time, status_time;
@@ -1483,13 +1486,16 @@ mystique_ctrl_read_b(uint32_t addr, void *priv)
ret = mystique->status & 0xff; ret = mystique->status & 0xff;
if (svga->cgastat & 8) if (svga->cgastat & 8)
ret |= REG_STATUS_VSYNCSTS; ret |= REG_STATUS_VSYNCSTS;
if (ret & 1)
mystique->softrap_status_read = 1;
break; break;
case REG_STATUS + 1: case REG_STATUS + 1:
ret = (mystique->status >> 8) & 0xff; ret = (mystique->status >> 8) & 0xff;
break; break;
case REG_STATUS + 2: case REG_STATUS + 2:
ret = (mystique->status >> 16) & 0xff; ret = (mystique->status >> 16) & 0xff;
if (mystique->busy || ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || !FIFO_EMPTY) if (mystique->busy || ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || !FIFO_EMPTY
|| mystique->dma.state != DMA_STATE_IDLE || mystique->softrap_pending || mystique->endprdmasts_pending)
ret |= (STATUS_DWGENGSTS >> 16); ret |= (STATUS_DWGENGSTS >> 16);
break; break;
case REG_STATUS + 3: case REG_STATUS + 3:
@@ -2724,6 +2730,12 @@ run_dma(mystique_t *mystique)
thread_wait_mutex(mystique->dma.lock); thread_wait_mutex(mystique->dma.lock);
if (mystique->softrap_pending || mystique->endprdmasts_pending || !mystique->softrap_status_read)
{
thread_release_mutex(mystique->dma.lock);
return;
}
if (mystique->dma.state == DMA_STATE_IDLE) { if (mystique->dma.state == DMA_STATE_IDLE) {
if (!(mystique->status & STATUS_ENDPRDMASTS)) if (!(mystique->status & STATUS_ENDPRDMASTS))
{ {
@@ -3025,16 +3037,14 @@ mystique_softrap_pending_timer(void *priv)
mystique->status |= STATUS_ENDPRDMASTS; mystique->status |= STATUS_ENDPRDMASTS;
} }
if (mystique->softrap_pending) { if (mystique->softrap_pending) {
mystique->softrap_pending--;
mystique->dma.secaddress = mystique->softrap_pending_val; mystique->dma.secaddress = mystique->softrap_pending_val;
mystique->status |= STATUS_SOFTRAPEN; mystique->status |= STATUS_SOFTRAPEN;
mystique->softrap_status_read = 0;
//pclog("softrapen\n"); //pclog("softrapen\n");
mystique_update_irqs(mystique); mystique_update_irqs(mystique);
mystique->softrap_pending--;
} }
/* Force ENDPRDMASTS flag to be set. */
if (mystique->dma.state == DMA_STATE_IDLE && !(mystique->status & STATUS_ENDPRDMASTS))
mystique->status |= STATUS_ENDPRDMASTS;
} }
static void static void
@@ -5838,6 +5848,8 @@ mystique_init(const device_t *info)
timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *) mystique, 1); timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *) mystique, 1);
mystique->status = STATUS_ENDPRDMASTS; mystique->status = STATUS_ENDPRDMASTS;
mystique->softrap_status_read = 1;
mystique->svga.vsync_callback = mystique_vsync_callback; mystique->svga.vsync_callback = mystique_vsync_callback;