Files
86Box/src/vid_cl_gd.c
OBattler bc5ac4a699 Reverted Direct3D to 2048x2048 buffer and suppressed the EGA/(S)VGA overscan, if enabled, in 2048x modes, fixes Direct3D freezes;
Improved the BusLogic incoming mailbox code;
The BusLogic callback is now three-phases and outgoing mailbox interrupts are emulated correctly;
Fixed the CD-ROM command READ DISC INFORMATION (0x51), fixes NetBSD crashing 86Box with segmentation fault when using the AHA-154x;
Added the CD-ROM command PAUSE/RESUME ALT (0xC2).
2017-01-24 01:03:23 +01:00

1113 lines
28 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "rom.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_cl_ramdac.h"
#include "vid_cl_gd.h"
#include "vid_cl_gd_blit.h"
void cirrus_update_bank_ptr(clgd_t *clgd, uint8_t bank_index);
void clgd_recalctimings(svga_t *svga);
void svga_write_cirrus(uint32_t addr, uint8_t val, void *p);
void svga_write_cirrus_linear(uint32_t addr, uint8_t val, void *p);
void svga_write_cirrus_linear_bitblt(uint32_t addr, uint8_t val, void *p);
uint8_t svga_read_cirrus(uint32_t addr, void *p);
uint8_t svga_read_cirrus_linear(uint32_t addr, void *p);
uint8_t svga_read_cirrus_linear_bitblt(uint32_t addr, void *p);
void clgd_out(uint16_t addr, uint8_t val, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_t *svga = &clgd->svga;
uint8_t old;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
// pclog("clgd out %04X %02X\n", addr, val);
switch (addr)
{
case 0x3c4:
svga->seqaddr = val;
break;
case 0x3c5:
if (svga->seqaddr > 5)
{
old = svga->seqregs[svga->seqaddr & 0x1f];
switch (svga->seqaddr & 0x1f)
{
case 0x06:
val &= 0x17;
if (val == 0x12)
{
svga->seqregs[svga->seqaddr & 0x1f] = 0x12;
}
else
{
svga->seqregs[svga->seqaddr & 0x1f] = 0xf;
}
break;
case 0x10: case 0x30: case 0x50: case 0x70:
case 0x90: case 0xb0: case 0xd0: case 0xf0:
svga->seqregs[0x10] = val;
svga->hwcursor.x = (val << 3) | (svga->seqaddr >> 5);
// pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x);
break;
case 0x11: case 0x31: case 0x51: case 0x71:
case 0x91: case 0xb1: case 0xd1: case 0xf1:
svga->seqregs[0x11] = val;
svga->hwcursor.y = (val << 3) | (svga->seqaddr >> 5);
// pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y);
break;
case 0x07:
cirrus_update_memory_access(clgd);
clgd_recalctimings(svga);
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
case 0x14: case 0x15: case 0x16:
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
svga->seqregs[svga->seqaddr & 0x1f] = val;
break;
case 0x13:
svga->seqregs[svga->seqaddr & 0x1f] = val;
svga->hwcursor.addr = 0x1fc000 + ((val & 0x3f) * 256);
// pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr);
break;
case 0x12:
svga->seqregs[svga->seqaddr & 0x1f] = val;
svga->hwcursor.ena = val & 1;
// pclog("svga->hwcursor.ena = %i\n", svga->hwcursor.ena);
break;
case 0x17:
old = svga->seqregs[svga->seqaddr & 0x1f];
svga->seqregs[svga->seqaddr & 0x1f] = (svga->seqregs[svga->seqaddr & 0x1f] & 0x38) | (val & 0xc7);
cirrus_update_memory_access(clgd);
break;
}
return;
}
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
// pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc);
cl_ramdac_out(addr, val, &clgd->ramdac, clgd, svga);
return;
case 0x3cf:
if (svga->gdcaddr == 5)
{
svga->gdcreg[5] = val & 0x7f;
if (svga->gdcreg[0xb] & 0x04)
svga->writemode = svga->gdcreg[5] & 7;
else
svga->writemode = svga->gdcreg[5] & 3;
cirrus_update_memory_access(clgd);
svga_out(addr, val, svga);
return;
}
if (svga->gdcaddr == 6)
{
if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
{
svga->gdcreg[6] = val;
cirrus_update_memory_access(clgd);
}
svga->gdcreg[6] = val;
return;
}
if (svga->gdcaddr > 8)
{
switch (svga->gdcaddr)
{
case 0x09: case 0x0A: case 0x0B:
svga->gdcreg[svga->gdcaddr & 0x3f] = val;
cirrus_update_bank_ptr(clgd, 0);
cirrus_update_bank_ptr(clgd, 1);
if (svga->gdcreg[0xb] & 0x04)
svga->writemode = svga->gdcreg[5] & 7;
else
svga->writemode = svga->gdcreg[5] & 3;
cirrus_update_memory_access(clgd);
break;
case 0x21: case 0x23: case 0x25: case 0x27:
svga->gdcreg[svga->gdcaddr & 0x3f] = val & 0x1f;
break;
case 0x2a:
svga->gdcreg[svga->gdcaddr & 0x3f] = val & 0x3f;
/* if auto start mode, starts bit blt now */
if (svga->gdcreg[0x31] & CIRRUS_BLT_AUTOSTART) cirrus_bitblt_start(clgd, svga);
break;
case 0x2e:
svga->gdcreg[svga->gdcaddr & 0x3f] = val & 0x3f;
break;
case 0x31:
cirrus_write_bitblt(clgd, svga, val);
break;
default:
svga->gdcreg[svga->gdcaddr & 0x3f] = val;
break;
}
return;
}
break;
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (svga->crtcreg <= 0x18)
val &= mask_crtc[svga->crtcreg];
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
if ((svga->crtcreg != 0x22) && (svga->crtcreg != 0x24) && (svga->crtcreg != 0x26) && (svga->crtcreg != 0x27)) svga->crtc[svga->crtcreg] = val;
if ((svga->crtcreg == 0x22) || (svga->crtcreg == 0x24) || (svga->crtcreg == 0x26) || (svga->crtcreg == 0x27)) return;
if (old != val)
{
if (svga->crtcreg == 0x1b)
{
svga->vrammask = (val & 2) ? (clgd->vram_size - 1) : 0x3ffff;
clgd->linear_mmio_mask = (val & 2) ? (clgd->vram_size - 256) : (0x40000 - 256);
}
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, svga);
}
uint8_t clgd_in(uint16_t addr, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_t *svga = &clgd->svga;
if ((((addr & 0xfff0) == 0x3d0) || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1))
addr ^= 0x60;
// if (addr != 0x3da) pclog("IN clgd %04X\n", addr);
switch (addr)
{
case 0x3c5:
if (svga->seqaddr > 5)
{
switch (svga->seqaddr)
{
case 0x06:
return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f;
case 0x10: case 0x30: case 0x50: case 0x70:
case 0x90: case 0xb0: case 0xd0: case 0xf0:
return svga->seqregs[0x10];
case 0x11: case 0x31: case 0x51: case 0x71:
case 0x91: case 0xb1: case 0xd1: case 0xf1:
return svga->seqregs[0x11];
case 0x15:
return clgd->vram_code;
case 0x05: case 0x07: case 0x08: case 0x09:
case 0x0a: case 0x0b: case 0x0c: case 0x0d:
case 0x0e: case 0x0f: case 0x12: case 0x13:
case 0x14: case 0x16: case 0x17: case 0x18:
case 0x19: case 0x1a: case 0x1b: case 0x1c:
case 0x1d: case 0x1e: case 0x1f:
return svga->seqregs[svga->seqaddr];
}
return svga->seqregs[svga->seqaddr & 0x3f];
}
break;
case 0x3cf:
if (svga->gdcaddr >= 0x3a)
{
return 0xff;
}
if (svga->gdcaddr > 8)
{
return svga->gdcreg[svga->gdcaddr & 0x3f];
}
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
// pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc);
return cl_ramdac_in(addr, &clgd->ramdac, clgd, svga);
case 0x3D4:
return svga->crtcreg;
case 0x3D5:
switch (svga->crtcreg)
{
case 0x24: /*Attribute controller toggle readback (R)*/
return svga->attrff << 7;
case 0x26: /*Attribute controller index readback (R)*/
return svga->attraddr & 0x3f;
}
return svga->crtc[svga->crtcreg];
}
return svga_in(addr, svga);
}
/***************************************
*
* bank memory
*
***************************************/
void cirrus_update_bank_ptr(clgd_t *clgd, uint8_t bank_index)
{
svga_t *svga = &clgd->svga;
uint32_t offset;
uint32_t limit;
if ((svga->gdcreg[0x0b] & 0x01) != 0) /* dual bank */
offset = svga->gdcreg[0x09 + bank_index];
else /* single bank */
offset = svga->gdcreg[0x09];
if ((svga->gdcreg[0x0b] & 0x20) != 0)
offset <<= 14;
else
offset <<= 12;
if (clgd->vram_size <= offset)
limit = 0;
else
limit = clgd->vram_size - offset;
if (((svga->gdcreg[0x0b] & 0x01) == 0) && (bank_index != 0)) {
if (limit > 0x8000) {
offset += 0x8000;
limit -= 0x8000;
} else {
limit = 0;
}
}
if (limit > 0) {
clgd->bank[bank_index] = offset;
clgd->limit[bank_index] = limit;
} else {
clgd->bank[bank_index] = 0;
clgd->limit[bank_index] = 0;
}
}
void clgd_recalctimings(svga_t *svga)
{
clgd_t *clgd = (clgd_t *)svga->p;
uint32_t iWidth, iHeight;
uint8_t iDispBpp;
svga->ma_latch = (svga->crtc[0x0c] << 8)
+ svga->crtc[0x0d]
+ ((svga->crtc[0x1b] & 0x01) << 16)
+ ((svga->crtc[0x1b] & 0x0c) << 15)
+ ((svga->crtc[0x1d] & 0x80) << 12);
svga->ma_latch <<= 2;
iHeight = 1 + svga->crtc[0x12]
+ ((svga->crtc[0x07] & 0x02) << 7)
+ ((svga->crtc[0x07] & 0x40) << 3);
if ((svga->crtc[0x1a] & 0x01) > 0) {
iHeight <<= 1;
svga->vtotal *= 2;
svga->dispend *= 2;
svga->vblankstart *= 2;
svga->vsyncstart *= 2;
svga->split *= 2;
}
iWidth = (svga->crtc[0x01] + 1) * 8;
iDispBpp = 4;
if ((svga->seqregs[0x07] & 0x1) == CIRRUS_SR7_BPP_SVGA)
{
pclog("Cirrus SVGA extended sequencer mode %x\n", svga->seqregs[0x07]);
switch (svga->seqregs[0x07] & CIRRUS_SR7_BPP_MASK)
{
case CIRRUS_SR7_BPP_8:
iDispBpp = 8;
svga->render = svga_render_8bpp_highres;
break;
case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
case CIRRUS_SR7_BPP_16:
case 0x7:
if (clgd->ramdac.ctrl & 0x1)
{
iDispBpp = 16;
svga->render = svga_render_16bpp_highres;
}
else
{
iDispBpp = 15;
svga->render = svga_render_15bpp_highres;
}
break;
case 0x3:
case CIRRUS_SR7_BPP_24:
case 0x5:
case 0xe:
iDispBpp = 24;
svga->render = svga_render_24bpp_highres;
break;
case CIRRUS_SR7_BPP_32:
iDispBpp = 32;
svga->render = svga_render_32bpp_highres;
break;
}
}
if ((iWidth != svga->video_res_x) || (iHeight != svga->video_res_y)
|| (iDispBpp != svga->bpp)) {
pclog("Cirrus switched to %u x %u x %u\n", iWidth, iHeight, iDispBpp);
}
svga->video_res_x = iWidth;
svga->video_res_y = iHeight;
svga->bpp = iDispBpp;
// pclog("MA now %05X %02X\n", svga->ma_latch, svga->crtc[0x1b]);
}
void clgd_hwcursor_draw(svga_t *svga, int displine)
{
int x;
uint8_t dat[2];
int xx;
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
int largecur = (svga->seqregs[0x12] & 4);
int cursize = (largecur) ? 64 : 32;
int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0;
int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0;
for (x = 0; x < cursize; x += 8)
{
dat[0] = svga->vram[svga->hwcursor_latch.addr];
dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
for (xx = 0; xx < 8; xx++)
{
if (offset >= svga->hwcursor_latch.x)
{
if (dat[1] & 0x80)
((uint32_t *)buffer32->line[displine + y_add])[offset + cursize + x_add] = 0;
if (dat[0] & 0x80)
((uint32_t *)buffer32->line[displine + y_add])[offset + cursize + x_add] ^= 0xffffff;
}
offset++;
dat[0] <<= 1;
dat[1] <<= 1;
}
svga->hwcursor_latch.addr++;
}
}
void cirrus_update_memory_access(clgd_t *clgd)
{
svga_t *svga = &clgd->svga;
if ((svga->seqregs[0x17] & 0x44) == 0x44)
{
goto generic_io;
}
else if (clgd->src_ptr != clgd->src_ptr_end)
{
goto generic_io;
}
else
{
if ((svga->gdcreg[0x0B] & 0x14) == 0x14)
{
goto generic_io;
}
else if (svga->gdcreg[0x0B] & 0x02)
{
goto generic_io;
}
svga->writemode = svga->gdcreg[0x05] & 7;
if (svga->writemode < 4 || svga->writemode > 5 || ((svga->gdcreg[0x0B] & 0x4) == 0))
{
//pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04);
switch (svga->gdcreg[6] & 0x0C)
{
case 0x0: /*128k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
mem_mapping_disable(&clgd->mmio_mapping);
svga->banked_mask = 0xffff;
break;
case 0x4: /*64k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
if (svga->seqregs[0x17] & 0x04)
mem_mapping_set_addr(&clgd->mmio_mapping, 0xb8000, 0x00100);
svga->banked_mask = 0xffff;
break;
case 0x8: /*32k at B0000*/
mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
mem_mapping_disable(&clgd->mmio_mapping);
svga->banked_mask = 0x7fff;
break;
case 0xC: /*32k at B8000*/
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
mem_mapping_disable(&clgd->mmio_mapping);
svga->banked_mask = 0x7fff;
break;
}
}
else
{
generic_io:
mem_mapping_disable(&svga->mapping);
mem_mapping_disable(&clgd->mmio_mapping);
}
}
}
void svga_write_mode45_8bpp(clgd_t *clgd, uint8_t mode, uint32_t offset, uint8_t mem_value)
{
int x;
uint8_t val = mem_value;
uint8_t *dst;
svga_t *svga = &clgd->svga;
dst = svga->vram + (offset &= svga->vrammask);
svga->changedvram[(offset &= svga->vrammask) >> 12] = changeframecount;
for (x = 0; x < 8; x++)
{
if (val & 0x80)
{
*dst = clgd->blt.fg_col;
}
else
{
*dst = clgd->blt.bg_col;
}
val <<= 1;
dst++;
}
}
void svga_write_mode45_16bpp(clgd_t *clgd, unsigned mode, unsigned offset, uint32_t mem_value)
{
int x;
unsigned val = mem_value;
uint8_t *dst;
svga_t *svga = &clgd->svga;
dst = svga->vram + (offset &= svga->vrammask);
svga->changedvram[(offset &= svga->vrammask) >> 12] = changeframecount;
for (x = 0; x < 8; x++)
{
if (val & 0x80)
{
*dst = clgd->blt.fg_col;
*(dst + 1) = svga->gdcreg[0x11];
}
else
{
*dst = clgd->blt.bg_col;
*(dst + 1) = svga->gdcreg[0x10];
}
val <<= 1;
dst += 2;
}
}
uint8_t cirrus_mmio_blt_read(uint32_t address, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_t *svga = &clgd->svga;
uint8_t value;
switch(address & 0xff)
{
case (CIRRUS_MMIO_BLTBGCOLOR + 0):
value = svga->gdcreg[0x00];
break;
case (CIRRUS_MMIO_BLTBGCOLOR + 1):
value = svga->gdcreg[0x10];
break;
case (CIRRUS_MMIO_BLTBGCOLOR + 2):
value = svga->gdcreg[0x12];
break;
case (CIRRUS_MMIO_BLTBGCOLOR + 3):
value = svga->gdcreg[0x14];
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 0):
value = svga->gdcreg[0x01];
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 1):
value = svga->gdcreg[0x11];
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 2):
value = svga->gdcreg[0x13];
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 3):
value = svga->gdcreg[0x15];
break;
case (CIRRUS_MMIO_BLTWIDTH + 0):
value = svga->gdcreg[0x20];
break;
case (CIRRUS_MMIO_BLTWIDTH + 1):
value = svga->gdcreg[0x21];
break;
case (CIRRUS_MMIO_BLTHEIGHT + 0):
value = svga->gdcreg[0x22];
break;
case (CIRRUS_MMIO_BLTHEIGHT + 1):
value = svga->gdcreg[0x23];
break;
case (CIRRUS_MMIO_BLTDESTPITCH + 0):
value = svga->gdcreg[0x24];
break;
case (CIRRUS_MMIO_BLTDESTPITCH + 1):
value = svga->gdcreg[0x25];
break;
case (CIRRUS_MMIO_BLTSRCPITCH + 0):
value = svga->gdcreg[0x26];
break;
case (CIRRUS_MMIO_BLTSRCPITCH + 1):
value = svga->gdcreg[0x27];
break;
case (CIRRUS_MMIO_BLTDESTADDR + 0):
value = svga->gdcreg[0x28];
break;
case (CIRRUS_MMIO_BLTDESTADDR + 1):
value = svga->gdcreg[0x29];
break;
case (CIRRUS_MMIO_BLTDESTADDR + 2):
value = svga->gdcreg[0x2a];
break;
case (CIRRUS_MMIO_BLTSRCADDR + 0):
value = svga->gdcreg[0x2c];
break;
case (CIRRUS_MMIO_BLTSRCADDR + 1):
value = svga->gdcreg[0x2d];
break;
case (CIRRUS_MMIO_BLTSRCADDR + 2):
value = svga->gdcreg[0x2e];
break;
case (CIRRUS_MMIO_BLTWRITEMASK):
value = svga->gdcreg[0x2f];
break;
case (CIRRUS_MMIO_BLTMODE):
value = svga->gdcreg[0x30];
break;
case (CIRRUS_MMIO_BLTROP):
value = svga->gdcreg[0x32];
break;
case (CIRRUS_MMIO_BLTMODEEXT):
value = svga->gdcreg[0x33];
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
value = svga->gdcreg[0x34];
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
value = svga->gdcreg[0x35];
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
value = svga->gdcreg[0x38];
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
value = svga->gdcreg[0x39];
break;
}
return value;
}
void cirrus_mmio_blt_write(uint32_t address, uint8_t value, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_t *svga = &clgd->svga;
switch(address & 0xff)
{
case (CIRRUS_MMIO_BLTBGCOLOR + 0):
svga->gdcreg[0x00] = value;
break;
case (CIRRUS_MMIO_BLTBGCOLOR + 1):
svga->gdcreg[0x10] = value;
break;
case (CIRRUS_MMIO_BLTBGCOLOR + 2):
svga->gdcreg[0x12] = value;
break;
case (CIRRUS_MMIO_BLTBGCOLOR + 3):
svga->gdcreg[0x14] = value;
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 0):
svga->gdcreg[0x01] = value;
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 1):
svga->gdcreg[0x11] = value;
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 2):
svga->gdcreg[0x13] = value;
break;
case (CIRRUS_MMIO_BLTFGCOLOR + 3):
svga->gdcreg[0x15] = value;
break;
case (CIRRUS_MMIO_BLTWIDTH + 0):
svga->gdcreg[0x20] = value;
break;
case (CIRRUS_MMIO_BLTWIDTH + 1):
svga->gdcreg[0x21] = value;
break;
case (CIRRUS_MMIO_BLTHEIGHT + 0):
svga->gdcreg[0x22] = value;
break;
case (CIRRUS_MMIO_BLTHEIGHT + 1):
svga->gdcreg[0x23] = value;
break;
case (CIRRUS_MMIO_BLTDESTPITCH + 0):
svga->gdcreg[0x24] = value;
break;
case (CIRRUS_MMIO_BLTDESTPITCH + 1):
svga->gdcreg[0x25] = value;
break;
case (CIRRUS_MMIO_BLTSRCPITCH + 0):
svga->gdcreg[0x26] = value;
break;
case (CIRRUS_MMIO_BLTSRCPITCH + 1):
svga->gdcreg[0x27] = value;
break;
case (CIRRUS_MMIO_BLTDESTADDR + 0):
svga->gdcreg[0x28] = value;
break;
case (CIRRUS_MMIO_BLTDESTADDR + 1):
svga->gdcreg[0x29] = value;
break;
case (CIRRUS_MMIO_BLTDESTADDR + 2):
svga->gdcreg[0x2a] = value;
break;
case (CIRRUS_MMIO_BLTSRCADDR + 0):
svga->gdcreg[0x2c] = value;
break;
case (CIRRUS_MMIO_BLTSRCADDR + 1):
svga->gdcreg[0x2d] = value;
break;
case (CIRRUS_MMIO_BLTSRCADDR + 2):
svga->gdcreg[0x2e] = value;
break;
case (CIRRUS_MMIO_BLTWRITEMASK):
svga->gdcreg[0x2f] = value;
break;
case (CIRRUS_MMIO_BLTMODE):
svga->gdcreg[0x30] = value;
break;
case (CIRRUS_MMIO_BLTROP):
svga->gdcreg[0x32] = value;
break;
case (CIRRUS_MMIO_BLTMODEEXT):
svga->gdcreg[0x33] = value;
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
svga->gdcreg[0x34] = value;
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
svga->gdcreg[0x35] = value;
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
svga->gdcreg[0x38] = value;
break;
case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
svga->gdcreg[0x39] = value;
break;
}
}
void cirrus_write(uint32_t addr, uint8_t val, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_t *svga = &clgd->svga;
// pclog("gd5429_write : %05X %02X ", addr, val);
if (clgd->src_ptr != clgd->src_ptr_end)
{
/* bitblt */
*clgd->src_ptr++ = (uint8_t) val;
if (clgd->src_ptr >= clgd->src_ptr_end)
{
cirrus_bitblt_cputovideo_next(clgd, svga);
}
}
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + clgd->bank[(addr >> 15) & 1];
// pclog("%08X\n", addr);
// svga_write_linear(addr, val, &clgd->svga);
svga->writemode = svga->gdcreg[0x05] & 0x7;
if (svga->writemode < 4 || svga->writemode > 5 || ((svga->gdcreg[0x0B] & 0x4) == 0)) {
svga_write_linear(addr, val, &clgd->svga);
} else {
if ((svga->gdcreg[0x0B] & 0x14) != 0x14) {
svga_write_mode45_8bpp(clgd, svga->writemode,
addr,
val);
} else {
svga_write_mode45_16bpp(clgd, svga->writemode,
addr,
val);
}
}
}
uint8_t cirrus_read(uint32_t addr, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_t *svga = &clgd->svga;
uint8_t ret;
// pclog("gd5429_read : %05X ", addr);
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + clgd->bank[(addr >> 15) & 1];
ret = svga_read_linear(addr, &clgd->svga);
// pclog("%08X %02X\n", addr, ret);
return ret;
}
void *clgd_common_init(char *romfn, uint8_t id)
{
clgd = malloc(sizeof(clgd_t));
svga_t *svga = &clgd->svga;
memset(clgd, 0, sizeof(clgd_t));
rom_init(&clgd->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
svga_init(&clgd->svga, clgd, 1 << 21, /*2mb*/
clgd_recalctimings,
clgd_in, clgd_out,
clgd_hwcursor_draw,
NULL);
mem_mapping_set_handler(&svga->mapping, cirrus_read, NULL, NULL, cirrus_write, NULL, NULL);
mem_mapping_set_p(&svga->mapping, clgd);
mem_mapping_add(&clgd->mmio_mapping, 0, 0, cirrus_mmio_blt_read, NULL, NULL, cirrus_mmio_blt_write, NULL, NULL, NULL, 0, clgd);
io_sethandler(0x03c0, 0x0020, clgd_in, NULL, NULL, clgd_out, NULL, NULL, clgd);
if (id < CIRRUS_ID_CLGD5428)
{
/* 1 MB */
clgd->vram_size = (1 << 20);
clgd->vram_code = 2;
svga->seqregs[0xf] = 0x18;
svga->seqregs[0x1f] = 0x22;
}
else if ((id >= CIRRUS_ID_CLGD5428) && (id <= CIRRUS_ID_CLGD5430))
{
/* 2 MB */
clgd->vram_size = (1 << 21);
clgd->vram_code = 3;
svga->seqregs[0xf] = 0x18;
svga->seqregs[0x1f] = 0x22;
}
else if (id >= CIRRUS_ID_CLGD5434)
{
/* 4 MB */
clgd->vram_size = (1 << 22);
clgd->vram_code = 4;
svga->seqregs[0xf] = 0x98;
svga->seqregs[0x1f] = 0x2d;
svga->seqregs[0x17] = 0x20;
svga->gdcreg[0x18] = 0xf;
}
// Seems the 5436 and 5446 BIOS'es never turn on that bit until it's actually needed,
// therefore they also don't turn it back off on 640x480x4bpp,
// therefore, we need to make sure the VRAM mask is correct at start.
svga->vrammask = (svga->crtc[0x1b] & 2) ? (clgd->vram_size - 1) : 0x3ffff;
clgd->linear_mmio_mask = (svga->crtc[0x1b] & 2) ? (clgd->vram_size - 256) : (0x40000 - 256);
svga->seqregs[0x15] = clgd->vram_code;
if ((id >= CIRRUS_ID_CLGD5422) && (id <= CIRRUS_ID_CLGD5429)) svga->seqregs[0xa] = (clgd->vram_code << 3);
svga->crtc[0x27] = id;
// clgd_recalc_mapping(clgd);
/* force refresh */
// cirrus_update_bank_ptr(s, 0);
// cirrus_update_bank_ptr(s, 1);
init_rops();
return clgd;
}
void *gd6235_init()
{
return clgd_common_init("roms/vga6235.rom", CIRRUS_ID_CLGD6235);
}
void *gd5422_init()
{
return clgd_common_init("roms/CL5422.ROM", CIRRUS_ID_CLGD5422);
}
void *gd5429_init()
{
return clgd_common_init("roms/5429.vbi", CIRRUS_ID_CLGD5429);
}
void *gd5430_init()
{
return clgd_common_init("roms/pci.BIN", CIRRUS_ID_CLGD5430);
}
void *dia5430_init()
{
return clgd_common_init("roms/diamondvlbus.BIN", CIRRUS_ID_CLGD5430);
}
void *gd5434_init()
{
return clgd_common_init("roms/japan.BIN", CIRRUS_ID_CLGD5434);
}
void *gd5436_init()
{
return clgd_common_init("roms/5436.VBI", CIRRUS_ID_CLGD5436);
}
void *gd5440_init()
{
return clgd_common_init("roms/5440BIOS.BIN", CIRRUS_ID_CLGD5440);
}
void *gd5446_init()
{
return clgd_common_init("roms/5446BV.VBI", CIRRUS_ID_CLGD5446);
}
static int gd5422_available()
{
return rom_present("roms/CL5422.ROM");
}
static int gd5429_available()
{
return rom_present("roms/5429.vbi");
}
static int gd5430_available()
{
return rom_present("roms/pci.BIN");
}
static int dia5430_available()
{
return rom_present("roms/diamondvlbus.BIN");
}
static int gd5434_available()
{
return rom_present("roms/japan.BIN");
}
static int gd5436_available()
{
return rom_present("roms/5436.VBI");
}
static int gd5440_available()
{
return rom_present("roms/5440BIOS.BIN");
}
static int gd5446_available()
{
return rom_present("roms/5446BV.VBI");
}
static int gd6235_available()
{
return rom_present("roms/vga6235.rom");
}
void clgd_close(void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_close(&clgd->svga);
free(clgd);
}
void clgd_speed_changed(void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_recalctimings(&clgd->svga);
}
void clgd_force_redraw(void *p)
{
clgd_t *clgd = (clgd_t *)p;
clgd->svga.fullchange = changeframecount;
}
void clgd_add_status_info(char *s, int max_len, void *p)
{
clgd_t *clgd = (clgd_t *)p;
svga_add_status_info(s, max_len, &clgd->svga);
}
device_t gd5422_device =
{
"Cirrus Logic GD5422",
// DEVICE_NOT_WORKING,
0,
gd5422_init,
clgd_close,
gd5422_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd5429_device =
{
"Cirrus Logic GD5429",
// DEVICE_NOT_WORKING,
0,
gd5429_init,
clgd_close,
gd5429_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd5430_device =
{
"Cirrus Logic GD5430",
// DEVICE_NOT_WORKING,
0,
gd5430_init,
clgd_close,
gd5430_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t dia5430_device =
{
"Diamond CL-GD5430",
// DEVICE_NOT_WORKING,
0,
dia5430_init,
clgd_close,
dia5430_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd5434_device =
{
"Cirrus Logic GD5434",
// DEVICE_NOT_WORKING,
0,
gd5434_init,
clgd_close,
gd5434_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd5436_device =
{
"Cirrus Logic GD5436",
// DEVICE_NOT_WORKING,
0,
gd5436_init,
clgd_close,
gd5436_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd5440_device =
{
"Cirrus Logic GD5440",
// DEVICE_NOT_WORKING,
0,
gd5440_init,
clgd_close,
gd5440_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd5446_device =
{
"Cirrus Logic GD5446",
// DEVICE_NOT_WORKING,
0,
gd5446_init,
clgd_close,
gd5446_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};
device_t gd6235_device =
{
"Cirrus Logic GD6235",
// DEVICE_NOT_WORKING,
0,
gd6235_init,
clgd_close,
gd6235_available,
clgd_speed_changed,
clgd_force_redraw,
clgd_add_status_info
};