Rework (S)VGA memory addressing. Support correct chain-4 mapping, as well

as MA13/14 remapping for non-CGA modes. Fixes corruption on Windows 3.x
when using Paradise drivers, also fixes corruption in Titan.
This commit is contained in:
SarahW 2021-05-29 09:08:34 +01:00
commit 092be3e9d4
12 changed files with 740 additions and 239 deletions

View file

@ -1010,6 +1010,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
{
case 0x31:
s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
svga->force_dword_mode = val & 0x08;
break;
case 0x32:
svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask;
@ -1662,15 +1663,35 @@ static void polygon_setup(s3_t *s3)
}
}
#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \
/*Remap address for chain-4/doubleword style layout*/
static inline uint32_t dword_remap(uint32_t in_addr)
{
return ((in_addr << 2) & 0x3fff0) |
((in_addr >> 14) & 0xc) |
(in_addr & ~0x3fffc);
}
static inline uint32_t dword_remap_w(uint32_t in_addr)
{
return ((in_addr << 2) & 0x1fff8) |
((in_addr >> 14) & 0x6) |
(in_addr & ~0x1fffe);
}
static inline uint32_t dword_remap_l(uint32_t in_addr)
{
return ((in_addr << 2) & 0xfffc) |
((in_addr >> 14) & 0x3) |
(in_addr & ~0xffff);
}
#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ dword_remap(addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)]; \
if (vram_mask) \
dat = ((dat & rd_mask) == rd_mask);
#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[(addr) & (s3->vram_mask >> 2)];
#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ dword_remap(addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)];
#define MIX { \
uint32_t old_dest_dat = dest_dat; \
@ -1699,18 +1720,18 @@ static void polygon_setup(s3_t *s3)
#define WRITE(addr) if (s3->bpp == 0) \
{ \
svga->vram[(addr) & s3->vram_mask] = dest_dat; \
svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \
svga->vram[dword_remap(addr) & s3->vram_mask] = dest_dat; \
svga->changedvram[(dword_remap(addr) & s3->vram_mask) >> 12] = changeframecount; \
} \
else if (s3->bpp == 1) \
{ \
vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \
svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)] = dest_dat; \
svga->changedvram[(dword_remap_w(addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
} \
else \
{ \
vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \
svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)] = dest_dat; \
svga->changedvram[(dword_remap_l(addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
}
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3)
@ -2520,8 +2541,10 @@ void s3_hwcursor_draw(svga_t *svga, int displine)
// pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y);
for (x = 0; x < 64; x += 16)
{
dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
uint32_t remapped_addr = dword_remap(svga->hwcursor_latch.addr);
dat[0] = (svga->vram[remapped_addr] << 8) | svga->vram[remapped_addr + 1];
dat[1] = (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
for (xx = 0; xx < 16; xx++)
{
if (offset >= svga->hwcursor_latch.x)