CL-GD 5446/5480: Implement missing byte swap behavior, fixes fonts with the Windows 3.1 CL-GD 5446 driver when cache is enabled.

This commit is contained in:
OBattler
2023-12-30 00:04:57 +01:00
parent e9bce21ee7
commit 7701174b39

View File

@@ -2074,18 +2074,49 @@ gd54xx_rop(gd54xx_t *gd54xx, uint8_t *res, uint8_t *dst, const uint8_t *src)
}
static uint8_t
gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx)
gd54xx_get_aperture(uint32_t addr)
{
uint32_t ap = addr >> 22;
return (uint8_t) (ap & 0x03);
}
static uint32_t
gd54xx_mem_sys_pos_adj(gd54xx_t *gd54xx, uint8_t ap, uint32_t pos)
{
uint32_t ret = pos;
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) &&
!(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) {
switch (ap) {
case 1:
ret ^= 1;
break;
case 2:
ret ^= 3;
break;
}
}
return ret;
}
static uint8_t
gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx, uint8_t ap)
{
uint32_t adj_pos = gd54xx_mem_sys_pos_adj(gd54xx, ap, gd54xx->blt.msd_buf_pos);
uint8_t ret = 0xff;
if (gd54xx->blt.msd_buf_cnt != 0) {
ret = gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos++];
ret = gd54xx->blt.msd_buf[adj_pos];
gd54xx->blt.msd_buf_pos++;
gd54xx->blt.msd_buf_cnt--;
if (gd54xx->blt.msd_buf_cnt == 0) {
if (gd54xx->countminusone == 1) {
gd54xx->blt.msd_buf_pos = 0;
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY))
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) &&
!(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY))
gd54xx_start_blit(0xff, 8, gd54xx, &gd54xx->svga);
else
gd54xx_start_blit(0xffffffff, 32, gd54xx, &gd54xx->svga);
@@ -2098,14 +2129,17 @@ gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx)
}
static void
gd54xx_mem_sys_src_write(gd54xx_t *gd54xx, uint8_t val)
gd54xx_mem_sys_src_write(gd54xx_t *gd54xx, uint8_t val, uint8_t ap)
{
gd54xx->blt.sys_src32 &= ~(0xff << (gd54xx->blt.sys_cnt << 3));
gd54xx->blt.sys_src32 |= (val << (gd54xx->blt.sys_cnt << 3));
uint32_t adj_pos = gd54xx_mem_sys_pos_adj(gd54xx, ap, gd54xx->blt.sys_cnt);
gd54xx->blt.sys_src32 &= ~(0xff << (adj_pos << 3));
gd54xx->blt.sys_src32 |= (val << (adj_pos << 3));
gd54xx->blt.sys_cnt = (gd54xx->blt.sys_cnt + 1) & 3;
if (gd54xx->blt.sys_cnt == 0) {
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) {
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) &&
!(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) {
for (uint8_t i = 0; i < 32; i += 8)
gd54xx_start_blit((gd54xx->blt.sys_src32 >> i) & 0xff, 8, gd54xx, &gd54xx->svga);
} else
@@ -2120,7 +2154,7 @@ gd54xx_write(uint32_t addr, uint8_t val, void *priv)
svga_t *svga = &gd54xx->svga;
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd54xx_mem_sys_src_write(gd54xx, val);
gd54xx_mem_sys_src_write(gd54xx, val, 0);
return;
}
@@ -2251,13 +2285,6 @@ gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr)
svga->changedvram[addr >> 12] = changeframecount;
}
static uint8_t
gd54xx_get_aperture(uint32_t addr)
{
uint32_t ap = addr >> 22;
return (uint8_t) (ap & 0x03);
}
static int
gd54xx_aperture2_enabled(gd54xx_t *gd54xx)
{
@@ -2294,7 +2321,7 @@ gd54xx_readb_linear(uint32_t addr, void *priv)
/* Do mem sys dest reads here if the blitter is neither paused, nor is there a second aperture. */
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED))
return gd54xx_mem_sys_dest_read(gd54xx);
return gd54xx_mem_sys_dest_read(gd54xx, ap);
switch (ap) {
default:
@@ -2318,8 +2345,9 @@ gd54xx_readb_linear(uint32_t addr, void *priv)
static uint16_t
gd54xx_readw_linear(uint32_t addr, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint32_t old_addr = addr;
uint8_t ap = gd54xx_get_aperture(addr);
uint16_t temp;
@@ -2338,8 +2366,8 @@ gd54xx_readw_linear(uint32_t addr, void *priv)
/* Do mem sys dest reads here if the blitter is neither paused, nor is there a second aperture. */
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
temp = gd54xx_readb_linear(addr, priv);
temp |= gd54xx_readb_linear(addr + 1, priv) << 8;
temp = gd54xx_readb_linear(old_addr, priv);
temp |= gd54xx_readb_linear(old_addr + 1, priv) << 8;
return temp;
}
@@ -2367,8 +2395,9 @@ gd54xx_readw_linear(uint32_t addr, void *priv)
static uint32_t
gd54xx_readl_linear(uint32_t addr, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint32_t old_addr = addr;
uint8_t ap = gd54xx_get_aperture(addr);
uint32_t temp;
@@ -2387,10 +2416,10 @@ gd54xx_readl_linear(uint32_t addr, void *priv)
/* Do mem sys dest reads here if the blitter is neither paused, nor is there a second aperture. */
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
temp = gd54xx_readb_linear(addr, priv);
temp |= gd54xx_readb_linear(addr + 1, priv) << 8;
temp |= gd54xx_readb_linear(addr + 2, priv) << 16;
temp |= gd54xx_readb_linear(addr + 3, priv) << 24;
temp = gd54xx_readb_linear(old_addr, priv);
temp |= gd54xx_readb_linear(old_addr + 1, priv) << 8;
temp |= gd54xx_readb_linear(old_addr + 2, priv) << 16;
temp |= gd54xx_readb_linear(old_addr + 3, priv) << 24;
return temp;
}
@@ -2427,9 +2456,11 @@ static uint8_t
gd5436_aperture2_readb(UNUSED(uint32_t addr), void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
uint8_t ap = gd54xx_get_aperture(addr);
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED))
return gd54xx_mem_sys_dest_read(gd54xx);
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest &&
gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED))
return gd54xx_mem_sys_dest_read(gd54xx, ap);
return 0xff;
}
@@ -2440,7 +2471,8 @@ gd5436_aperture2_readw(uint32_t addr, void *priv)
gd54xx_t *gd54xx = (gd54xx_t *) priv;
uint16_t ret = 0xffff;
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest &&
gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
ret = gd5436_aperture2_readb(addr, priv);
ret |= gd5436_aperture2_readb(addr + 1, priv) << 8;
return ret;
@@ -2455,7 +2487,8 @@ gd5436_aperture2_readl(uint32_t addr, void *priv)
gd54xx_t *gd54xx = (gd54xx_t *) priv;
uint32_t ret = 0xffffffff;
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest &&
gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
ret = gd5436_aperture2_readb(addr, priv);
ret |= gd5436_aperture2_readb(addr + 1, priv) << 8;
ret |= gd5436_aperture2_readb(addr + 2, priv) << 16;
@@ -2470,10 +2503,11 @@ static void
gd5436_aperture2_writeb(UNUSED(uint32_t addr), uint8_t val, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
uint8_t ap = gd54xx_get_aperture(addr);
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest
&& gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED))
gd54xx_mem_sys_src_write(gd54xx, val);
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest &&
gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED))
gd54xx_mem_sys_src_write(gd54xx, val, ap);
}
static void
@@ -2481,8 +2515,8 @@ gd5436_aperture2_writew(uint32_t addr, uint16_t val, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest
&& gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest &&
gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd5436_aperture2_writeb(addr, val, gd54xx);
gd5436_aperture2_writeb(addr + 1, val >> 8, gd54xx);
}
@@ -2493,8 +2527,8 @@ gd5436_aperture2_writel(uint32_t addr, uint32_t val, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest
&& gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest &&
gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd5436_aperture2_writeb(addr, val, gd54xx);
gd5436_aperture2_writeb(addr + 1, val >> 8, gd54xx);
gd5436_aperture2_writeb(addr + 2, val >> 16, gd54xx);
@@ -2508,7 +2542,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv)
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint8_t ap = gd54xx_get_aperture(addr);
uint8_t ap = gd54xx_get_aperture(addr);
if ((svga->seqregs[0x07] & 0x01) == 0) {
svga_write_linear(addr, val, svga);
@@ -2526,7 +2560,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv)
/* Do mem sys src writes here if the blitter is neither paused, nor is there a second aperture. */
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd54xx_mem_sys_src_write(gd54xx, val);
gd54xx_mem_sys_src_write(gd54xx, val, ap);
return;
}
@@ -2552,10 +2586,10 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv)
static void
gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint8_t ap = gd54xx_get_aperture(addr);
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint32_t old_addr = addr;
uint8_t ap = gd54xx_get_aperture(addr);
if ((svga->seqregs[0x07] & 0x01) == 0) {
svga_writew_linear(addr, val, svga);
@@ -2573,8 +2607,8 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv)
/* Do mem sys src writes here if the blitter is neither paused, nor is there a second aperture. */
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd54xx_writeb_linear(addr, val, gd54xx);
gd54xx_writeb_linear(addr + 1, val >> 8, gd54xx);
gd54xx_writeb_linear(old_addr, val, gd54xx);
gd54xx_writeb_linear(old_addr + 1, val >> 8, gd54xx);
return;
}
@@ -2619,10 +2653,10 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv)
static void
gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv)
{
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint8_t ap = gd54xx_get_aperture(addr);
gd54xx_t *gd54xx = (gd54xx_t *) priv;
svga_t *svga = &gd54xx->svga;
uint32_t old_addr = addr;
uint8_t ap = gd54xx_get_aperture(addr);
if ((svga->seqregs[0x07] & 0x01) == 0) {
svga_writel_linear(addr, val, svga);
@@ -2640,10 +2674,10 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv)
/* Do mem sys src writes here if the blitter is neither paused, nor is there a second aperture. */
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd54xx_writeb_linear(addr, val, gd54xx);
gd54xx_writeb_linear(addr + 1, val >> 8, gd54xx);
gd54xx_writeb_linear(addr + 2, val >> 16, gd54xx);
gd54xx_writeb_linear(addr + 3, val >> 24, gd54xx);
gd54xx_writeb_linear(old_addr, val, gd54xx);
gd54xx_writeb_linear(old_addr + 1, val >> 8, gd54xx);
gd54xx_writeb_linear(old_addr + 2, val >> 16, gd54xx);
gd54xx_writeb_linear(old_addr + 3, val >> 24, gd54xx);
return;
}
@@ -2705,7 +2739,7 @@ gd54xx_read(uint32_t addr, void *priv)
return svga_read(addr, svga);
if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED))
return gd54xx_mem_sys_dest_read(gd54xx);
return gd54xx_mem_sys_dest_read(gd54xx, 0);
addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1];
return svga_read_linear(addr, svga);
@@ -2938,7 +2972,7 @@ gd543x_mmio_writeb(uint32_t addr, uint8_t val, void *priv)
svga_t *svga = &gd54xx->svga;
if (!gd543x_do_mmio(svga, addr) && !gd54xx->blt.ms_is_dest && gd54xx->countminusone && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
gd54xx_mem_sys_src_write(gd54xx, val);
gd54xx_mem_sys_src_write(gd54xx, val, 0);
return;
}
@@ -3127,7 +3161,7 @@ gd543x_mmio_read(uint32_t addr, void *priv)
} else if (gd54xx->mmio_vram_overlap)
ret = gd54xx_read(addr, gd54xx);
else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
ret = gd54xx_mem_sys_dest_read(gd54xx);
ret = gd54xx_mem_sys_dest_read(gd54xx, 0);
}
return ret;