Reworked EGA plotting code a bit.

Tweaked EGA odd/even handling - 640x350x4 with 64kb video memory now works.
This commit is contained in:
SarahW 2017-07-18 21:48:14 +01:00
commit 47b4e1da1c

View file

@ -250,65 +250,23 @@ void ega_recalctimings(ega_t *ega)
// printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]); // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]);
} }
void ega_poll(void *p) static void ega_draw_text(ega_t *ega)
{ {
ega_t *ega = (ega_t *)p;
uint8_t chr, dat, attr;
uint32_t charaddr;
int x, xx; int x, xx;
for (x = 0; x < ega->hdisp; x++)
{
int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
uint8_t chr = ega->vram[(ega->ma << 1) & ega->vrammask];
uint8_t attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
uint8_t dat;
uint32_t fg, bg; uint32_t fg, bg;
int offset; uint32_t charaddr;
uint8_t edat[4];
int drawcursor = 0;
if (!ega->linepos) if (attr & 8)
{ charaddr = ega->charsetb + (chr * 128);
ega->vidtime += ega->dispofftime; else
charaddr = ega->charseta + (chr * 128);
ega->stat |= 1;
ega->linepos = 1;
if (ega->dispon)
{
if (ega->firstline == 2000)
{
ega->firstline = ega->displine;
video_wait_for_buffer();
}
if (ega->scrblank)
{
for (x = 0; x < ega->hdisp; x++)
{
switch (ega->seqregs[1] & 9)
{
case 0:
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 9) + xx + 32] = 0;
break;
case 1:
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 8) + xx + 32] = 0;
break;
case 8:
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 18) + xx + 32] = 0;
break;
case 9:
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 16) + xx + 32] = 0;
break;
}
}
}
else if (!(ega->gdcreg[6] & 1))
{
if (fullchange)
{
for (x = 0; x < ega->hdisp; x++)
{
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
if (attr & 8) charaddr = ega->charsetb + (chr * 128);
else charaddr = ega->charseta + (chr * 128);
if (drawcursor) if (drawcursor)
{ {
@ -370,32 +328,94 @@ void ega_poll(void *p)
ega->ma &= ega->vrammask; ega->ma &= ega->vrammask;
} }
} }
}
else static void ega_draw_2bpp(ega_t *ega)
{ {
switch (ega->gdcreg[5] & 0x20) int x;
{ int offset = ((8 - ega->scrollcache) << 1) + 16;
case 0x00:
if (ega->seqregs[1] & 8)
{
offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++) for (x = 0; x <= ega->hdisp; x++)
{ {
if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) uint8_t edat[2];
uint32_t addr = ega->ma;
if (!(ega->crtc[0x17] & 0x40))
{ {
edat[0] = ega->vram[ega->ma | 0x8000]; addr = (addr << 1) & ega->vrammask;
edat[1] = ega->vram[ega->ma | 0x8001]; addr &= ~7;
edat[2] = ega->vram[ega->ma | 0x8002]; if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
edat[3] = ega->vram[ega->ma | 0x8003]; addr |= 4;
if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
addr |= 4;
}
if (!(ega->crtc[0x17] & 0x01))
addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
if (!(ega->crtc[0x17] & 0x02))
addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
edat[0] = ega->vram[addr];
edat[1] = ega->vram[addr | 0x1];
if (ega->seqregs[1] & 4)
ega->ma += 2;
else
ega->ma += 4;
ega->ma &= ega->vrammask;
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 14 + offset]= ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 15 + offset] = ega->pallook[ega->egapal[edat[1] & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 12 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 13 + offset] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 10 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 11 + offset] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 8 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 9 + offset] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 6 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 7 + offset] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 4 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 5 + offset] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 2 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 3 + offset] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
}
}
static void ega_draw_4bpp_lowres(ega_t *ega)
{
int x;
int offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++)
{
uint8_t edat[4];
uint8_t dat;
uint32_t addr = ega->ma;
int oddeven = 0;
if (!(ega->crtc[0x17] & 0x40))
{
addr = (addr << 1) & ega->vrammask;
if (ega->seqregs[1] & 4)
oddeven = (addr & 4) ? 1 : 0;
addr &= ~7;
if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
addr |= 4;
if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
addr |= 4;
}
if (!(ega->crtc[0x17] & 0x01))
addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
if (!(ega->crtc[0x17] & 0x02))
addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
if (ega->seqregs[1] & 4)
{
edat[0] = ega->vram[addr | oddeven];
edat[2] = ega->vram[addr | oddeven | 0x2];
edat[1] = edat[3] = 0;
ega->ma += 2;
} }
else else
{ {
edat[0] = ega->vram[ega->ma]; edat[0] = ega->vram[addr];
edat[1] = ega->vram[ega->ma | 0x1]; edat[1] = ega->vram[addr | 0x1];
edat[2] = ega->vram[ega->ma | 0x2]; edat[2] = ega->vram[addr | 0x2];
edat[3] = ega->vram[ega->ma | 0x3]; edat[3] = ega->vram[addr | 0x3];
}
ega->ma += 4; ega->ma += 4;
}
ega->ma &= ega->vrammask; ega->ma &= ega->vrammask;
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
@ -412,26 +432,50 @@ void ega_poll(void *p)
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
} }
} }
else
static void ega_draw_4bpp_highres(ega_t *ega)
{ {
offset = (8 - ega->scrollcache) + 24; int x;
int offset = (8 - ega->scrollcache) + 24;
for (x = 0; x <= ega->hdisp; x++) for (x = 0; x <= ega->hdisp; x++)
{ {
if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) uint8_t edat[4];
uint8_t dat;
uint32_t addr = ega->ma;
int oddeven = 0;
if (!(ega->crtc[0x17] & 0x40))
{ {
edat[0] = ega->vram[ega->ma | 0x8000]; addr = (addr << 1) & ega->vrammask;
edat[1] = ega->vram[ega->ma | 0x8001]; if (ega->seqregs[1] & 4)
edat[2] = ega->vram[ega->ma | 0x8002]; oddeven = (addr & 4) ? 1 : 0;
edat[3] = ega->vram[ega->ma | 0x8003]; addr &= ~7;
if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
addr |= 4;
if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
addr |= 4;
}
if (!(ega->crtc[0x17] & 0x01))
addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
if (!(ega->crtc[0x17] & 0x02))
addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
if (ega->seqregs[1] & 4)
{
edat[0] = ega->vram[addr | oddeven];
edat[2] = ega->vram[addr | oddeven | 0x2];
edat[1] = edat[3] = 0;
ega->ma += 2;
} }
else else
{ {
edat[0] = ega->vram[ega->ma]; edat[0] = ega->vram[addr];
edat[1] = ega->vram[ega->ma | 0x1]; edat[1] = ega->vram[addr | 0x1];
edat[2] = ega->vram[ega->ma | 0x2]; edat[2] = ega->vram[addr | 0x2];
edat[3] = ega->vram[ega->ma | 0x3]; edat[3] = ega->vram[addr | 0x3];
}
ega->ma += 4; ega->ma += 4;
}
ega->ma &= ega->vrammask; ega->ma &= ega->vrammask;
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
@ -448,33 +492,65 @@ void ega_poll(void *p)
((uint32_t *)buffer32->line[ega->displine])[(x << 3) + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
} }
} }
void ega_poll(void *p)
{
ega_t *ega = (ega_t *)p;
int x, xx;
if (!ega->linepos)
{
ega->vidtime += ega->dispofftime;
ega->stat |= 1;
ega->linepos = 1;
if (ega->dispon)
{
if (ega->firstline == 2000)
{
ega->firstline = ega->displine;
video_wait_for_buffer();
}
if (ega->scrblank)
{
for (x = 0; x < ega->hdisp; x++)
{
switch (ega->seqregs[1] & 9)
{
case 0:
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 9) + xx + 32] = 0;
break; break;
case 0x20: case 1:
offset = ((8 - ega->scrollcache) << 1) + 16; for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 8) + xx + 32] = 0;
for (x = 0; x <= ega->hdisp; x++) break;
case 8:
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 18) + xx + 32] = 0;
break;
case 9:
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 16) + xx + 32] = 0;
break;
}
}
}
else if (!(ega->gdcreg[6] & 1))
{ {
if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) if (fullchange)
{ ega_draw_text(ega);
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
} }
else else
{ {
edat[0] = ega->vram[(ega->ma << 1)]; switch (ega->gdcreg[5] & 0x20)
edat[1] = ega->vram[(ega->ma << 1) + 1]; {
} case 0x00:
ega->ma += 4; if (ega->seqregs[1] & 8)
ega->ma &= ega->vrammask; ega_draw_4bpp_lowres(ega);
else
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 14 + offset]= ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 15 + offset] = ega->pallook[ega->egapal[edat[1] & 3]]; ega_draw_4bpp_highres(ega);
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 12 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 13 + offset] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; break;
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 10 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 11 + offset] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]]; case 0x20:
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 8 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 9 + offset] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]]; ega_draw_2bpp(ega);
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 6 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 7 + offset] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 4 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 5 + offset] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 2 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 3 + offset] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
((uint32_t *)buffer32->line[ega->displine])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
}
break; break;
} }
} }
@ -632,6 +708,9 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
if (addr & 1) if (addr & 1)
writemask2 <<= 1; writemask2 <<= 1;
addr &= ~1; addr &= ~1;
if (addr & 0x4000)
addr |= 1;
addr &= ~0x4000;
} }
addr <<= 2; addr <<= 2;
@ -766,6 +845,9 @@ uint8_t ega_read(uint32_t addr, void *p)
{ {
readplane = (readplane & 2) | (addr & 1); readplane = (readplane & 2) | (addr & 1);
addr &= ~1; addr &= ~1;
if (addr & 0x4000)
addr |= 1;
addr &= ~0x4000;
} }
addr <<= 2; addr <<= 2;