From 12232fd7b89245637f269f7798632d756c34d4ba Mon Sep 17 00:00:00 2001 From: TomW Date: Wed, 12 Aug 2015 20:37:39 +0100 Subject: [PATCH] Implemented odd/even memory mode for EGA and VGA. --- src/vid_ega.c | 115 +++++++++++++++++++++++++----------------- src/vid_ega.h | 2 +- src/vid_svga.c | 21 +++++++- src/vid_svga.h | 2 +- src/vid_svga_render.c | 4 +- 5 files changed, 91 insertions(+), 53 deletions(-) diff --git a/src/vid_ega.c b/src/vid_ega.c index 706c357..d639429 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -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) diff --git a/src/vid_ega.h b/src/vid_ega.h index 47de8f4..fa227ae 100644 --- a/src/vid_ega.h +++ b/src/vid_ega.h @@ -23,7 +23,7 @@ typedef struct ega_t int fast; uint8_t colourcompare, colournocare; int readmode, writemode, readplane; - int chain4; + int chain4, chain2; uint8_t writemask; uint32_t charseta, charsetb; diff --git a/src/vid_svga.c b/src/vid_svga.c index 38fba90..f718253 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -162,6 +162,7 @@ void svga_out(uint16_t addr, uint8_t val, void *p) case 5: svga->writemode=val&3; svga->readmode=val&8; break; case 6: // pclog("svga_out recalcmapping %p\n", svga); + svga->chain2 = val & 2; if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { // pclog("Write mapping %02X\n", val); @@ -740,6 +741,14 @@ void svga_write(uint32_t addr, uint8_t val, void *p) writemask2=1<<(addr&3); addr&=~3; } + else if (svga->chain2) + { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else { addr<<=2; @@ -900,6 +909,7 @@ uint8_t svga_read(uint32_t addr, void *p) { svga_t *svga = (svga_t *)p; uint8_t temp, temp2, temp3, temp4; + int readplane = svga->readplane; cycles -= video_timing_b; cycles_lost += video_timing_b; @@ -918,7 +928,14 @@ uint8_t svga_read(uint32_t addr, void *p) return 0xff; return svga->vram[addr]; } - else addr<<=2; + else if (svga->chain2) + { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; + } + else + addr<<=2; addr &= 0x7fffff; @@ -946,7 +963,7 @@ uint8_t svga_read(uint32_t addr, void *p) return ~(temp | temp2 | temp3 | temp4); } //pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane); - return svga->vram[addr | svga->readplane]; + return svga->vram[addr | readplane]; } void svga_write_linear(uint32_t addr, uint8_t val, void *p) diff --git a/src/vid_svga.h b/src/vid_svga.h index 39afa4f..cd482c5 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -30,7 +30,7 @@ typedef struct svga_t int fast; uint8_t colourcompare, colournocare; int readmode, writemode, readplane; - int chain4; + int chain4, chain2; uint8_t writemask; uint32_t charseta, charsetb; diff --git a/src/vid_svga_render.c b/src/vid_svga_render.c index b653952..165b92d 100644 --- a/src/vid_svga_render.c +++ b/src/vid_svga_render.c @@ -52,7 +52,7 @@ void svga_render_text_40(svga_t *svga) { drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); chr = svga->vram[(svga->ma << 1) & svga->vrammask]; - attr = svga->vram[((svga->ma << 1) + 4) & svga->vrammask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vrammask]; if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); @@ -115,7 +115,7 @@ void svga_render_text_80(svga_t *svga) { drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); chr = svga->vram[(svga->ma << 1) & svga->vrammask]; - attr = svga->vram[((svga->ma << 1) + 4) & svga->vrammask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vrammask]; if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128);