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

@ -1,4 +1,5 @@
/*Cirrus Logic CL-GD5429 emulation*/
//SR7.0 = "true packed-pixel memory addressing"
#include <stdlib.h>
#include "ibm.h"
#include "cpu.h"
@ -178,6 +179,8 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
case 0x07:
svga->set_reset_disabled = svga->seqregs[7] & 1;
svga->packed_chain4 = svga->seqregs[7] & 1;
svga_recalctimings(svga);
case 0x17:
if (gd5429->type >= CL_TYPE_GD5429)
gd5429_recalc_mapping(gd5429);
@ -844,11 +847,16 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
svga->fullchange = 2;
if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
addr <<= 3;
else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4))
else if (((svga->chain4 && svga->packed_chain4) || svga->fb_only) && (svga->writemode < 4))
{
writemask2 = 1 << (addr & 3);
addr &= ~3;
}
else if (svga->chain4)
{
writemask2 = 1 << (addr & 3);
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
}
else if (svga->chain2_write)
{
writemask2 &= ~0xa;
@ -1193,13 +1201,18 @@ uint8_t gd5429_read_linear(uint32_t addr, void *p)
if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
addr <<= 3;
else if (svga->chain4 || svga->fb_only)
else if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
return svga->vram[addr & svga->vram_mask];
}
else if (svga->chain4)
{
readplane = addr & 3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
}
else if (svga->chain2_read)
{
readplane = (readplane & 2) | (addr & 1);

View file

@ -496,6 +496,8 @@ void *et4000_init()
NULL,
NULL);
et4000->svga.packed_chain4 = 1;
return et4000;
}
@ -527,6 +529,8 @@ void *et4000k_init()
et4000->svga.ksc5601_swap_mode = 0;
et4000->svga.ksc5601_english_font_type = 0;
et4000->svga.packed_chain4 = 1;
return et4000;
}
@ -571,6 +575,8 @@ void *et4000_kasan_init()
et4000->svga.ksc5601_swap_mode = 0;
et4000->svga.ksc5601_english_font_type = 0x1FF;
et4000->svga.packed_chain4 = 1;
return et4000;
}

View file

@ -1207,6 +1207,8 @@ void *et4000w32p_init()
et4000->fifo_not_full_event = thread_create_event();
et4000->fifo_thread = thread_create(fifo_thread, et4000);
et4000->svga.packed_chain4 = 1;
return et4000;
}

View file

