Merge pull request #3217 from iamgreaser/gm/gh-2944-ega-64k-mvp
Gm/gh 2944 ega 64k mvp
This commit is contained in:
@@ -20,11 +20,11 @@
|
|||||||
break; \
|
break; \
|
||||||
\
|
\
|
||||||
case VAR_WORD_MODE_MA13: \
|
case VAR_WORD_MODE_MA13: \
|
||||||
out_addr = ((in_addr << 1) & 0x1fff8) | ((in_addr >> 13) & 0x4) | (in_addr & ~0x1ffff); \
|
out_addr = ((in_addr << 1) & 0x3fff8) | ((in_addr >> 13) & 0x4) | (in_addr & ~0x3ffff); \
|
||||||
break; \
|
break; \
|
||||||
\
|
\
|
||||||
case VAR_WORD_MODE_MA15: \
|
case VAR_WORD_MODE_MA15: \
|
||||||
out_addr = ((in_addr << 1) & 0x1fff8) | ((in_addr >> 15) & 0x4) | (in_addr & ~0x1ffff); \
|
out_addr = ((in_addr << 1) & 0x3fff8) | ((in_addr >> 15) & 0x4) | (in_addr & ~0x3ffff); \
|
||||||
break; \
|
break; \
|
||||||
\
|
\
|
||||||
case VAR_DWORD_MODE: \
|
case VAR_DWORD_MODE: \
|
||||||
@@ -85,7 +85,7 @@ ega_recalc_remap_func(ega_t *ega)
|
|||||||
func_nr = VAR_DWORD_MODE;
|
func_nr = VAR_DWORD_MODE;
|
||||||
else if (ega->crtc[0x17] & 0x40)
|
else if (ega->crtc[0x17] & 0x40)
|
||||||
func_nr = VAR_BYTE_MODE;
|
func_nr = VAR_BYTE_MODE;
|
||||||
else if (ega->crtc[0x17] & 0x20)
|
else if ((ega->crtc[0x17] & 0x20) && ega->vram_limit > 64*1024)
|
||||||
func_nr = VAR_WORD_MODE_MA15;
|
func_nr = VAR_WORD_MODE_MA15;
|
||||||
else
|
else
|
||||||
func_nr = VAR_WORD_MODE_MA13;
|
func_nr = VAR_WORD_MODE_MA13;
|
||||||
|
@@ -752,6 +752,73 @@ ega_doblit(int wx, int wy, ega_t *ega)
|
|||||||
ega->y_add >>= 1;
|
ega->y_add >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ega_remap_cpu_addr(uint32_t inaddr, ega_t *ega)
|
||||||
|
{
|
||||||
|
int a0mux;
|
||||||
|
uint32_t addr = inaddr;
|
||||||
|
|
||||||
|
// The CPU A0 line is multiplexed via a 3-to-8 mux.
|
||||||
|
// Input bits are:
|
||||||
|
// bit 0: 1 = 64K, 0 = 128K+ (from memory expansion connector)
|
||||||
|
// bit 1: 1 = Odd/Even mode, 0 = normal mode (from GC reg 6 bit 1)
|
||||||
|
// bit 2: 1 = 128K mapping, 0 = other mapping (from memory decode PROM)
|
||||||
|
a0mux = 0;
|
||||||
|
|
||||||
|
if (ega->gdcreg[6] & 2) {
|
||||||
|
a0mux |= 2;
|
||||||
|
}
|
||||||
|
if (ega->vram_limit <= 64*1024) {
|
||||||
|
a0mux |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((ega->gdcreg[6] & 0xC)) {
|
||||||
|
case 0x0: // 128K A000
|
||||||
|
addr &= 0xFFFF;
|
||||||
|
// TODO: Confirm the behaviour of this on actual hardware
|
||||||
|
a0mux |= 4;
|
||||||
|
break;
|
||||||
|
case 0x4: // 64K A000
|
||||||
|
addr &= 0xFFFF;
|
||||||
|
break;
|
||||||
|
case 0x8: // 32K B000
|
||||||
|
addr &= 0x7FFF;
|
||||||
|
break;
|
||||||
|
case 0xC: // 32K B800
|
||||||
|
addr &= 0x7FFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a0mux) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 7: // A0 becomes A0
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// A0 becomes the inversion of PGSEL (reg 0x3C2, miscout, bit 5)
|
||||||
|
// That is, 1 selects the "low" 64k, and 0 selects the "high" 64k.
|
||||||
|
addr &= ~1;
|
||||||
|
addr |= (~ega->miscout>>5)&1;
|
||||||
|
break;
|
||||||
|
case 3: // A0 becomes A14
|
||||||
|
addr &= ~1;
|
||||||
|
addr |= (inaddr>>14)&1;
|
||||||
|
break;
|
||||||
|
case 6: // A0 becomes A16
|
||||||
|
addr &= ~1;
|
||||||
|
addr |= (inaddr>>16)&1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In 64k mode, only select the first 16Kword/64KB bank
|
||||||
|
if (!(ega->seqregs[4] & 2)) {
|
||||||
|
addr &= 0x3FFF;
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ega_write(uint32_t addr, uint8_t val, void *p)
|
ega_write(uint32_t addr, uint8_t val, void *p)
|
||||||
{
|
{
|
||||||
@@ -761,21 +828,14 @@ ega_write(uint32_t addr, uint8_t val, void *p)
|
|||||||
|
|
||||||
cycles -= video_timing_write_b;
|
cycles -= video_timing_write_b;
|
||||||
|
|
||||||
if (addr >= 0xB0000)
|
|
||||||
addr &= 0x7fff;
|
|
||||||
else
|
|
||||||
addr &= 0xffff;
|
|
||||||
|
|
||||||
if (ega->chain2_write) {
|
if (ega->chain2_write) {
|
||||||
writemask2 &= ~0xa;
|
writemask2 &= ~0xa;
|
||||||
if (addr & 1)
|
if (addr & 1)
|
||||||
writemask2 <<= 1;
|
writemask2 <<= 1;
|
||||||
addr &= ~1;
|
|
||||||
if (addr & 0x4000)
|
|
||||||
addr |= 1;
|
|
||||||
addr &= ~0x4000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr = ega_remap_cpu_addr(addr, ega);
|
||||||
|
|
||||||
addr <<= 2;
|
addr <<= 2;
|
||||||
|
|
||||||
if (addr >= ega->vram_limit)
|
if (addr >= ega->vram_limit)
|
||||||
@@ -939,19 +999,13 @@ ega_read(uint32_t addr, void *p)
|
|||||||
int readplane = ega->readplane;
|
int readplane = ega->readplane;
|
||||||
|
|
||||||
cycles -= video_timing_read_b;
|
cycles -= video_timing_read_b;
|
||||||
if (addr >= 0xb0000)
|
|
||||||
addr &= 0x7fff;
|
|
||||||
else
|
|
||||||
addr &= 0xffff;
|
|
||||||
|
|
||||||
if (ega->chain2_read) {
|
if (ega->chain2_read) {
|
||||||
readplane = (readplane & 2) | (addr & 1);
|
readplane = (readplane & 2) | (addr & 1);
|
||||||
addr &= ~1;
|
|
||||||
if (addr & 0x4000)
|
|
||||||
addr |= 1;
|
|
||||||
addr &= ~0x4000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr = ega_remap_cpu_addr(addr, ega);
|
||||||
|
|
||||||
addr <<= 2;
|
addr <<= 2;
|
||||||
|
|
||||||
if (addr >= ega->vram_limit)
|
if (addr >= ega->vram_limit)
|
||||||
|
@@ -336,7 +336,7 @@ ega_render_2bpp_highres(ega_t *ega)
|
|||||||
void
|
void
|
||||||
ega_render_4bpp_lowres(ega_t *ega)
|
ega_render_4bpp_lowres(ega_t *ega)
|
||||||
{
|
{
|
||||||
int x, oddeven;
|
int x, secondcclk;
|
||||||
uint8_t dat, edat[4];
|
uint8_t dat, edat[4];
|
||||||
uint32_t addr, *p;
|
uint32_t addr, *p;
|
||||||
|
|
||||||
@@ -349,21 +349,25 @@ ega_render_4bpp_lowres(ega_t *ega)
|
|||||||
ega->firstline_draw = ega->displine;
|
ega->firstline_draw = ega->displine;
|
||||||
ega->lastline_draw = ega->displine;
|
ega->lastline_draw = ega->displine;
|
||||||
|
|
||||||
|
secondcclk = 0;
|
||||||
for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) {
|
for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) {
|
||||||
addr = ega->remap_func(ega, ega->ma);
|
addr = ega->remap_func(ega, ega->ma);
|
||||||
oddeven = 0;
|
addr &= ega->vrammask;
|
||||||
|
|
||||||
if (ega->seqregs[1] & 4) {
|
if (ega->seqregs[1] & 4) {
|
||||||
oddeven = (addr & 4) ? 1 : 0;
|
// FIXME: Verify the behaviour of planes 1,3 on actual hardware
|
||||||
edat[0] = ega->vram[addr | oddeven];
|
edat[0] = ega->vram[(addr | 0) ^ secondcclk];
|
||||||
edat[2] = ega->vram[addr | oddeven | 0x2];
|
edat[1] = ega->vram[(addr | 1) ^ secondcclk];
|
||||||
edat[1] = edat[3] = 0;
|
edat[2] = ega->vram[(addr | 2) ^ secondcclk];
|
||||||
ega->ma += 2;
|
edat[3] = ega->vram[(addr | 3) ^ secondcclk];
|
||||||
|
secondcclk = (secondcclk + 1) & 1;
|
||||||
|
if (secondcclk == 0)
|
||||||
|
ega->ma += 4;
|
||||||
} else {
|
} else {
|
||||||
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
|
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
|
||||||
ega->ma += 4;
|
ega->ma += 4;
|
||||||
}
|
}
|
||||||
ega->ma &= ega->vrammask;
|
ega->ma &= 0x3ffff;
|
||||||
|
|
||||||
if (ega->crtc[0x17] & 0x80) {
|
if (ega->crtc[0x17] & 0x80) {
|
||||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||||
@@ -388,7 +392,7 @@ ega_render_4bpp_lowres(ega_t *ega)
|
|||||||
void
|
void
|
||||||
ega_render_4bpp_highres(ega_t *ega)
|
ega_render_4bpp_highres(ega_t *ega)
|
||||||
{
|
{
|
||||||
int x, oddeven;
|
int x, secondcclk;
|
||||||
uint8_t dat, edat[4];
|
uint8_t dat, edat[4];
|
||||||
uint32_t addr, *p;
|
uint32_t addr, *p;
|
||||||
|
|
||||||
@@ -401,21 +405,24 @@ ega_render_4bpp_highres(ega_t *ega)
|
|||||||
ega->firstline_draw = ega->displine;
|
ega->firstline_draw = ega->displine;
|
||||||
ega->lastline_draw = ega->displine;
|
ega->lastline_draw = ega->displine;
|
||||||
|
|
||||||
|
secondcclk = 0;
|
||||||
for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) {
|
for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) {
|
||||||
addr = ega->remap_func(ega, ega->ma);
|
addr = ega->remap_func(ega, ega->ma);
|
||||||
oddeven = 0;
|
addr &= ega->vrammask;
|
||||||
|
|
||||||
if (ega->seqregs[1] & 4) {
|
if (ega->seqregs[1] & 4) {
|
||||||
oddeven = (addr & 4) ? 1 : 0;
|
// FIXME: Verify the behaviour of planes 1,3 on actual hardware
|
||||||
edat[0] = ega->vram[addr | oddeven];
|
edat[0] = ega->vram[(addr | 0) ^ secondcclk];
|
||||||
edat[2] = ega->vram[addr | oddeven | 0x2];
|
edat[1] = ega->vram[(addr | 1) ^ secondcclk];
|
||||||
edat[1] = edat[3] = 0;
|
edat[2] = ega->vram[(addr | 2) ^ secondcclk];
|
||||||
ega->ma += 2;
|
edat[3] = ega->vram[(addr | 3) ^ secondcclk];
|
||||||
|
secondcclk = (secondcclk + 1) & 1;
|
||||||
|
if (secondcclk == 0)
|
||||||
|
ega->ma += 4;
|
||||||
} else {
|
} else {
|
||||||
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
|
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
|
||||||
ega->ma += 4;
|
ega->ma += 4;
|
||||||
}
|
}
|
||||||
ega->ma &= ega->vrammask;
|
ega->ma &= 0x3ffff;
|
||||||
|
|
||||||
if (ega->crtc[0x17] & 0x80) {
|
if (ega->crtc[0x17] & 0x80) {
|
||||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||||
|
Reference in New Issue
Block a user