diff --git a/src/VIDEO/vid_ega.c b/src/VIDEO/vid_ega.c index 70201c18a..0920e3884 100644 --- a/src/VIDEO/vid_ega.c +++ b/src/VIDEO/vid_ega.c @@ -782,10 +782,16 @@ void ega_write(uint32_t addr, uint8_t val, void *p) if (addr & 1) writemask2 <<= 1; addr &= ~1; + if (addr & 0x4000) + addr |= 1; + addr &= ~0x4000; } addr <<= 2; + if (addr >= ega->vram_limit) + return; + if (!(ega->gdcreg[6] & 1)) fullchange = 2; @@ -909,10 +915,16 @@ uint8_t ega_read(uint32_t addr, void *p) { readplane = (readplane & 2) | (addr & 1); addr &= ~1; + if (addr & 0x4000) + addr |= 1; + addr &= ~0x4000; } addr <<= 2; + if (addr >= ega->vram_limit) + return 0xff; + ega->la = ega->vram[addr]; ega->lb = ega->vram[addr | 0x1]; ega->lc = ega->vram[addr | 0x2]; @@ -975,6 +987,10 @@ void ega_init(ega_t *ega) pallook16[c] = makecol32(0xaa, 0x55, 0); } ega->pallook = pallook16; + + ega->vram_limit = 256 * 1024; + ega->vrammask = ega->vram_limit-1; + old_overscan_color = 0; } @@ -1024,6 +1040,9 @@ void *ega_standalone_init() ega_common_defaults(ega); + ega->vram_limit = device_get_config_int("memory") * 1024; + ega->vrammask = ega->vram_limit-1; + mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); @@ -1060,6 +1079,9 @@ void *cpqega_standalone_init() ega_common_defaults(ega); + ega->vram_limit = device_get_config_int("memory") * 1024; + ega->vrammask = ega->vram_limit-1; + mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); @@ -1096,6 +1118,9 @@ void *sega_standalone_init() ega_common_defaults(ega); + ega->vram_limit = device_get_config_int("memory") * 1024; + ega->vrammask = ega->vram_limit-1; + mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); @@ -1238,6 +1263,30 @@ void ega_speed_changed(void *p) ega_recalctimings(ega); } +static device_config_t ega_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 256, + { + { + "64 kB", 64 + }, + { + "128 kB", 128 + }, + { + "256 kB", 256 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + device_t ega_device = { "EGA", @@ -1247,7 +1296,8 @@ device_t ega_device = ega_standalone_available, ega_speed_changed, NULL, - NULL + NULL, + ega_config }; device_t cpqega_device = @@ -1259,7 +1309,8 @@ device_t cpqega_device = cpqega_standalone_available, ega_speed_changed, NULL, - NULL + NULL, + ega_config }; device_t sega_device = @@ -1271,7 +1322,8 @@ device_t sega_device = sega_standalone_available, ega_speed_changed, NULL, - NULL + NULL, + ega_config }; device_t jega_device = @@ -1283,5 +1335,6 @@ device_t jega_device = sega_standalone_available, ega_speed_changed, NULL, - NULL + NULL, + ega_config }; diff --git a/src/VIDEO/vid_ega.h b/src/VIDEO/vid_ega.h index 90ddf17a4..e7b30b32b 100644 --- a/src/VIDEO/vid_ega.h +++ b/src/VIDEO/vid_ega.h @@ -87,6 +87,8 @@ typedef struct ega_t uint8_t *vram; int vrammask; + uint32_t vram_limit; + int video_res_x, video_res_y, video_bpp; uint8_t RMOD1, RMOD2, RDAGS, RDFFB, RDFSB, RDFAP, RPESL, RPULP, RPSSC, RPSSU, RPSSL; diff --git a/src/VIDEO/vid_ega_render.c b/src/VIDEO/vid_ega_render.c index eea08992b..66c3f2f65 100644 --- a/src/VIDEO/vid_ega_render.c +++ b/src/VIDEO/vid_ega_render.c @@ -66,85 +66,84 @@ void ega_render_blank(ega_t *ega) } void ega_render_text_standard(ega_t *ega, int drawcursor) -{ +{ + int x, xx; int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); - uint8_t chr, dat, attr; - uint32_t charaddr; - int x, xx; - uint32_t fg, bg; + + 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 charaddr; + + if (attr & 8) + charaddr = ega->charsetb + (chr * 128); + else + charaddr = ega->charseta + (chr * 128); - 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 (drawcursor) + { + bg = ega->pallook[ega->egapal[attr & 15]]; + fg = ega->pallook[ega->egapal[attr >> 4]]; + } + else + { + fg = ega->pallook[ega->egapal[attr & 15]]; + bg = ega->pallook[ega->egapal[attr >> 4]]; + if (attr & 0x80 && ega->attrregs[0x10] & 8) + { + bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; + if (ega->blink & 16) + fg = bg; + } + } - if (attr & 8) charaddr = ega->charsetb + (chr * 128); - else charaddr = ega->charseta + (chr * 128); - - if (drawcursor) - { - bg = ega->pallook[ega->egapal[attr & 15]]; - fg = ega->pallook[ega->egapal[attr >> 4]]; - } - else - { - fg = ega->pallook[ega->egapal[attr & 15]]; - bg = ega->pallook[ega->egapal[attr >> 4]]; - if (attr & 0x80 && ega->attrregs[0x10] & 8) - { - bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; - if (ega->blink & 16) - fg = bg; - } - } - - dat = ega->vram[charaddr + (ega->sc << 2)]; - if (ega->seqregs[1] & 8) - { - if (ega->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - ((uint32_t *)buffer32->line[dl])[(((x << 4) + 32 + (xx << 1)) & 2047) + x_add] = - ((uint32_t *)buffer32->line[dl])[(((x << 4) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - ((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + (xx << 1)) & 2047) + x_add] = - ((uint32_t *)buffer32->line[dl])[(((x * 18) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) - ((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] = - ((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = bg; - else - ((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] = - ((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = (dat & 1) ? fg : bg; - } - } - else - { - if (ega->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - ((uint32_t *)buffer32->line[dl])[(((x << 3) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - ((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) - ((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = bg; - else - ((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = (dat & 1) ? fg : bg; - } - } - ega->ma += 4; - ega->ma &= ega->vrammask; - } - } + dat = ega->vram[charaddr + (ega->sc << 2)]; + if (ega->seqregs[1] & 8) + { + if (ega->seqregs[1] & 1) + { + for (xx = 0; xx < 8; xx++) + ((uint32_t *)buffer32->line[dl])[((x << 4) + 32 + (xx << 1) + x_add) & 2047] = + ((uint32_t *)buffer32->line[dl])[((x << 4) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; + } + else + { + for (xx = 0; xx < 8; xx++) + ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + (xx << 1) + x_add) & 2047] = + ((uint32_t *)buffer32->line[dl])[((x * 18) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) + ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 16 + x_add) & 2047] = + ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 17 + x_add) & 2047] = bg; + else + ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 16 + x_add) & 2047] = + ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 17 + x_add) & 2047] = (dat & 1) ? fg : bg; + } + } + else + { + if (ega->seqregs[1] & 1) + { + for (xx = 0; xx < 8; xx++) + ((uint32_t *)buffer32->line[dl])[((x << 3) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; + } + else + { + for (xx = 0; xx < 8; xx++) + ((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) + ((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + 8 + x_add) & 2047] = bg; + else + ((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + 8 + x_add) & 2047] = (dat & 1) ? fg : bg; + } + } + ega->ma += 4; + ega->ma &= ega->vrammask; + } } static __inline int is_kanji1(uint8_t chr) @@ -381,24 +380,35 @@ void ega_render_2bpp_lowres(ega_t *ega) int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x; - int offset; - uint8_t edat[4]; + int offset = ((8 - ega->scrollcache) << 1) + 16; + + for (x = 0; x <= ega->hdisp; x++) + { + uint8_t edat[2]; + uint32_t addr = ega->ma; + + if (!(ega->crtc[0x17] & 0x40)) + { + addr = (addr << 1) & ega->vrammask; + 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); - offset = ((8 - ega->scrollcache) << 1) + 16; - for (x = 0; x <= ega->hdisp; x++) - { - if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) - { - edat[0] = ega->vram[(ega->ma << 1) + 0x8000]; - edat[1] = ega->vram[(ega->ma << 1) + 0x8001]; - } - else - { - edat[0] = ega->vram[(ega->ma << 1)]; - edat[1] = ega->vram[(ega->ma << 1) + 1]; - } - ega->ma += 4; - ega->ma &= ega->vrammask; + 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[dl])[(x << 4) + 14 + offset + x_add]= ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; @@ -416,24 +426,35 @@ void ega_render_2bpp_highres(ega_t *ega) int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x; - int offset; - uint8_t edat[4]; + int offset = ((8 - ega->scrollcache) << 1) + 16; + + for (x = 0; x <= ega->hdisp; x++) + { + uint8_t edat[2]; + uint32_t addr = ega->ma; + + if (!(ega->crtc[0x17] & 0x40)) + { + addr = (addr << 1) & ega->vrammask; + 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); - offset = ((8 - ega->scrollcache) << 1) + 16; - for (x = 0; x <= ega->hdisp; x++) - { - if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) - { - edat[0] = ega->vram[(ega->ma << 1) + 0x8000]; - edat[1] = ega->vram[(ega->ma << 1) + 0x8001]; - } - else - { - edat[0] = ega->vram[(ega->ma << 1)]; - edat[1] = ega->vram[(ega->ma << 1) + 1]; - } - ega->ma += 4; - ega->ma &= ega->vrammask; + 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[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; @@ -450,30 +471,49 @@ void ega_render_4bpp_lowres(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); - uint8_t dat; int x; - int offset; - uint8_t edat[4]; + 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 + { + edat[0] = ega->vram[addr]; + edat[1] = ega->vram[addr | 0x1]; + edat[2] = ega->vram[addr | 0x2]; + edat[3] = ega->vram[addr | 0x3]; + ega->ma += 4; + } + ega->ma &= ega->vrammask; - offset = ((8 - ega->scrollcache) << 1) + 16; - for (x = 0; x <= ega->hdisp; x++) - { - if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) - { - edat[0] = ega->vram[ega->ma | 0x8000]; - edat[1] = ega->vram[ega->ma | 0x8001]; - edat[2] = ega->vram[ega->ma | 0x8002]; - edat[3] = ega->vram[ega->ma | 0x8003]; - } - else - { - edat[0] = ega->vram[ega->ma]; - edat[1] = ega->vram[ega->ma | 0x1]; - edat[2] = ega->vram[ega->ma | 0x2]; - edat[3] = ega->vram[ega->ma | 0x3]; - } - ega->ma += 4; - ega->ma &= ega->vrammask; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; @@ -493,30 +533,48 @@ void ega_render_4bpp_highres(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); - uint8_t dat; int x; - int offset; - uint8_t edat[4]; + int offset = (8 - ega->scrollcache) + 24; + + for (x = 0; x <= ega->hdisp; x++) + { + uint8_t edat[4]; + uint8_t dat; + uint32_t addr = ega->ma; + int oddeven = 0; - offset = (8 - ega->scrollcache) + 24; - for (x = 0; x <= ega->hdisp; x++) - { - if (ega->sc & 1 && !(ega->crtc[0x17] & 1)) - { - edat[0] = ega->vram[ega->ma | 0x8000]; - edat[1] = ega->vram[ega->ma | 0x8001]; - edat[2] = ega->vram[ega->ma | 0x8002]; - edat[3] = ega->vram[ega->ma | 0x8003]; - } - else - { - edat[0] = ega->vram[ega->ma]; - edat[1] = ega->vram[ega->ma | 0x1]; - edat[2] = ega->vram[ega->ma | 0x2]; - edat[3] = ega->vram[ega->ma | 0x3]; - } - ega->ma += 4; - ega->ma &= ega->vrammask; + 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 + { + edat[0] = ega->vram[addr]; + edat[1] = ega->vram[addr | 0x1]; + edat[2] = ega->vram[addr | 0x2]; + edat[3] = ega->vram[addr | 0x3]; + ega->ma += 4; + } + ega->ma &= ega->vrammask; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];