@ -154,6 +154,9 @@ void ht216_out(uint16_t addr, uint8_t val, void *p)
ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0);
ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0);
break;
case 0xfc:
svga->packed_chain4 = val & 0x20;
break;
case 0xff:
svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((val & 0x60) << 11)) << 2;
//pclog("cursor_addr = %05x\n", svga->hwcursor.addr);
@ -421,6 +424,14 @@ static inline uint8_t extalu(int op, uint8_t input_a, uint8_t input_b)
return val;
}
/*Remap address for chain-4/doubleword style layout*/
static inline uint32_t dword_remap(svga_t *svga, uint32_t in_addr)
{
if (svga->packed_chain4)
return in_addr;
return ((in_addr & 0xfffc) << 2) | ((in_addr & 0x30000) >> 14) | (in_addr & ~0x3ffff);
}
static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded)
{
svga_t *svga = &ht216->svga;
@ -430,10 +441,10 @@ static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
if (svga->chain4 || svga->fb_only)
if (svga->chain4)
{
writemask2=1<<(addr&3);
addr&=~3;
writemask2 = 1 << (addr & 3);
addr = dword_remap(svga, addr) & ~3;
}
else if (svga->chain2_write)
{
@ -666,9 +677,10 @@ static void ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat
uint8_t input_a = 0, input_b = 0;
uint8_t fg, bg;
uint8_t output;
uint32_t remapped_addr = dword_remap(svga, addr);
if (ht216->ht_regs[0xcd] & HT_REG_CD_RMWMDE) /*RMW*/
input_b = svga->vram[addr];
input_b = svga->vram[remapped_addr];
else
input_b = ht216->bg_latch[addr & 7];
@ -695,9 +707,9 @@ static void ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat
bg = extalu(ht216->ht_regs[0xce] & 0xf, input_a, input_b);
// svga->vram[addr]
output = (fg & rop_select) | (bg & ~rop_select);
svga->vram[addr] = (svga->vram[addr] & ~bit_mask) | (output & bit_mask);
svga->vram[addr] = (svga->vram[remapped_addr] & ~bit_mask) | (output & bit_mask);
// pclog(" A=%02x B=%02x R=%02x FG=%02x BG=%02x ops=%02x val=%02x addr=%05x\n", input_a, input_b, rop_select, fg, bg, ht216->ht_regs[0xce], svga->vram[addr], addr);
svga->changedvram[addr >> 12] = changeframecount;
svga->changedvram[remapped_addr >> 12] = changeframecount;
}
static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val)
@ -909,7 +921,7 @@ static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr)
egareads++;
if (svga->chain4 || svga->fb_only)
if (svga->chain4)
{
// if (ht216->ht_regs[0xcd])
// pclog(" addr=%08x decode_mask=%08x vram_max=%08x\n", addr, svga->decode_mask, svga->vram_max);
@ -920,20 +932,20 @@ static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr)
latch_addr = (addr & svga->vram_mask) & ~7;
if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE)
latch_addr += (svga->gdcreg[3] & 7);
ht216->bg_latch[0] = svga->vram[latch_addr];
ht216->bg_latch[1] = svga->vram[latch_addr + 1];
ht216->bg_latch[2] = svga->vram[latch_addr + 2];
ht216->bg_latch[3] = svga->vram[latch_addr + 3];
ht216->bg_latch[4] = svga->vram[latch_addr + 4];
ht216->bg_latch[5] = svga->vram[latch_addr + 5];
ht216->bg_latch[6] = svga->vram[latch_addr + 6];
ht216->bg_latch[7] = svga->vram[latch_addr + 7];
ht216->bg_latch[0] = svga->vram[dword_remap(svga, latch_addr)];
ht216->bg_latch[1] = svga->vram[dword_remap(svga, latch_addr + 1)];
ht216->bg_latch[2] = svga->vram[dword_remap(svga, latch_addr + 2)];
ht216->bg_latch[3] = svga->vram[dword_remap(svga, latch_addr + 3)];
ht216->bg_latch[4] = svga->vram[dword_remap(svga, latch_addr + 4)];
ht216->bg_latch[5] = svga->vram[dword_remap(svga, latch_addr + 5)];
ht216->bg_latch[6] = svga->vram[dword_remap(svga, latch_addr + 6)];
ht216->bg_latch[7] = svga->vram[dword_remap(svga, latch_addr + 7)];
/*pclog(" Read %08x %02x %02x %02x %02x %02x %02x %02x %02x\n", addr,
ht216->bg_latch[0],ht216->bg_latch[1],ht216->bg_latch[2],ht216->bg_latch[3],
ht216->bg_latch[4],ht216->bg_latch[5],ht216->bg_latch[6],ht216->bg_latch[7]);*/
return svga->vram[addr & svga->vram_mask];
return svga->vram[dword_remap(svga, addr) & svga->vram_mask];
}
else if (svga->chain2_read)
{

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)

View file

@ -3945,6 +3945,9 @@ static void *s3_virge_init()
ddc_init();
//TODO ViRGE does not use packed chain4
virge->svga.packed_chain4 = 1;
return virge;
}
@ -4044,6 +4047,9 @@ static void *s3_virge_375_init()
ddc_init();
//TODO ViRGE does not use packed chain4
virge->svga.packed_chain4 = 1;
return virge;
}

View file

