Implemented odd/even memory mode for EGA and VGA.

This commit is contained in:
TomW 2015-08-12 20:37:39 +01:00
commit 12232fd7b8
5 changed files with 91 additions and 53 deletions

View file

@ -98,6 +98,7 @@ void ega_out(uint16_t addr, uint8_t val, void *p)
break;
case 6:
// pclog("Write mapping %02X\n", val);
ega->chain2 = val & 2;
switch (val & 0xc)
{
case 0x0: /*128k at A0000*/
@ -298,7 +299,7 @@ void ega_poll(void *p)
{
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
attr = ega->vram[((ega->ma << 1) + 4) & 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);
@ -612,6 +613,7 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
{
ega_t *ega = (ega_t *)p;
uint8_t vala, valb, valc, vald;
int writemask2 = ega->writemask;
egawrites++;
cycles -= video_timing_b;
@ -620,18 +622,27 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
if (addr >= 0xB0000) addr &= 0x7fff;
else addr &= 0xffff;
if (ega->chain2)
{
writemask2 &= ~0xa;
if (addr & 1)
writemask2 <<= 1;
addr &= ~1;
}
addr <<= 2;
if (!(ega->gdcreg[6] & 1))
fullchange = 2;
addr <<= 2;
// pclog("%i %08X %i %i %02X %02X %02X %02X %02X\n",chain4,addr,writemode,writemask,gdcreg[8],vram[0],vram[1],vram[2],vram[3]);
switch (ega->writemode)
{
case 1:
if (ega->writemask & 1) ega->vram[addr] = ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = ega->ld;
if (writemask2 & 1) ega->vram[addr] = ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = ega->ld;
break;
case 0:
if (ega->gdcreg[3] & 7)
@ -639,10 +650,10 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
if (ega->gdcreg[8] == 0xff && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1])
{
if (ega->writemask & 1) ega->vram[addr] = val;
if (ega->writemask & 2) ega->vram[addr | 0x1] = val;
if (ega->writemask & 4) ega->vram[addr | 0x2] = val;
if (ega->writemask & 8) ega->vram[addr | 0x3] = val;
if (writemask2 & 1) ega->vram[addr] = val;
if (writemask2 & 2) ega->vram[addr | 0x1] = val;
if (writemask2 & 4) ega->vram[addr | 0x2] = val;
if (writemask2 & 8) ega->vram[addr | 0x3] = val;
}
else
{
@ -658,28 +669,28 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
switch (ega->gdcreg[3] & 0x18)
{
case 0: /*Set*/
if (ega->writemask & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
break;
case 8: /*AND*/
if (ega->writemask & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld;
if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld;
break;
case 0x10: /*OR*/
if (ega->writemask & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld;
if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld;
break;
case 0x18: /*XOR*/
if (ega->writemask & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld;
if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld;
break;
}
// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
@ -688,10 +699,10 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
case 2:
if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1])
{
if (ega->writemask & 1) ega->vram[addr] = (((val & 1) ? 0xff : 0) & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
if (ega->writemask & 2) ega->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
if (ega->writemask & 4) ega->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
if (ega->writemask & 8) ega->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
if (writemask2 & 1) ega->vram[addr] = (((val & 1) ? 0xff : 0) & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
if (writemask2 & 2) ega->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
if (writemask2 & 4) ega->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
if (writemask2 & 8) ega->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
}
else
{
@ -702,28 +713,28 @@ void ega_write(uint32_t addr, uint8_t val, void *p)
switch (ega->gdcreg[3] & 0x18)
{
case 0: /*Set*/
if (ega->writemask & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
break;
case 8: /*AND*/
if (ega->writemask & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld;
if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld;
break;
case 0x10: /*OR*/
if (ega->writemask & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld;
if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld;
break;
case 0x18: /*XOR*/
if (ega->writemask & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la;
if (ega->writemask & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb;
if (ega->writemask & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc;
if (ega->writemask & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld;
if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la;
if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb;
if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc;
if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld;
break;
}
}
@ -735,13 +746,23 @@ uint8_t ega_read(uint32_t addr, void *p)
{
ega_t *ega = (ega_t *)p;
uint8_t temp, temp2, temp3, temp4;
int readplane = ega->readplane;
egareads++;
cycles -= video_timing_b;
cycles_lost += video_timing_b;
// pclog("Readega %06X ",addr);
if (addr >= 0xb0000) addr &= 0x7fff;
else addr &= 0xffff;
if (ega->chain2)
{
readplane = (readplane & 2) | (addr & 1);
addr &= ~1;
}
addr <<= 2;
ega->la = ega->vram[addr];
ega->lb = ega->vram[addr | 0x1];
ega->lc = ega->vram[addr | 0x2];
@ -762,7 +783,7 @@ uint8_t ega_read(uint32_t addr, void *p)
temp4 ^= (ega->colourcompare & 8) ? 0xff : 0;
return ~(temp | temp2 | temp3 | temp4);
}
return ega->vram[addr | ega->readplane];
return ega->vram[addr | readplane];
}
void ega_init(ega_t *ega)