@ -116,7 +116,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p)
case 4:
svga->chain2_write = !(val & 4);
svga->chain4 = val & 8;
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) &&
((svga->chain4 && svga->packed_chain4) || svga->fb_only);
break;
}
break;
@ -201,7 +202,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p)
case 7: svga->colournocare=val; break;
}
svga->gdcreg[svga->gdcaddr & 15] = val;
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) &&
((svga->chain4 && svga->packed_chain4) || svga->fb_only);
if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
svga_recalctimings(svga);
break;
@ -444,6 +446,8 @@ void svga_recalctimings(svga_t *svga)
svga->dispontime = TIMER_USEC;
if (svga->dispofftime < TIMER_USEC)
svga->dispofftime = TIMER_USEC;
svga_recalc_remap_func(svga);
/* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock);
printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart);
printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]);
@ -816,11 +820,17 @@ void svga_write(uint32_t addr, uint8_t val, void *p)
addr += svga->write_bank;
if (!(svga->gdcreg[6] & 1)) svga->fullchange=2;
if (svga->chain4 || svga->fb_only)
if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
writemask2=1<<(addr&3);
addr&=~3;
}
else if (svga->chain4)
{
writemask2 = 1 << (addr & 3);
addr &= ~3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
}
else if (svga->chain2_write)
{
writemask2 &= ~0xa;
@ -1007,7 +1017,7 @@ uint8_t svga_read(uint32_t addr, void *p)
// pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode);
// pclog("%i\n", svga->readmode);
if (svga->chain4 || svga->fb_only)
if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
@ -1019,6 +1029,11 @@ uint8_t svga_read(uint32_t addr, void *p)
svga->ld = svga->vram[latch_addr | 0x3];
return svga->vram[addr & svga->vram_mask];
}
else if (svga->chain4)
{
readplane = addr & 3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
}
else if (svga->chain2_read)
{
readplane = (readplane & 2) | (addr & 1);
@ -1082,11 +1097,16 @@ void svga_write_linear(uint32_t addr, uint8_t val, void *p)
if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
if (svga->chain4 || svga->fb_only)
if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
writemask2=1<<(addr&3);
addr&=~3;
}
else if (svga->chain4)
{
writemask2 = 1 << (addr & 3);
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
}
else if (svga->chain2_write)
{
writemask2 &= ~0xa;
@ -1262,13 +1282,18 @@ uint8_t svga_read_linear(uint32_t addr, void *p)
egareads++;
if (svga->chain4 || svga->fb_only)
if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
return svga->vram[addr & svga->vram_mask];
}
else if (svga->chain4)
{
readplane = addr & 3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
}
else if (svga->chain2_read)
{
readplane = (readplane & 2) | (addr & 1);
@ -1276,7 +1301,9 @@ uint8_t svga_read_linear(uint32_t addr, void *p)
addr <<= 2;
}
else
{
addr<<=2;
}
addr &= svga->decode_mask;

View file

@ -148,6 +148,16 @@ typedef struct svga_t
/*Used to implement CRTC[0x17] bit 2 hsync divisor*/
int hsync_divisor;
/*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4
addresses are shifted to match*/
int packed_chain4;
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
int remap_required;
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);
} svga_t;
extern int svga_init(svga_t *svga, void *p, int memsize,

View file

@ -3,6 +3,7 @@
#include "video.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_svga_render_remap.h"
void svga_render_null(svga_t *svga)
{
@ -58,9 +59,12 @@ void svga_render_text_40(svga_t *svga)
for (x = 0; x < svga->hdisp; x += xinc)
{
uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
chr = svga->vram[addr];
attr = svga->vram[addr+1];
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
@ -122,9 +126,12 @@ void svga_render_text_80(svga_t *svga)
for (x = 0; x < svga->hdisp; x += xinc)
{
uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
chr = svga->vram[addr];
attr = svga->vram[addr+1];
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
@ -186,10 +193,12 @@ void svga_render_text_80_ksc5601(svga_t *svga)
for (x = 0; x < svga->hdisp; x += xinc)
{
uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask];
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
chr = svga->vram[addr];
nextchr = svga->vram[addr + 8];
attr = svga->vram[addr + 1];
if (drawcursor)
{
@ -304,11 +313,9 @@ void svga_render_text_80_ksc5601(svga_t *svga)
void svga_render_2bpp_lowres(svga_t *svga)
{
int changed_offset;
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = ((8 - svga->scrollcache) << 1) + 16;
@ -320,10 +327,11 @@ void svga_render_2bpp_lowres(svga_t *svga)
for (x = 0; x <= svga->hdisp; x += 16)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint8_t dat[2];
dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
dat[0] = svga->vram[addr];
dat[1] = svga->vram[addr + 1];
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
@ -343,11 +351,9 @@ void svga_render_2bpp_lowres(svga_t *svga)
void svga_render_2bpp_highres(svga_t *svga)
{
int changed_offset;
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - svga->scrollcache) + 24;
@ -359,30 +365,31 @@ void svga_render_2bpp_highres(svga_t *svga)
for (x = 0; x <= svga->hdisp; x += 8)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint8_t dat[2];
dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
dat[0] = svga->vram[addr];
dat[1] = svga->vram[addr + 1];
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]];
p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]];
p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]];
p[3] = svga->pallook[svga->egapal[dat[0] & 3]];
p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]];
p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]];
p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]];
p[7] = svga->pallook[svga->egapal[dat[1] & 3]];
p += 8;
*p++ = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]];
*p++ = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]];
*p++ = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]];
*p++ = svga->pallook[svga->egapal[dat[0] & 3]];
*p++ = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]];
*p++ = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]];
*p++ = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]];
*p++ = svga->pallook[svga->egapal[dat[1] & 3]];
}
}
}
void svga_render_4bpp_lowres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = ((8 - svga->scrollcache) << 1) + 16;
@ -396,8 +403,9 @@ void svga_render_4bpp_lowres(svga_t *svga)
{
uint8_t edat[4];
uint8_t dat;
uint32_t addr = svga->remap_func(svga, svga->ma);
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]);
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]);
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
@ -421,11 +429,9 @@ void svga_render_4bpp_lowres(svga_t *svga)
void svga_render_4bpp_highres(svga_t *svga)
{
int changed_offset;
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - svga->scrollcache) + 24;
@ -439,32 +445,33 @@ void svga_render_4bpp_highres(svga_t *svga)
{
uint8_t edat[4];
uint8_t dat;
uint32_t addr = svga->remap_func(svga, svga->ma);
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]);
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]);
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
p += 8;
*p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
*p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
}
}
}
void svga_render_8bpp_lowres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
@ -474,6 +481,8 @@ void svga_render_8bpp_lowres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 8)
{
uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
@ -486,13 +495,32 @@ void svga_render_8bpp_lowres(svga_t *svga)
svga->ma += 4;
p += 8;
}
}
else
{
for (x = 0; x <= svga->hdisp; x += 8)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
p[0] = p[1] = svga->pallook[dat & 0xff];
p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff];
p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff];
p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff];
svga->ma += 4;
p += 8;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_8bpp_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -502,31 +530,50 @@ void svga_render_8bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 8)
{
uint32_t dat;
dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
p[0] = svga->pallook[dat & 0xff];
p[1] = svga->pallook[(dat >> 8) & 0xff];
p[2] = svga->pallook[(dat >> 16) & 0xff];
p[3] = svga->pallook[(dat >> 24) & 0xff];
uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
*p++ = svga->pallook[dat & 0xff];
*p++ = svga->pallook[(dat >> 8) & 0xff];
*p++ = svga->pallook[(dat >> 16) & 0xff];
*p++ = svga->pallook[(dat >> 24) & 0xff];
dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
p[4] = svga->pallook[dat & 0xff];
p[5] = svga->pallook[(dat >> 8) & 0xff];
p[6] = svga->pallook[(dat >> 16) & 0xff];
p[7] = svga->pallook[(dat >> 24) & 0xff];
dat = *(uint32_t *)(&svga->vram[(svga->ma+4) & svga->vram_display_mask]);
*p++ = svga->pallook[dat & 0xff];
*p++ = svga->pallook[(dat >> 8) & 0xff];
*p++ = svga->pallook[(dat >> 16) & 0xff];
*p++ = svga->pallook[(dat >> 24) & 0xff];
svga->ma += 8;
p += 8;
}
}
else
{
for (x = 0; x <= svga->hdisp; x += 4)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
svga->ma += 4;
*p++ = svga->pallook[dat & 0xff];
*p++ = svga->pallook[(dat >> 8) & 0xff];
*p++ = svga->pallook[(dat >> 16) & 0xff];
*p++ = svga->pallook[(dat >> 24) & 0xff];
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_15bpp_lowres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
@ -536,26 +583,44 @@ void svga_render_15bpp_lowres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 4)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = video_15to32[dat & 0xffff];
p[x + 1] = video_15to32[dat >> 16];
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x] = video_15to32[dat & 0xffff];
p[x + 1] = video_15to32[dat >> 16];
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
}
svga->ma += x << 1;
}
else
{
for (x = 0; x <= svga->hdisp; x += 2)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_15bpp_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -565,32 +630,51 @@ void svga_render_15bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 8)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = video_15to32[dat & 0xffff];
p[x + 1] = video_15to32[dat >> 16];
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x + 2] = video_15to32[dat & 0xffff];
p[x + 3] = video_15to32[dat >> 16];
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
p[x + 4] = video_15to32[dat & 0xffff];
p[x + 5] = video_15to32[dat >> 16];
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
p[x + 6] = video_15to32[dat & 0xffff];
p[x + 7] = video_15to32[dat >> 16];
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
}
svga->ma += x << 1;
}
else
{
for (x = 0; x <= svga->hdisp; x += 2)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_16bpp_lowres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
@ -600,17 +684,34 @@ void svga_render_16bpp_lowres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 4)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = video_16to32[dat & 0xffff];
p[x + 1] = video_16to32[dat >> 16];
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x] = video_16to32[dat & 0xffff];
p[x + 1] = video_16to32[dat >> 16];
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
}
svga->ma += x << 1;
}
else
{
for (x = 0; x <= svga->hdisp; x += 2)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
svga->ma += 4;
}
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@ -619,7 +720,9 @@ void svga_render_16bpp_lowres(svga_t *svga)
void svga_render_16bpp_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -629,55 +732,106 @@ void svga_render_16bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 8)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = video_16to32[dat & 0xffff];
p[x + 1] = video_16to32[dat >> 16];
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x + 2] = video_16to32[dat & 0xffff];
p[x + 3] = video_16to32[dat >> 16];
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
p[x + 4] = video_16to32[dat & 0xffff];
p[x + 5] = video_16to32[dat >> 16];
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
p[x + 6] = video_16to32[dat & 0xffff];
p[x + 7] = video_16to32[dat >> 16];
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
}
svga->ma += x << 1;
}
else
{
for (x = 0; x <= svga->hdisp; x += 2)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_24bpp_lowres(svga_t *svga)
{
int x, offset;
uint32_t fg;
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - (svga->scrollcache & 6)) + 24;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x++)
{
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 3;
svga->ma &= svga->vram_display_mask;
((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
p[0] = p[1] = dat0 & 0xffffff;
p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16);
p[6] = p[7] = dat2 >> 8;
svga->ma += 12;
}
}
else
{
for (x = 0; x <= svga->hdisp; x += 4)
{
uint32_t dat0, dat1, dat2;
uint32_t addr;
addr = svga->remap_func(svga, svga->ma);
dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
addr = svga->remap_func(svga, svga->ma + 4);
dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
addr = svga->remap_func(svga, svga->ma + 8);
dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
p[0] = p[1] = dat0 & 0xffffff;
p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16);
p[6] = p[7] = dat2 >> 8;
svga->ma += 12;
}
}
}
}
void svga_render_24bpp_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -687,46 +841,84 @@ void svga_render_24bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x += 4)
{
uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
p[x] = dat & 0xffffff;
uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
p[x + 1] = dat & 0xffffff;
dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
p[x + 2] = dat & 0xffffff;
dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
p[x + 3] = dat & 0xffffff;
*p++ = dat0 & 0xffffff;
*p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
*p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16);
*p++ = dat2 >> 8;
svga->ma += 12;
}
}
else
{
for (x = 0; x <= svga->hdisp; x += 4)
{
uint32_t dat0, dat1, dat2;
uint32_t addr;
addr = svga->remap_func(svga, svga->ma);
dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
addr = svga->remap_func(svga, svga->ma + 4);
dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
addr = svga->remap_func(svga, svga->ma + 8);
dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = dat0 & 0xffffff;
*p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
*p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16);
*p++ = dat2 >> 8;
svga->ma += 12;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_32bpp_lowres(svga_t *svga)
{
int x, offset;
uint32_t fg;
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - (svga->scrollcache & 6)) + 24;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x++)
{
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
*p++ = dat & 0xffffff;
*p++ = dat & 0xffffff;
}
svga->ma += x*4;
}
else
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr]);
*p++ = dat & 0xffffff;
*p++ = dat & 0xffffff;
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
@ -734,7 +926,9 @@ void svga_render_32bpp_lowres(svga_t *svga)
91%*/
void svga_render_32bpp_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -744,19 +938,35 @@ void svga_render_32bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
p[x] = dat & 0xffffff;
*p++ = dat & 0xffffff;
}
svga->ma += x*4;
}
else
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = dat & 0xffffff;
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_ABGR8888_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -766,19 +976,35 @@ void svga_render_ABGR8888_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
*p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
}
svga->ma += x*4;
}
else
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_RGBA8888_highres(svga_t *svga)
{
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
uint32_t changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@ -788,12 +1014,26 @@ void svga_render_RGBA8888_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required)
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
p[x] = dat >> 8;
*p++ = dat >> 8;
}
svga->ma += x*4;
}
else
{
for (x = 0; x <= svga->hdisp; x++)
{
uint32_t addr = svga->remap_func(svga, svga->ma);
uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
*p++ = dat >> 8;
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}

View file

@ -9,6 +9,8 @@ extern int scrollcache;
extern uint8_t edatlookup[4][4];
void svga_recalc_remap_func(svga_t *svga);
void svga_render_null(svga_t *svga);
void svga_render_blank(svga_t *svga);
void svga_render_text_40(svga_t *svga);

129
src/vid_svga_render_remap.h Normal file
View file

@ -0,0 +1,129 @@
/*Variables :
byte/word/doubleword mode
word has MA13/MA15->MA0
ET4000 treats doubleword as byte
row 0 -> MA13
row 1 -> MA14
*/
//S3 - enhanced mode mappings CR31.3 can force doubleword mode
//Cirrus Logic handles SVGA writes seperately
//S3, CL, TGUI blitters need checking
//CL, S3, Mach64, ET4000, Banshee, TGUI all okay
//Still to check - ViRGE, HT216
#define VAR_BYTE_MODE (0 << 0)
#define VAR_WORD_MODE_MA13 (1 << 0)
#define VAR_WORD_MODE_MA15 (2 << 0)
#define VAR_DWORD_MODE (3 << 0)
#define VAR_MODE_MASK (3 << 0)
#define VAR_ROW0_MA13 (1 << 2)
#define VAR_ROW1_MA14 (1 << 3)
#define ADDRESS_REMAP_FUNC(nr) \
static uint32_t address_remap_func_ ## nr(svga_t *svga, uint32_t in_addr) \
{ \
uint32_t out_addr; \
\
switch (nr & VAR_MODE_MASK) \
{ \
case VAR_BYTE_MODE: \
out_addr = in_addr; \
break; \
\
case VAR_WORD_MODE_MA13: \
out_addr = ((in_addr << 1) & 0x1fff8) | \
((in_addr >> 13) & 0x4) | \
(in_addr & ~0x1ffff); \
break; \
\
case VAR_WORD_MODE_MA15: \
out_addr = ((in_addr << 1) & 0x1fff8) | \
((in_addr >> 15) & 0x4) | \
(in_addr & ~0x1ffff); \
break; \
\
case VAR_DWORD_MODE: \
out_addr = ((in_addr << 2) & 0x3fff0) | \
((in_addr >> 14) & 0xc) | \
(in_addr & ~0x3ffff); \
break; \
} \
\
if (nr & VAR_ROW0_MA13) \
out_addr = (out_addr & ~(1 << (13+2))) | \
((svga->sc & 1) ? (1 << (13+2)) : 0); \
if (nr & VAR_ROW1_MA14) \
out_addr = (out_addr & ~(1 << (14+2))) | \
((svga->sc & 2) ? (1 << (14+2)) : 0); \
\
return out_addr; \
}
ADDRESS_REMAP_FUNC(0)
ADDRESS_REMAP_FUNC(1)
ADDRESS_REMAP_FUNC(2)
ADDRESS_REMAP_FUNC(3)
ADDRESS_REMAP_FUNC(4)
ADDRESS_REMAP_FUNC(5)
ADDRESS_REMAP_FUNC(6)
ADDRESS_REMAP_FUNC(7)
ADDRESS_REMAP_FUNC(8)
ADDRESS_REMAP_FUNC(9)
ADDRESS_REMAP_FUNC(10)
ADDRESS_REMAP_FUNC(11)
ADDRESS_REMAP_FUNC(12)
ADDRESS_REMAP_FUNC(13)
ADDRESS_REMAP_FUNC(14)
ADDRESS_REMAP_FUNC(15)
static uint32_t (*address_remap_funcs[16])(svga_t *svga, uint32_t in_addr) =
{
address_remap_func_0,
address_remap_func_1,
address_remap_func_2,
address_remap_func_3,
address_remap_func_4,
address_remap_func_5,
address_remap_func_6,
address_remap_func_7,
address_remap_func_8,
address_remap_func_9,
address_remap_func_10,
address_remap_func_11,
address_remap_func_12,
address_remap_func_13,
address_remap_func_14,
address_remap_func_15
};
void svga_recalc_remap_func(svga_t *svga)
{
int func_nr;
if (svga->fb_only)
func_nr = 0;
else
{
if (svga->force_dword_mode)
func_nr = VAR_DWORD_MODE;
else if (svga->crtc[0x14] & (1 << 6))
func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE;
else if (svga->crtc[0x17] & (1 << 6))
func_nr = VAR_BYTE_MODE;
else if (svga->crtc[0x17] & (1 << 5))
func_nr = VAR_WORD_MODE_MA15;
else
func_nr = VAR_WORD_MODE_MA13;
if (!(svga->crtc[0x17] & (1 << 0)))
func_nr |= VAR_ROW0_MA13;
if (!(svga->crtc[0x17] & (1 << 1)))
func_nr |= VAR_ROW1_MA14;
}
// pclog("svga_recalc_remap_func: fb_only=%i chain4=%i packed_chain4=%i crtc[14]=%02x crtc[17]=%02x func_nr=%i\n",
// svga->fb_only, svga->chain4, svga->packed_chain4, svga->crtc[0x14], svga->crtc[0x17], func_nr);
svga->remap_required = (func_nr != 0);
svga->remap_func = address_remap_funcs[func_nr];
}

View file

@ -631,17 +631,34 @@ void tgui_recalcmapping(tgui_t *tgui)
}
}
/*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);
}
void tgui_hwcursor_draw(svga_t *svga, int displine)
{
uint32_t dat[2];
int xx;
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
uint32_t remapped_addr;
if (svga->interlace && svga->hwcursor_oddeven)
svga->hwcursor_latch.addr += 8;
dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7];
remapped_addr = dword_remap(svga->hwcursor_latch.addr);
dat[0] = (svga->vram[remapped_addr] << 24) | (svga->vram[remapped_addr + 1] << 16) | (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
remapped_addr = dword_remap(svga->hwcursor_latch.addr+4);
dat[1] = (svga->vram[remapped_addr] << 24) | (svga->vram[remapped_addr + 1] << 16) | (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
for (xx = 0; xx < 32; xx++)
{
if (offset >= svga->hwcursor_latch.x)
@ -840,8 +857,13 @@ static uint8_t tgui_ext_linear_read(uint32_t addr, void *p)
return 0xff;
addr &= ~0xf;
addr = dword_remap(addr);
for (c = 0; c < 16; c++)
tgui->copy_latch[c] = svga->vram[addr+c];
{
tgui->copy_latch[c] = svga->vram[addr];
addr += ((c & 3) == 3) ? 13 : 1;
}
return svga->vram[addr & svga->vram_mask];
}
@ -871,7 +893,9 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
if (addr >= svga->vram_max)
return;
addr &= svga->vram_mask;
addr &= ~0x7;
addr &= (tgui->ext_gdc_regs[0] & 8) ? ~0xf : ~0x7;
addr = dword_remap(addr);
svga->changedvram[addr >> 12] = changeframecount;
switch (tgui->ext_gdc_regs[0] & 0xf)
@ -882,7 +906,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
@ -892,7 +916,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
@ -902,7 +926,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[0];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
@ -912,15 +936,17 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
addr &= ~0xf;
for (c = 0; c < 16; c++)
*(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c];
{
*(uint8_t *)&svga->vram[addr] = tgui->copy_latch[c];
addr += ((c & 3) == 3) ? 13 : 1;
}
break;
}
}
@ -942,6 +968,8 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
return;
addr &= svga->vram_mask;
addr &= ~0xf;
addr = dword_remap(addr);
svga->changedvram[addr >> 12] = changeframecount;
val = (val >> 8) | (val << 8);
@ -954,7 +982,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
@ -964,7 +992,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
@ -974,7 +1002,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[0];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
@ -984,14 +1012,17 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
for (c = 0; c < 16; c++)
*(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c];
{
*(uint8_t *)&svga->vram[addr] = tgui->copy_latch[c];
addr += ((c & 3) == 3) ? 13 : 1;
}
break;
}
}
@ -1044,8 +1075,8 @@ enum
TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/
};
#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \
else dat = vram_w[addr & 0xfffff];
#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[dword_remap(addr) & 0x1fffff]; \
else dat = vram_w[dword_remap_w(addr) & 0xfffff];
#define MIX() do \
{ \
@ -1061,13 +1092,13 @@ enum
#define WRITE(addr, dat) if (tgui->accel.bpp == 0) \
{ \
svga->vram[addr & 0x1fffff] = dat; \
svga->changedvram[((addr) & 0x1fffff) >> 12] = changeframecount; \
svga->vram[dword_remap(addr) & 0x1fffff] = dat; \
svga->changedvram[(dword_remap(addr) & 0x1fffff) >> 12] = changeframecount; \
} \
else \
{ \
vram_w[addr & 0xfffff] = dat; \
svga->changedvram[((addr) & 0xfffff) >> 11] = changeframecount; \
vram_w[dword_remap_w(addr) & 0xfffff] = dat; \
svga->changedvram[(dword_remap_w(addr) & 0xfffff) >> 11] = changeframecount; \
}
void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)