diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index f5f3d2dd0..102d3ddca 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -8,7 +8,7 @@ * * Implementation of Socket 4 and 5 machines. * - * Version: @(#)m_at_socket4_5.c 1.0.0 2019/05/16 + * Version: @(#)m_at_socket4_5.c 1.0.1 2019/10/20 * * Authors: Sarah Walker, * Miran Grca, @@ -214,15 +214,16 @@ machine_at_endeavor_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + if (gfxcard == VID_INTERNAL) + device_add(&s3_phoenix_trio64_onboard_pci_device); + device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); device_add(&pc87306_device); device_add(&intel_flash_bxt_ami_device); - if (gfxcard == VID_INTERNAL) - device_add(&s3_phoenix_trio64_onboard_pci_device); - return ret; } diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index e9fa33fec..377a37bd5 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -8,7 +8,7 @@ * * Implementation of Socket 7 and Super Socket 7 machines. * - * Version: @(#)m_at_socket7_s7.c 1.0.0 2019/05/16 + * Version: @(#)m_at_socket7_s7.c 1.0.1 2019/10/20 * * Authors: Sarah Walker, * Miran Grca, @@ -121,13 +121,14 @@ machine_at_pb640_init(const machine_t *model) device_add(&i430fx_pb640_device); device_add(&piix_pb640_device); device_add(&ide_isa_2ch_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); if (gfxcard == VID_INTERNAL) device_add(&gd5440_onboard_pci_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + return ret; } @@ -158,7 +159,7 @@ machine_at_acerm3a_init(const machine_t *model) pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index a37f65033..a0c883c33 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -186,11 +186,11 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if ((ati28800->regs[0xb4] & 0x10) && (svga->crtcreg == 0x0a && svga->crtcreg == 0x0b)) + if ((ati28800->regs[0xb4] & 0x10) && ((svga->crtcreg == 0x0a) || (svga->crtcreg == 0x0b))) return; if ((ati28800->regs[0xb4] & 0x20) && ((svga->crtc[0x08] & 0x7f) && (svga->crtc[0x14] & 0x1f))) return; - if ((ati28800->regs[0xb4] & 0x40) && ((svga->crtcreg >= 0x00 && svga->crtcreg <= 0x06) && + if ((ati28800->regs[0xb4] & 0x40) && (((svga->crtcreg >= 0x00) && (svga->crtcreg <= 0x06)) && (svga->crtc[0x07] & 0x10) != 0x10)) return; diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 049572cd5..d8fe8b8ef 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -2790,26 +2790,22 @@ void mach64_hwcursor_draw(svga_t *svga, int displine) uint8_t dat; uint32_t col0 = ramdac->pallook[0]; uint32_t col1 = ramdac->pallook[1]; - int y_add, x_add; - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - offset = svga->hwcursor_latch.xoff; for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) { dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 32 + x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 32 + x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 33 + x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 33 + x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 34 + x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 34 + x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 35 + x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x + 35 + x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; dat >>= 2; offset += 4; } @@ -2968,7 +2964,7 @@ void mach64_overlay_draw(svga_t *svga, int displine) int graphics_key_fn = (mach64->overlay_key_cntl >> 4) & 5; int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf; - p = &buffer32->line[displine][32 + mach64->svga.overlay_latch.x]; + p = &buffer32->line[displine][svga->x_add + mach64->svga.overlay_latch.x]; if (mach64->scaler_update) { diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/vid_bt48x_ramdac.c index 9919d4fac..53dec87a6 100644 --- a/src/video/vid_bt48x_ramdac.c +++ b/src/video/vid_bt48x_ramdac.c @@ -336,7 +336,6 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) int x, xx, comb, b0, b1; uint16_t dat[2]; int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; - int y_add, x_add; int pitch, bppl, mode, x_pos, y_pos; uint32_t clr1, clr2, clr3, *p; uint8_t *cd; @@ -346,9 +345,6 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) clr2 = ramdac->extpallook[2]; clr3 = ramdac->extpallook[3]; - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - /* The planes come in two parts, and each plane is 1bpp, so a 32x32 cursor has 4 bytes per line, and a 64x64 cursor has 8 bytes per line. */ @@ -377,8 +373,8 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) b1 = (dat[1] >> (15 - xx)) & 1; comb = (b0 | (b1 << 1)); - y_pos = displine + y_add; - x_pos = offset + 32 + x_add; + y_pos = displine; + x_pos = offset + svga->x_add; p = buffer32->line[y_pos]; if (offset >= svga->dac_hwcursor_latch.x) { diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 135b47491..2cb05a1d2 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -443,31 +443,40 @@ cga_poll(void *p) ys_temp = (cga->lastline - cga->firstline) << 1; if ((xs_temp > 0) && (ys_temp > 0)) { - if (xsize < 64) xs_temp = 656; - if (ysize < 32) ys_temp = 400; + if (xs_temp < 64) xs_temp = 656; + if (ys_temp < 32) ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; - if ((cga->cgamode & 8) && x && (cga->lastline - cga->firstline) && - ((xs_temp != xsize) || (ys_temp != ysize) || - video_force_resize_get())) { + if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; - set_screen_size(xsize, ysize + 16); + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); if (video_force_resize_get()) video_force_resize_set(0); } - if (cga->composite) - video_blit_memtoscreen(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, + if (enable_overscan) { + if (cga->composite) + video_blit_memtoscreen(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, xsize, ((cga->lastline - cga->firstline) + 8) << 1); - else - video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, - xsize, ((cga->lastline - cga->firstline) + 8) << 1); + else + video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, + xsize, ((cga->lastline - cga->firstline) + 8) << 1); + } else { + if (cga->composite) + video_blit_memtoscreen(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + xsize, (cga->lastline - cga->firstline) << 1); + else + video_blit_memtoscreen_8(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + xsize, (cga->lastline - cga->firstline) << 1); + } } frames++; - video_res_x = xsize - 16; + video_res_x = xsize; video_res_y = ysize; if (cga->cgamode & 1) { video_res_x /= 8; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 23b923125..7ae3fd431 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -334,7 +334,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) if (val == 0x12) svga->seqregs[6] = 0x12; else - svga->seqregs[6] = 0x0f; + svga->seqregs[6] = (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) ? 0xff : 0x0f; if (svga->crtc[0x27] < CIRRUS_ID_CLGD5429) gd54xx->unlocked = (svga->seqregs[6] == 0x12); break; @@ -388,7 +388,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) else svga->hwcursor.xsize = 32; svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0; - // (svga->crtc[0x1b] & 2) + if ((svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256)); else @@ -668,7 +668,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) val = (svga->crtc[7] & ~0x10) | (val & 0x10); old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; - + if (old != val) { if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { svga->fullchange = changeframecount; @@ -687,67 +687,76 @@ gd54xx_in(uint16_t addr, void *p) gd54xx_t *gd54xx = (gd54xx_t *)p; svga_t *svga = &gd54xx->svga; - uint8_t index, temp; + uint8_t index, ret = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1)) + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { case 0x3c4: - if (gd54xx->unlocked) { - temp = svga->seqaddr; - if ((temp & 0x1e) == 0x10) { - if (temp & 1) - temp = ((svga->hwcursor.y & 7) << 5) | 0x11; + if (svga->seqregs[6] == 0x12) { + ret = svga->seqaddr; + if ((ret & 0x1e) == 0x10) { + if (ret & 1) + ret = ((svga->hwcursor.y & 7) << 5) | 0x11; else - temp = ((svga->hwcursor.x & 7) << 5) | 0x10; + ret = ((svga->hwcursor.x & 7) << 5) | 0x10; } - return temp; - } - return svga->seqaddr; + } else + ret = svga->seqaddr; + break; case 0x3c5: if ((svga->seqaddr == 2) && !gd54xx->unlocked) - return svga_in(addr, svga) & 0x0f; + ret = svga_in(addr, svga) & 0x0f; else if ((svga->seqaddr > 6) && !gd54xx->unlocked) - return 0xff; - - if (svga->seqaddr > 5) { + ret = 0xff; + else if (svga->seqaddr > 5) { + ret = svga->seqregs[svga->seqaddr & 0x3f]; switch (svga->seqaddr) { case 6: - return svga->seqregs[6]; + ret = svga->seqregs[6]; + break; case 0x0b: case 0x0c: case 0x0d: case 0x0e: - return gd54xx->vclk_n[svga->seqaddr-0x0b]; + ret = gd54xx->vclk_n[svga->seqaddr-0x0b]; + break; case 0x17: - temp = svga->gdcreg[0x17] & ~(7 << 3); + ret = svga->gdcreg[0x17] & ~(7 << 3); if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) { if (gd54xx->vlb) - temp |= (CL_GD5429_SYSTEM_BUS_VESA << 3); + ret |= (CL_GD5429_SYSTEM_BUS_VESA << 3); else - temp |= (CL_GD5429_SYSTEM_BUS_ISA << 3); + ret |= (CL_GD5429_SYSTEM_BUS_ISA << 3); } else { if (gd54xx->pci) - temp |= (CL_GD543X_SYSTEM_BUS_PCI << 3); + ret |= (CL_GD543X_SYSTEM_BUS_PCI << 3); else if (gd54xx->vlb) - temp |= (CL_GD543X_SYSTEM_BUS_VESA << 3); + ret |= (CL_GD543X_SYSTEM_BUS_VESA << 3); else - temp |= (CL_GD543X_SYSTEM_BUS_ISA << 3); + ret |= (CL_GD543X_SYSTEM_BUS_ISA << 3); } - return temp; + break; + case 0x18: + ret = svga->seqregs[0x18] & 0xfe; + break; case 0x1b: case 0x1c: case 0x1d: case 0x1e: - return gd54xx->vclk_d[svga->seqaddr-0x1b]; + ret = gd54xx->vclk_d[svga->seqaddr - 0x1b]; + break; } - return svga->seqregs[svga->seqaddr & 0x3f]; - } + break; + } else + ret = svga_in(addr, svga); break; case 0x3c6: if (!gd54xx->unlocked) - break; - if (gd54xx->ramdac.state == 4) { + ret = svga_in(addr, svga); + else if (gd54xx->ramdac.state == 4) { gd54xx->ramdac.state = 0; - return gd54xx->ramdac.ctrl; + ret = gd54xx->ramdac.ctrl; + } else { + gd54xx->ramdac.state++; + ret = svga_in(addr, svga); } - gd54xx->ramdac.state++; break; case 0x3c9: svga->dac_status = 3; @@ -758,170 +767,180 @@ gd54xx_in(uint16_t addr, void *p) case 0: svga->dac_pos++; if (svga->seqregs[0x12] & 2) - return gd54xx->extpal[index].r & 0x3f; + ret = gd54xx->extpal[index].r & 0x3f; else - return svga->vgapal[index].r & 0x3f; + ret = svga->vgapal[index].r & 0x3f; + break; case 1: svga->dac_pos++; if (svga->seqregs[0x12] & 2) - return gd54xx->extpal[index].g & 0x3f; + ret = gd54xx->extpal[index].g & 0x3f; else - return svga->vgapal[index].g & 0x3f; + ret = svga->vgapal[index].g & 0x3f; + break; case 2: svga->dac_pos=0; svga->dac_addr = (svga->dac_addr + 1) & 255; if (svga->seqregs[0x12] & 2) - return gd54xx->extpal[index].b & 0x3f; + ret = gd54xx->extpal[index].b & 0x3f; else - return svga->vgapal[index].b & 0x3f; + ret = svga->vgapal[index].b & 0x3f; + break; } - return 0xFF; + break; case 0x3ce: - return svga->gdcaddr & 0x3f; + ret = svga->gdcaddr & 0x3f; + break; case 0x3cf: if (svga->gdcaddr >= 0x10) { if ((svga->gdcaddr > 8) && !gd54xx->unlocked) - return 0xff; - if ((svga->gdcaddr > 0x1f) && ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5422) || - (svga->crtc[0x27] == CIRRUS_ID_CLGD5424))) - return 0xff; - switch (svga->gdcaddr) { + ret = 0xff; + else if ((svga->gdcaddr > 0x1f) && ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5422) || + (svga->crtc[0x27] == CIRRUS_ID_CLGD5424))) + ret = 0xff; + else switch (svga->gdcaddr) { case 0x10: - temp = gd543x_mmio_read(0xb8001, gd54xx); + ret = gd543x_mmio_read(0xb8001, gd54xx); break; case 0x11: - temp = gd543x_mmio_read(0xb8005, gd54xx); + ret = gd543x_mmio_read(0xb8005, gd54xx); break; case 0x12: - temp = gd543x_mmio_read(0xb8002, gd54xx); + ret = gd543x_mmio_read(0xb8002, gd54xx); break; case 0x13: - temp = gd543x_mmio_read(0xb8006, gd54xx); + ret = gd543x_mmio_read(0xb8006, gd54xx); break; case 0x14: - temp = gd543x_mmio_read(0xb8003, gd54xx); + ret = gd543x_mmio_read(0xb8003, gd54xx); break; case 0x15: - temp = gd543x_mmio_read(0xb8007, gd54xx); + ret = gd543x_mmio_read(0xb8007, gd54xx); break; case 0x20: - temp = gd543x_mmio_read(0xb8008, gd54xx); + ret = gd543x_mmio_read(0xb8008, gd54xx); break; case 0x21: - temp = gd543x_mmio_read(0xb8009, gd54xx); + ret = gd543x_mmio_read(0xb8009, gd54xx); break; case 0x22: - temp = gd543x_mmio_read(0xb800a, gd54xx); + ret = gd543x_mmio_read(0xb800a, gd54xx); break; case 0x23: - temp = gd543x_mmio_read(0xb800b, gd54xx); + ret = gd543x_mmio_read(0xb800b, gd54xx); break; case 0x24: - temp = gd543x_mmio_read(0xb800c, gd54xx); + ret = gd543x_mmio_read(0xb800c, gd54xx); break; case 0x25: - temp = gd543x_mmio_read(0xb800d, gd54xx); + ret = gd543x_mmio_read(0xb800d, gd54xx); break; case 0x26: - temp = gd543x_mmio_read(0xb800e, gd54xx); + ret = gd543x_mmio_read(0xb800e, gd54xx); break; case 0x27: - temp = gd543x_mmio_read(0xb800f, gd54xx); + ret = gd543x_mmio_read(0xb800f, gd54xx); break; case 0x28: - temp = gd543x_mmio_read(0xb8010, gd54xx); + ret = gd543x_mmio_read(0xb8010, gd54xx); break; case 0x29: - temp = gd543x_mmio_read(0xb8011, gd54xx); + ret = gd543x_mmio_read(0xb8011, gd54xx); break; case 0x2a: - temp = gd543x_mmio_read(0xb8012, gd54xx); + ret = gd543x_mmio_read(0xb8012, gd54xx); break; case 0x2c: - temp = gd543x_mmio_read(0xb8014, gd54xx); + ret = gd543x_mmio_read(0xb8014, gd54xx); break; case 0x2d: - temp = gd543x_mmio_read(0xb8015, gd54xx); + ret = gd543x_mmio_read(0xb8015, gd54xx); break; case 0x2e: - temp = gd543x_mmio_read(0xb8016, gd54xx); + ret = gd543x_mmio_read(0xb8016, gd54xx); break; case 0x2f: - temp = gd543x_mmio_read(0xb8017, gd54xx); + ret = gd543x_mmio_read(0xb8017, gd54xx); break; case 0x30: - temp = gd543x_mmio_read(0xb8018, gd54xx); + ret = gd543x_mmio_read(0xb8018, gd54xx); break; case 0x32: - temp = gd543x_mmio_read(0xb801a, gd54xx); + ret = gd543x_mmio_read(0xb801a, gd54xx); break; case 0x33: - temp = gd543x_mmio_read(0xb801b, gd54xx); + ret = gd543x_mmio_read(0xb801b, gd54xx); break; case 0x31: - temp = gd543x_mmio_read(0xb8040, gd54xx); + ret = gd543x_mmio_read(0xb8040, gd54xx); break; case 0x34: - temp = gd543x_mmio_read(0xb801c, gd54xx); + ret = gd543x_mmio_read(0xb801c, gd54xx); break; case 0x35: - temp = gd543x_mmio_read(0xb801d, gd54xx); + ret = gd543x_mmio_read(0xb801d, gd54xx); break; case 0x38: - temp = gd543x_mmio_read(0xb8020, gd54xx); + ret = gd543x_mmio_read(0xb8020, gd54xx); break; case 0x39: - temp = gd543x_mmio_read(0xb8021, gd54xx); - break; - - default: - temp = 0xff; + ret = gd543x_mmio_read(0xb8021, gd54xx); break; } } else { if ((svga->gdcaddr < 2) && !gd54xx->unlocked) - temp = (svga->gdcreg[svga->gdcaddr] & 0x0f); + ret = (svga->gdcreg[svga->gdcaddr] & 0x0f); else - temp = svga->gdcreg[svga->gdcaddr]; + ret = svga->gdcreg[svga->gdcaddr]; } - return temp; + break; case 0x3d4: - return svga->crtcreg; + ret = svga->crtcreg; + break; case 0x3d5: + ret = svga->crtc[svga->crtcreg]; if (((svga->crtcreg == 0x19) || (svga->crtcreg == 0x1a) || (svga->crtcreg == 0x1b) || (svga->crtcreg == 0x1d) || (svga->crtcreg == 0x25) || (svga->crtcreg == 0x27)) && !gd54xx->unlocked) - return 0xff; - switch (svga->crtcreg) { + ret = 0xff; + else switch (svga->crtcreg) { case 0x22: /*Graphis Data Latches Readback Register*/ /*Should this be & 7 if 8 byte latch is enabled? */ - return (svga->latch >> ((svga->gdcreg[4] & 3) << 3)) & 0xff; + ret = (svga->latch >> ((svga->gdcreg[4] & 3) << 3)) & 0xff; + break; case 0x24: /*Attribute controller toggle readback (R)*/ - return svga->attrff << 7; + ret = svga->attrff << 7; + break; case 0x26: /*Attribute controller index readback (R)*/ - return svga->attraddr & 0x3f; + ret = svga->attraddr & 0x3f; + break; case 0x27: /*ID*/ - return svga->crtc[0x27]; /*GD542x/GD543x*/ + ret = svga->crtc[0x27]; /*GD542x/GD543x*/ + break; case 0x28: /*Class ID*/ if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5430) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5440)) - return 0xff; /*Standard CL-GD5430/40*/ + ret = 0xff; /*Standard CL-GD5430/40*/ break; } - return svga->crtc[svga->crtcreg]; + break; + default: + ret = svga_in(addr, svga); + break; } - return svga_in(addr, svga); + + return ret; } @@ -1057,6 +1076,7 @@ gd54xx_recalctimings(svga_t *svga) svga->interlace = (svga->crtc[0x1a] & 0x01); + svga->map8 = svga->pallook; if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) svga->render = svga_render_8bpp_highres; else if (svga->gdcreg[5] & 0x40) @@ -1076,7 +1096,7 @@ gd54xx_recalctimings(svga_t *svga) switch (gd54xx->ramdac.ctrl & rdmask) { case 0: svga->bpp = 15; - if (gd54xx->ramdac.ctrl & 0x80) + if (gd54xx->ramdac.ctrl & 0x10) svga->render = svga_render_15bpp_mix_highres; else svga->render = svga_render_15bpp_highres; @@ -1101,51 +1121,19 @@ gd54xx_recalctimings(svga_t *svga) case 8: svga->bpp = 8; - svga->render = svga_render_8bpp_gs_highres; + svga->map8 = video_8togs; + svga->render = svga_render_8bpp_highres; break; case 9: svga->bpp = 8; - svga->render = svga_render_8bpp_rgb_highres; - break; - - case 0xf: - switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { - case CIRRUS_SR7_BPP_32: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { - svga->bpp = 32; - svga->render = svga_render_32bpp_highres; - svga->rowoffset *= 2; - } - break; - - case CIRRUS_SR7_BPP_24: - svga->bpp = 24; - svga->render = svga_render_24bpp_highres; - break; - - case CIRRUS_SR7_BPP_16: - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - } - break; - - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - break; - - case CIRRUS_SR7_BPP_8: - svga->bpp = 8; - svga->render = svga_render_8bpp_highres; - break; - } + svga->map8 = video_8to32; + svga->render = svga_render_8bpp_highres; break; } } else { svga->bpp = 15; - if (gd54xx->ramdac.ctrl & 0x80) + if (gd54xx->ramdac.ctrl & 0x10) svga->render = svga_render_15bpp_mix_highres; else svga->render = svga_render_15bpp_highres; @@ -1181,6 +1169,7 @@ gd54xx_recalctimings(svga_t *svga) svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; } + static void gd54xx_hwcursor_draw(svga_t *svga, int displine) { @@ -1188,14 +1177,10 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine) int x, xx, comb, b0, b1; uint8_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add, x_add; int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4; uint32_t bgcol = gd54xx->extpallook[0x00]; uint32_t fgcol = gd54xx->extpallook[0x0f]; - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += pitch; @@ -1216,16 +1201,16 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine) break; case 1: /* The pixel is shown in the cursor background color */ - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = bgcol; + ((uint32_t *)buffer32->line[displine])[offset + svga->x_add] = bgcol; break; case 2: /* The pixel is shown as the inverse of the original screen pixel (XOR cursor) */ - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; + ((uint32_t *)buffer32->line[displine])[offset + svga->x_add] ^= 0xffffff; break; case 3: /* The pixel is shown in the cursor foreground color */ - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = fgcol; + ((uint32_t *)buffer32->line[displine])[offset + svga->x_add] = fgcol; break; } } @@ -1401,7 +1386,7 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *p) static void gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr) { - uint32_t i; + uint32_t i, j; switch (svga->writemode) { case 4: @@ -1429,22 +1414,21 @@ gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr) addr <<= 2; for (i = 0; i < 8; i++) { - if (val & svga->seqregs[2] & (0x80 >> i)) { - svga->vram[addr + (i << 1)] = svga->gdcreg[1]; - svga->vram[addr + (i << 1) + 1] = svga->gdcreg[0x11]; - } else { - svga->vram[addr + (i << 1)] = svga->gdcreg[0]; - svga->vram[addr + (i << 1) + 1] = svga->gdcreg[0x10]; + j = (0x80 >> i); + if (svga->seqregs[2] & j) { + svga->vram[addr + (i << 1)] = (val & j) ? + svga->gdcreg[1] : svga->gdcreg[0]; + svga->vram[addr + (i << 1) + 1] = (val & j) ? + svga->gdcreg[0x11] : svga->gdcreg[0x10]; } } } else { addr <<= 1; for (i = 0; i < 8; i++) { - if (val & svga->seqregs[2] & (0x80 >> i)) - svga->vram[addr + i] = svga->gdcreg[1]; - else - svga->vram[addr + i] = svga->gdcreg[0]; + j = (0x80 >> i); + if (svga->seqregs[2] & j) + svga->vram[addr + i] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; } } break; @@ -3210,10 +3194,6 @@ gd54xx_close(void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; - FILE *f = fopen("d:\\queen\\86boxnew\\vram.dmp", "wb"); - fwrite(gd54xx->svga.vram, 1, gd54xx->vram_size, f); - fclose(f); - svga_close(&gd54xx->svga); free(gd54xx); diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 7458c7ad9..f17c526a1 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -1,3 +1,23 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Compaq CGA graphics cards. + * + * Version: @(#)vid_compaq_cga.c 1.0.0 2019/01/02 + * + * Authors: John Elliott, + * Sarah Walker, + * Miran Grca, + * + * Copyright 2016-2019 John Elliott. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + */ #include #include #include @@ -16,426 +36,444 @@ #include "vid_cga.h" #include "vid_cga_comp.h" + #define CGA_RGB 0 #define CGA_COMPOSITE 1 -static uint32_t vflags; + +static uint32_t vflags; +static uint8_t mdaattr[256][2][2]; + typedef struct compaq_cga_t { - cga_t cga; + cga_t cga; } compaq_cga_t; -static uint8_t mdaattr[256][2][2]; -void compaq_cga_recalctimings(compaq_cga_t *self) +#ifdef ENABLE_COMPAQ_CGA_LOG +int compaq_cga_do_log = ENABLE_COMPAQ_CGA_LOG; + + +static void +compaq_cga_log(const char *fmt, ...) { - double _dispontime, _dispofftime, disptime; - disptime = self->cga.crtc[0] + 1; - _dispontime = self->cga.crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - self->cga.dispontime = (uint64_t)(_dispontime); - self->cga.dispofftime = (uint64_t)(_dispofftime); + va_list ap; + + if (compaq_cga_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define compaq_cga_log(fmt, ...) +#endif + + +void +compaq_cga_recalctimings(compaq_cga_t *self) +{ + double _dispontime, _dispofftime, disptime; + disptime = self->cga.crtc[0] + 1; + + _dispontime = self->cga.crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + self->cga.dispontime = (uint64_t)(_dispontime); + self->cga.dispofftime = (uint64_t)(_dispofftime); } -void compaq_cga_poll(void *p) + +void +compaq_cga_poll(void *p) { - compaq_cga_t *self = (compaq_cga_t *)p; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint8_t border; - uint8_t cols[4]; - int oldsc; - int underline = 0; - int blink = 0; + compaq_cga_t *self = (compaq_cga_t *)p; + uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c, xs_temp, ys_temp; + int oldvc; + uint8_t chr, attr; + uint8_t border; + uint8_t cols[4]; + int oldsc; + int underline = 0; + int blink = 0; - /* If in graphics mode or character height is not 13, behave as CGA */ - if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) - { - overscan_x = overscan_y = 16; - cga_poll(&self->cga); - return; - } else - overscan_x = overscan_y = 0; + /* If in graphics mode or character height is not 13, behave as CGA */ + if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) { + overscan_x = overscan_y = 16; + cga_poll(&self->cga); + return; + } else + overscan_x = overscan_y = 0; -/* We are in Compaq 350-line CGA territory */ - if (!self->cga.linepos) - { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - oldsc = self->cga.sc; - if ((self->cga.crtc[8] & 3) == 3) - self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; - if (self->cga.cgadispon) - { - if (self->cga.displine < self->cga.firstline) - { - self->cga.firstline = self->cga.displine; - video_wait_for_buffer(); -// printf("Firstline %i\n",firstline); - } - self->cga.lastline = self->cga.displine; - - cols[0] = (self->cga.cgacol & 15) + 16; + /* We are in Compaq 350-line CGA territory */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + self->cga.linepos = 1; + oldsc = self->cga.sc; + if ((self->cga.crtc[8] & 3) == 3) + self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; + if (self->cga.cgadispon) { + if (self->cga.displine < self->cga.firstline) { + self->cga.firstline = self->cga.displine; + video_wait_for_buffer(); + compaq_cga_log("Firstline %i\n", firstline); + } + self->cga.lastline = self->cga.displine; - for (c = 0; c < 8; c++) - { - buffer32->line[self->cga.displine][c] = cols[0]; - if (self->cga.cgamode & 1) - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0]; - else - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0]; - } - if (self->cga.cgamode & 1) - { - for (x = 0; x < self->cga.crtc[1]; x++) - { - chr = self->cga.charbuffer[x << 1]; - attr = self->cga.charbuffer[(x << 1) + 1]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (vflags) { - underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - } - if (vflags && (self->cga.cgamode & 0x80)) - { - cols[0] = mdaattr[attr][blink][0]; - cols[1] = mdaattr[attr][blink][1]; - if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; - } - else if (self->cga.cgamode & 0x20) - { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if (vflags) { - if (blink) - cols[1] = cols[0]; - } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) - cols[1] = cols[0]; - } - } - else - { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (vflags && underline) - { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; - } - else if (drawcursor) - { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - else - { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - self->cga.ma++; - } - } - else - { - for (x = 0; x < self->cga.crtc[1]; x++) - { - chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)]; - attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (vflags) { - underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - } - if (vflags && (self->cga.cgamode & 0x80)) - { - cols[0] = mdaattr[attr][blink][0]; - cols[1] = mdaattr[attr][blink][1]; - if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; - } - else if (self->cga.cgamode & 0x20) - { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if (vflags) { - if (blink) - cols[1] = cols[0]; - } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) - cols[1] = cols[0]; - } - } - else - { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - self->cga.ma++; - if (vflags && underline) - { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] = - buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 9] = - mdaattr[attr][blink][1]; - } - else if (drawcursor) - { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] = - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - else - { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } - else - { - cols[0] = (self->cga.cgacol & 15) + 16; - if (self->cga.cgamode & 1) hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); - else hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); - } + cols[0] = (self->cga.cgacol & 15) + 16; - if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16; - else x = (self->cga.crtc[1] << 4) + 16; - - if (self->cga.composite) - { - if (self->cga.cgamode & 0x10) - border = 0x00; + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][c] = cols[0]; + if (self->cga.cgamode & 1) + buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0]; else - border = self->cga.cgacol & 0x0f; + buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0]; + } - if (vflags) - Composite_Process(self->cga.cgamode & 0x7F, border, x >> 2, buffer32->line[self->cga.displine]); - else - Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]); - } + if (self->cga.cgamode & 1) { + for (x = 0; x < self->cga.crtc[1]; x++) { + chr = self->cga.charbuffer[x << 1]; + attr = self->cga.charbuffer[(x << 1) + 1]; + drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - self->cga.sc = oldsc; - if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) - self->cga.cgastat |= 8; - self->cga.displine++; - if (self->cga.displine >= 500) - self->cga.displine = 0; - } - else - { - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - self->cga.linepos = 0; - if (self->cga.vsynctime) - { - self->cga.vsynctime--; - if (!self->cga.vsynctime) - self->cga.cgastat &= ~8; - } - if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) - { - self->cga.con = 0; - self->cga.coff = 1; - } - if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) - self->cga.maback = self->cga.ma; - if (self->cga.vadj) - { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - self->cga.vadj--; - if (!self->cga.vadj) - { - self->cga.cgadispon = 1; - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - self->cga.sc = 0; - } - } - else if (self->cga.sc == self->cga.crtc[9]) - { - self->cga.maback = self->cga.ma; - self->cga.sc = 0; - oldvc = self->cga.vc; - self->cga.vc++; - self->cga.vc &= 127; + if (vflags) { + underline = 0; + blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + } - if (self->cga.vc == self->cga.crtc[6]) - self->cga.cgadispon = 0; + if (vflags && (self->cga.cgamode & 0x80)) { + cols[0] = mdaattr[attr][blink][0]; + cols[1] = mdaattr[attr][blink][1]; - if (oldvc == self->cga.crtc[4]) - { - self->cga.vc = 0; - self->cga.vadj = self->cga.crtc[5]; - if (!self->cga.vadj) self->cga.cgadispon = 1; - if (!self->cga.vadj) self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - if ((self->cga.crtc[10] & 0x60) == 0x20) self->cga.cursoron = 0; - else self->cga.cursoron = self->cga.cgablink & 8; - } + if ((self->cga.sc == 12) && ((attr & 7) == 1)) + underline = 1; + } else if (self->cga.cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; - if (self->cga.vc == self->cga.crtc[7]) - { - self->cga.cgadispon = 0; - self->cga.displine = 0; - self->cga.vsynctime = 16; - if (self->cga.crtc[7]) - { -// printf("Lastline %i Firstline %i %i\n",self->cga.lastline,self->cga.firstline,self->cga.lastline-self->cga.firstline); + if (vflags) { + if (blink) + cols[1] = cols[0]; + } else { + if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) + cols[1] = cols[0]; + } + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } - if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3); - else x = (self->cga.crtc[1] << 4); - self->cga.lastline++; - if (x != xsize || (self->cga.lastline - self->cga.firstline) != ysize) - { - xsize = x; - ysize = self->cga.lastline - self->cga.firstline; -// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,self->cga.crtc[1]); + if (vflags && underline) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + self->cga.ma++; + } + } else { + for (x = 0; x < self->cga.crtc[1]; x++) { + chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)]; + attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)]; + drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - } - - if (self->cga.composite) - video_blit_memtoscreen(8, self->cga.firstline, 0, ysize, xsize, ysize); - else - video_blit_memtoscreen_8(8, self->cga.firstline, 0, ysize, xsize, ysize); - frames++; + if (vflags) { + underline = 0; + blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + } - video_res_x = xsize - 16; - video_res_y = ysize; - if (self->cga.cgamode & 1) - { - video_res_x /= 8; - video_res_y /= self->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(self->cga.cgamode & 2)) - { - video_res_x /= 16; - video_res_y /= self->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(self->cga.cgamode & 16)) - { - video_res_x /= 2; - video_bpp = 2; - } - else - { - video_bpp = 1; - } - } - self->cga.firstline = 1000; - self->cga.lastline = 0; - self->cga.cgablink++; - self->cga.oddeven ^= 1; - } - } - else - { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - } - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; - if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1)))) - self->cga.con = 1; - if (self->cga.cgadispon && (self->cga.cgamode & 1)) - { - for (x = 0; x < (self->cga.crtc[1] << 1); x++) - self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)]; - } - } + if (vflags && (self->cga.cgamode & 0x80)) { + cols[0] = mdaattr[attr][blink][0]; + cols[1] = mdaattr[attr][blink][1]; + if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; + } else if (self->cga.cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; -} + if (vflags) { + if (blink) + cols[1] = cols[0]; + } else { + if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) + cols[1] = cols[0]; + } + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + self->cga.ma++; -void *compaq_cga_init(const device_t *info) -{ - int display_type; - int c; - compaq_cga_t *self = malloc(sizeof(compaq_cga_t)); - memset(self, 0, sizeof(compaq_cga_t)); + if (vflags && underline) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] = + buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 9] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] = + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + } else { + cols[0] = (self->cga.cgacol & 15) + 16; - display_type = device_get_config_int("display_type"); - self->cga.composite = (display_type != CGA_RGB); - self->cga.revision = device_get_config_int("composite_type"); - self->cga.snow_enabled = device_get_config_int("snow_enabled"); - - self->cga.vram = malloc(0x4000); - - cga_comp_init(self->cga.revision); - timer_add(&self->cga.timer, compaq_cga_poll, self, 1); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); - io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); - - if (info->local) { - for (c = 0; c < 256; c++) { - mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16; - if (c & 8) mdaattr[c][0][1] = 15 + 16; - else mdaattr[c][0][1] = 7 + 16; - } - mdaattr[0x70][0][1] = 16; - mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15; - mdaattr[0xF0][0][1] = 16; - mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15; - mdaattr[0x78][0][1] = 16 + 7; - mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15; - mdaattr[0xF8][0][1] = 16 + 7; - mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15; - mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16; - mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16; - mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16; - mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16; + if (self->cga.cgamode & 1) hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); + else hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); } - vflags = info->local; + if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16; + else x = (self->cga.crtc[1] << 4) + 16; - overscan_x = overscan_y = 16; + if (self->cga.composite) { + if (self->cga.cgamode & 0x10) + border = 0x00; + else + border = self->cga.cgacol & 0x0f; - self->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (self->cga.rgb_type << 1); - cgapal_rebuild(); - - self->cga.crtc[9] = 13; - - return self; -} - -void compaq_cga_close(void *p) -{ - compaq_cga_t *self = (compaq_cga_t *)p; - - free(self->cga.vram); - free(self); -} - -void compaq_cga_speed_changed(void *p) -{ - compaq_cga_t *self = (compaq_cga_t *)p; - - if (self->cga.crtc[9] == 13) /* Character height */ - { - compaq_cga_recalctimings(self); + if (vflags) + Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]); + else + Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]); } - else - { - cga_recalctimings(&self->cga); - } + + self->cga.sc = oldsc; + if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) + self->cga.cgastat |= 8; + self->cga.displine++; + if (self->cga.displine >= 500) + self->cga.displine = 0; + } else { + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + self->cga.linepos = 0; + if (self->cga.vsynctime) { + self->cga.vsynctime--; + if (!self->cga.vsynctime) + self->cga.cgastat &= ~8; + } + + if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { + self->cga.con = 0; + self->cga.coff = 1; + } + if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) + self->cga.maback = self->cga.ma; + if (self->cga.vadj) { + self->cga.sc++; + self->cga.sc &= 31; + self->cga.ma = self->cga.maback; + self->cga.vadj--; + if (!self->cga.vadj) { + self->cga.cgadispon = 1; + self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + self->cga.sc = 0; + } + } else if (self->cga.sc == self->cga.crtc[9]) { + self->cga.maback = self->cga.ma; + self->cga.sc = 0; + oldvc = self->cga.vc; + self->cga.vc++; + self->cga.vc &= 127; + + if (self->cga.vc == self->cga.crtc[6]) + self->cga.cgadispon = 0; + + if (oldvc == self->cga.crtc[4]) { + self->cga.vc = 0; + self->cga.vadj = self->cga.crtc[5]; + + if (!self->cga.vadj) self->cga.cgadispon = 1; + + if (!self->cga.vadj) self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + + if ((self->cga.crtc[10] & 0x60) == 0x20) + self->cga.cursoron = 0; + else + self->cga.cursoron = self->cga.cgablink & 8; + } + + if (self->cga.vc == self->cga.crtc[7]) { + self->cga.cgadispon = 0; + self->cga.displine = 0; + self->cga.vsynctime = 16; + + if (self->cga.crtc[7]) { + compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline, + self->cga.firstline ,self->cga.lastline - self->cga.firstline); + + if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3); + else x = (self->cga.crtc[1] << 4); + + self->cga.lastline++; + + xs_temp = x; + ys_temp = (self->cga.lastline - self->cga.firstline); + + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xsize < 64) xs_temp = 656; + if (ysize < 32) ys_temp = 400; + if (!enable_overscan) + xsize -= 16; + + if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if (enable_overscan) { + if (self->cga.composite) + video_blit_memtoscreen(0, self->cga.firstline - 8, 0, ysize + 16, xsize + 16, ysize + 16); + else + video_blit_memtoscreen_8(0, self->cga.firstline - 8, 0, ysize + 16, xsize + 16, ysize + 16); + } else { + if (self->cga.composite) + video_blit_memtoscreen(8, self->cga.firstline, 0, ysize, xsize, ysize); + else + video_blit_memtoscreen_8(8, self->cga.firstline, 0, ysize, xsize, ysize); + } + } + + frames++; + + video_res_x = xsize; + if (enable_overscan) + xsize -= 16; + video_res_y = ysize; + if (self->cga.cgamode & 1) { + video_res_x /= 8; + video_res_y /= self->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(self->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= self->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(self->cga.cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else + video_bpp = 1; + } + + self->cga.firstline = 1000; + self->cga.lastline = 0; + self->cga.cgablink++; + self->cga.oddeven ^= 1; + } + } else { + self->cga.sc++; + self->cga.sc &= 31; + self->cga.ma = self->cga.maback; + } + + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; + + if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1)))) + self->cga.con = 1; + + if (self->cga.cgadispon && (self->cga.cgamode & 1)) { + for (x = 0; x < (self->cga.crtc[1] << 1); x++) + self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)]; + } + } } + +void * +compaq_cga_init(const device_t *info) +{ + int display_type; + int c; + compaq_cga_t *self = malloc(sizeof(compaq_cga_t)); + memset(self, 0, sizeof(compaq_cga_t)); + + display_type = device_get_config_int("display_type"); + self->cga.composite = (display_type != CGA_RGB); + self->cga.revision = device_get_config_int("composite_type"); + self->cga.snow_enabled = device_get_config_int("snow_enabled"); + + self->cga.vram = malloc(0x4000); + + cga_comp_init(self->cga.revision); + timer_add(&self->cga.timer, compaq_cga_poll, self, 1); + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); + io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); + + if (info->local) { + for (c = 0; c < 256; c++) { + mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16; + if (c & 8) mdaattr[c][0][1] = 15 + 16; + else mdaattr[c][0][1] = 7 + 16; + } + + mdaattr[0x70][0][1] = 16; + mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15; + mdaattr[0xF0][0][1] = 16; + mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15; + mdaattr[0x78][0][1] = 16 + 7; + mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15; + mdaattr[0xF8][0][1] = 16 + 7; + mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15; + mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16; + mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16; + mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16; + mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16; + } + + vflags = info->local; + + overscan_x = overscan_y = 16; + + self->cga.rgb_type = device_get_config_int("rgb_type"); + cga_palette = (self->cga.rgb_type << 1); + cgapal_rebuild(); + + self->cga.crtc[9] = 13; + + return self; +} + + +void +compaq_cga_close(void *p) +{ + compaq_cga_t *self = (compaq_cga_t *)p; + + free(self->cga.vram); + free(self); +} + + +void +compaq_cga_speed_changed(void *p) +{ + compaq_cga_t *self = (compaq_cga_t *)p; + + if (self->cga.crtc[9] == 13) /* Character height */ + compaq_cga_recalctimings(self); + else + cga_recalctimings(&self->cga); +} + + extern const device_config_t cga_config[]; const device_t compaq_cga_device = diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 3dd13df61..20fd9ac35 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -6,14 +6,13 @@ * * This file is part of the 86Box distribution. * - * Emulation of the EGA, Chips & Technologies SuperEGA, and - * AX JEGA graphics cards. + * Emulation of the EGA and Chips & Technologies SuperEGA + * graphics cards. * - * Version: @(#)vid_ega.c 1.0.21 2019/09/29 + * Version: @(#)vid_ega.c 1.0.22 2019/10/03 * * Authors: Sarah Walker, * Miran Grca, - * akm * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. @@ -36,1031 +35,970 @@ #include "vid_ega_render.h" +void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega); + + #define BIOS_IBM_PATH L"roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" #define BIOS_CPQ_PATH L"roms/video/ega/108281-001.bin" #define BIOS_SEGA_PATH L"roms/video/ega/lega.vbi" enum { - EGA_IBM = 0, - EGA_COMPAQ, - EGA_SUPEREGA + EGA_IBM = 0, + EGA_COMPAQ, + EGA_SUPEREGA }; -static video_timings_t timing_ega = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_ega = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static uint8_t ega_rotate[8][256]; +static uint32_t pallook16[256], pallook64[256]; +static int old_overscan_color = 0; -extern uint8_t edatlookup[4][4]; +extern uint8_t edatlookup[4][4]; -static uint8_t ega_rotate[8][256]; +/* 3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour): + 7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines). */ +int egaswitchread, egaswitches=9; +int update_overscan = 0; -static uint32_t pallook16[256], pallook64[256]; -/*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/ -int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/ - -static int old_overscan_color = 0; - -int update_overscan = 0; - -#ifdef JEGA -uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ -uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */ - -typedef struct { - char id[ID_LEN]; - char name[NAME_LEN]; - unsigned char width; - unsigned char height; - unsigned char type; -} fontx_h; - -typedef struct { - uint16_t start; - uint16_t end; -} fontxTbl; - -static __inline int ega_jega_enabled(ega_t *ega) +void +ega_out(uint16_t addr, uint8_t val, void *p) { - if (!ega->is_jega) - { - return 0; - } + ega_t *ega = (ega_t *)p; + int c; + uint8_t o, old; - return !(ega->RMOD1 & 0x40); -} + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) + addr ^= 0x60; -void ega_jega_write_font(ega_t *ega) -{ - unsigned int chr = ega->RDFFB; - unsigned int chr_2 = ega->RDFSB; - - ega->RSTAT &= ~0x02; - - /* Check if the character code is in the Wide character set of Shift-JIS */ - if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc))) - { - if (ega->font_index >= 32) - { - ega->font_index = 0; - } - chr <<= 8; - /* Fix vertical character position */ - chr |= chr_2; - if (ega->font_index < 16) - { - jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)] = ega->RDFAP; /* 16x16 font */ - } - else - { - jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1] = ega->RDFAP; /* 16x16 font */ - } - } - else - { - if (ega->font_index >= 19) - { - ega->font_index = 0; - } - jfont_sbcs_19[(chr * 19) + ega->font_index] = ega->RDFAP; /* 8x19 font */ - } - ega->font_index++; - ega->RSTAT |= 0x02; -} - -void ega_jega_read_font(ega_t *ega) -{ - unsigned int chr = ega->RDFFB; - unsigned int chr_2 = ega->RDFSB; - - ega->RSTAT &= ~0x02; - - /* Check if the character code is in the Wide character set of Shift-JIS */ - if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc))) - { - if (ega->font_index >= 32) - { - ega->font_index = 0; - } - chr <<= 8; - /* Fix vertical character position */ - chr |= chr_2; - if (ega->font_index < 16) - { - ega->RDFAP = jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)]; /* 16x16 font */ - } - else - { - ega->RDFAP = jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1]; /* 16x16 font */ - } - } - else - { - if (ega->font_index >= 19) - { - ega->font_index = 0; - } - ega->RDFAP = jfont_sbcs_19[(chr * 19) + ega->font_index]; /* 8x19 font */ - } - ega->font_index++; - ega->RSTAT |= 0x02; -} -#endif - - -void ega_out(uint16_t addr, uint8_t val, void *p) -{ - ega_t *ega = (ega_t *)p; - int c; - uint8_t o, old; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c0: - case 0x3c1: - if (!ega->attrff) - ega->attraddr = val & 31; - else - { - o = ega->attrregs[ega->attraddr & 31]; - ega->attrregs[ega->attraddr & 31] = val; - if (ega->attraddr < 16) - fullchange = changeframecount; - if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) - { - for (c = 0; c < 16; c++) - { - if (ega->attrregs[0x10] & 0x80) ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); - else ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); - } - } + switch (addr) { + case 0x3c0: case 0x3c1: + if (!ega->attrff) { + ega->attraddr = val & 31; + if ((val & 0x20) != ega->attr_palette_enable) { + fullchange = 3; + ega->attr_palette_enable = val & 0x20; + ega_recalctimings(ega); + } + } else { + o = ega->attrregs[ega->attraddr & 31]; + ega->attrregs[ega->attraddr & 31] = val; + if (ega->attraddr < 16) + fullchange = changeframecount; + if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) { + for (c = 0; c < 16; c++) { + if (ega->attrregs[0x10] & 0x80) ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); + else ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); + } + } /* Recalculate timings on change of attribute register 0x11 (overscan border color) too. */ - if ((ega->attraddr == 0x10) || (ega->attraddr == 0x11)) { + if (ega->attraddr == 0x10) { + if (o != val) + ega_recalctimings(ega); + } else if (ega->attraddr == 0x11) { ega->overscan_color = ega->vres ? pallook16[val & 0x0f] : pallook64[val & 0x3f]; if (o != val) ega_recalctimings(ega); } - } - ega->attrff ^= 1; - break; - case 0x3c2: - o = ega->miscout; - egaswitchread = (val & 0xc) >> 2; - ega->vres = !(val & 0x80); - ega->pallook = ega->vres ? pallook16 : pallook64; - ega->vidclock = val & 4; /*printf("3C2 write %02X\n",val);*/ - ega->miscout=val; - ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : pallook64[ega->attrregs[0x11] & 0x3f]; - if ((o ^ val) & 0x80) - ega_recalctimings(ega); - break; - case 0x3c4: - ega->seqaddr = val; - break; - case 0x3c5: - o = ega->seqregs[ega->seqaddr & 0xf]; - ega->seqregs[ega->seqaddr & 0xf] = val; - if (o != val && (ega->seqaddr & 0xf) == 1) - ega_recalctimings(ega); - switch (ega->seqaddr & 0xf) - { - case 1: - if (ega->scrblank && !(val & 0x20)) - fullchange = 3; - ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20); - break; - case 2: - ega->writemask = val & 0xf; - break; - case 3: - ega->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - ega->charseta = ((val & 3) * 0x10000) + 2; - break; - case 4: - ega->chain2_write = !(val & 4); - break; - } - break; - case 0x3ce: - ega->gdcaddr = val; - break; - case 0x3cf: - ega->gdcreg[ega->gdcaddr & 15] = val; - switch (ega->gdcaddr & 15) - { - case 2: - ega->colourcompare = val; - break; - case 4: - ega->readplane = val & 3; - break; - case 5: - ega->writemode = val & 3; - ega->readmode = val & 8; - ega->chain2_read = val & 0x10; - break; - case 6: - switch (val & 0xc) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000); - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000); - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000); - break; - } - break; - case 7: - ega->colournocare = val; - break; - } - break; - case 0x3d0: - case 0x3d4: - ega->crtcreg = val & 31; - return; - case 0x3d1: - case 0x3d5: - if (ega->crtcreg <= 7 && ega->crtc[0x11] & 0x80) return; - old = ega->crtc[ega->crtcreg]; - ega->crtc[ega->crtcreg] = val; - if (old != val) - { - if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) - { - fullchange = changeframecount; - ega_recalctimings(ega); - } - } - break; - } + } + ega->attrff ^= 1; + break; + case 0x3c2: + o = ega->miscout; + egaswitchread = (val & 0xc) >> 2; + ega->vres = !(val & 0x80); + ega->pallook = ega->vres ? pallook16 : pallook64; + ega->vidclock = val & 4; + ega->miscout = val; + ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : pallook64[ega->attrregs[0x11] & 0x3f]; + if ((o ^ val) & 0x80) + ega_recalctimings(ega); + break; + case 0x3c4: + ega->seqaddr = val; + break; + case 0x3c5: + o = ega->seqregs[ega->seqaddr & 0xf]; + ega->seqregs[ega->seqaddr & 0xf] = val; + if (o != val && (ega->seqaddr & 0xf) == 1) + ega_recalctimings(ega); + switch (ega->seqaddr & 0xf) { + case 1: + if (ega->scrblank && !(val & 0x20)) + fullchange = 3; + ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20); + break; + case 2: + ega->writemask = val & 0xf; + break; + case 3: + ega->charsetb = (((val >> 2) & 3) * 0x10000) + 2; + ega->charseta = ((val & 3) * 0x10000) + 2; + break; + case 4: + ega->chain2_write = !(val & 4); + break; + } + break; + case 0x3ce: + ega->gdcaddr = val; + break; + case 0x3cf: + ega->gdcreg[ega->gdcaddr & 15] = val; + switch (ega->gdcaddr & 15) { + case 2: + ega->colourcompare = val; + break; + case 4: + ega->readplane = val & 3; + break; + case 5: + ega->writemode = val & 3; + ega->readmode = val & 8; + ega->chain2_read = val & 0x10; + break; + case 6: + switch (val & 0xc) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000); + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000); + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000); + break; + } + break; + case 7: + ega->colournocare = val; + break; + } + break; + case 0x3d0: case 0x3d4: + ega->crtcreg = val & 31; + return; + case 0x3d1: case 0x3d5: + if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80)) + return; + if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80)) + val = (ega->crtc[7] & ~0x10) | (val & 0x10); + old = ega->crtc[ega->crtcreg]; + ega->crtc[ega->crtcreg] = val; + if (old != val) { + if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) { + fullchange = changeframecount; + ega_recalctimings(ega); + } + } + break; + } } uint8_t ega_in(uint16_t addr, void *p) { - ega_t *ega = (ega_t *)p; + ega_t *ega = (ega_t *)p; + uint8_t ret = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c0: - return ega->attraddr; - case 0x3c1: - return ega->attrregs[ega->attraddr]; - case 0x3c2: - return (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; - break; - case 0x3c4: - return ega->seqaddr; - case 0x3c5: - return ega->seqregs[ega->seqaddr & 0xf]; - case 0x3c8: - return 2; - case 0x3cc: - return ega->miscout; - case 0x3ce: - return ega->gdcaddr; - case 0x3cf: - return ega->gdcreg[ega->gdcaddr & 0xf]; - case 0x3d0: - case 0x3d4: - return ega->crtcreg; - case 0x3d1: - case 0x3d5: - return ega->crtc[ega->crtcreg]; - case 0x3da: - ega->attrff = 0; - ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ - return ega->stat; - } - return 0xff; + switch (addr) { + case 0x3c0: + ret = ega->attraddr | ega->attr_palette_enable; + break; + case 0x3c1: + ret = ega->attrregs[ega->attraddr]; + break; + case 0x3c2: + ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; + break; + case 0x3c4: + ret = ega->seqaddr; + break; + case 0x3c5: + ret = ega->seqregs[ega->seqaddr & 0xf]; + break; + case 0x3c8: + ret = 2; + break; + case 0x3cc: + ret = ega->miscout; + break; + case 0x3ce: + ret = ega->gdcaddr; + break; + case 0x3cf: + ret = ega->gdcreg[ega->gdcaddr & 0xf]; + break; + case 0x3d0: case 0x3d4: + ret = ega->crtcreg; + break; + case 0x3d1: + case 0x3d5: + ret = ega->crtc[ega->crtcreg]; + break; + case 0x3da: + ega->attrff = 0; + ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ + ret = ega->stat; + break; + } + + return ret; } -void ega_recalctimings(ega_t *ega) +void +ega_recalctimings(ega_t *ega) { - double _dispontime, _dispofftime, disptime; - double crtcconst; + double _dispontime, _dispofftime, disptime; + double crtcconst; - ega->vtotal = ega->crtc[6]; - ega->dispend = ega->crtc[0x12]; - ega->vsyncstart = ega->crtc[0x10]; - ega->split = ega->crtc[0x18]; + ega->vtotal = ega->crtc[6]; + ega->dispend = ega->crtc[0x12]; + ega->vsyncstart = ega->crtc[0x10]; + ega->split = ega->crtc[0x18]; - if (ega->crtc[7] & 1) ega->vtotal |= 0x100; - if (ega->crtc[7] & 32) ega->vtotal |= 0x200; - ega->vtotal += 2; + if (ega->crtc[7] & 1) ega->vtotal |= 0x100; + if (ega->crtc[7] & 32) ega->vtotal |= 0x200; + ega->vtotal += 2; - if (ega->crtc[7] & 2) ega->dispend |= 0x100; - if (ega->crtc[7] & 64) ega->dispend |= 0x200; - ega->dispend++; + if (ega->crtc[7] & 2) ega->dispend |= 0x100; + if (ega->crtc[7] & 64) ega->dispend |= 0x200; + ega->dispend++; - if (ega->crtc[7] & 4) ega->vsyncstart |= 0x100; - if (ega->crtc[7] & 128) ega->vsyncstart |= 0x200; - ega->vsyncstart++; + if (ega->crtc[7] & 4) ega->vsyncstart |= 0x100; + if (ega->crtc[7] & 128) ega->vsyncstart |= 0x200; + ega->vsyncstart++; - if (ega->crtc[7] & 0x10) ega->split |= 0x100; - if (ega->crtc[9] & 0x40) ega->split |= 0x200; - ega->split++; + if (ega->crtc[7] & 0x10) ega->split |= 0x100; + if (ega->crtc[9] & 0x40) ega->split |= 0x200; + ega->split++; - ega->hdisp = ega->crtc[1]; - ega->hdisp++; + ega->hdisp = ega->crtc[1]; + ega->hdisp++; - ega->rowoffset = ega->crtc[0x13]; - ega->rowcount = ega->crtc[9] & 0x1f; + ega->rowoffset = ega->crtc[0x13]; - if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); - else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); + ega->linedbl = ega->crtc[9] & 0x80; + ega->rowcount = ega->crtc[9] & 0x1f; - if (enable_overscan) { - overscan_y = (ega->rowcount + 1) << 1; + if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); + else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); - if (ega->seqregs[1] & 8) - overscan_y <<= 1; - if (overscan_y < 16) - overscan_y = 16; - } + ega->interlace = 0; - if (ega->seqregs[1] & 8) { - disptime = (double) ((ega->crtc[0] + 2) << 1); - _dispontime = (double) ((ega->crtc[1] + 1) << 1); - } else { - disptime = (double) (ega->crtc[0] + 2); - _dispontime = (double) (ega->crtc[1] + 1); + ega->ma_latch = (ega->crtc[0xc] << 8) | ega->crtc[0xd]; + + ega->render = ega_render_blank; + if (!ega->scrblank && ega->attr_palette_enable) { + if (!(ega->gdcreg[6] & 1)) { + if (ega->seqregs[1] & 8) { + ega->render = ega_render_text_40; + ega->hdisp *= (ega->seqregs[1] & 1) ? 16 : 18; + } else { + ega->render = ega_render_text_80; + ega->hdisp *= (ega->seqregs[1] & 1) ? 8 : 9; + } + ega->hdisp_old = ega->hdisp; + } else { + ega->hdisp *= (ega->seqregs[1] & 8) ? 16 : 8; + ega->hdisp_old = ega->hdisp; + + switch (ega->gdcreg[5] & 0x20) { + case 0x00: + if (ega->seqregs[1] & 8) + ega->render = ega_render_4bpp_lowres; + else + ega->render = ega_render_4bpp_highres; + break; + case 0x20: + ega->render = ega_render_2bpp; + break; + } } - _dispofftime = disptime - _dispontime; - _dispontime = _dispontime * crtcconst; - _dispofftime = _dispofftime * crtcconst; + } - ega->dispontime = (uint64_t)(_dispontime); - ega->dispofftime = (uint64_t)(_dispofftime); + if (enable_overscan) { + overscan_y = (ega->rowcount + 1) << 1; + + if (overscan_y < 16) + overscan_y = 16; + } + + overscan_x = (ega->seqregs[1] & 1) ? 16 : 18; + + if (ega->seqregs[1] & 8) + overscan_x <<= 1; + + ega->y_add = (overscan_y >> 1) - (ega->crtc[8] & 0x1f); + ega->x_add = (overscan_x >> 1); + + if (ega->seqregs[1] & 8) { + disptime = (double) ((ega->crtc[0] + 2) << 1); + _dispontime = (double) ((ega->crtc[1] + 1) << 1); + } else { + disptime = (double) (ega->crtc[0] + 2); + _dispontime = (double) (ega->crtc[1] + 1); + } + _dispofftime = disptime - _dispontime; + _dispontime = _dispontime * crtcconst; + _dispofftime = _dispofftime * crtcconst; + + ega->dispontime = (uint64_t)(_dispontime); + ega->dispofftime = (uint64_t)(_dispofftime); } -void ega_poll(void *p) +void +ega_poll(void *p) { - ega_t *ega = (ega_t *)p; - int x; - int xs_temp, ys_temp; - int drawcursor = 0; - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - int y_add_ex = enable_overscan ? overscan_y : 0; - int x_add_ex = enable_overscan ? 16 : 0; - uint32_t *q, i, j; - int wx = 640, wy = 350; + ega_t *ega = (ega_t *)p; + int x, old_ma; + int wx = 640, wy = 350; + uint32_t blink_delay; - if (!ega->linepos) - { - timer_advance_u64(&ega->timer, ega->dispofftime); + if (!ega->linepos) { + timer_advance_u64(&ega->timer, ega->dispofftime); + ega->stat |= 1; + ega->linepos = 1; - ega->stat |= 1; - ega->linepos = 1; + if (ega->dispon) { + ega->hdisp_on = 1; - if (ega->dispon) - { - if (ega->firstline == 2000) - { - ega->firstline = ega->displine; - video_wait_for_buffer(); - } + ega->ma &= ega->vrammask; + if (ega->firstline == 2000) { + ega->firstline = ega->displine; + video_wait_for_buffer(); + } - if (ega->scrblank) - { - ega_render_blank(ega); - } - else if (!(ega->gdcreg[6] & 1)) - { - if (fullchange) - { -#ifdef JEGA - if (ega_jega_enabled(ega)) - { - ega_render_text_jega(ega, drawcursor); - } - else - { - ega_render_text_standard(ega, drawcursor); - } -#else - ega_render_text_standard(ega, drawcursor); -#endif - } - } - else - { - switch (ega->gdcreg[5] & 0x20) - { - case 0x00: - if (ega->seqregs[1] & 8) - { - ega_render_4bpp_lowres(ega); - } - else - { - ega_render_4bpp_highres(ega); - } - break; - case 0x20: - ega_render_2bpp(ega); - break; - } - } - if (ega->lastline < ega->displine) - ega->lastline = ega->displine; - } + ega_render_overscan_left(ega); + if (ega->scrblank || fullchange) { + if (ega->firstline_draw == 2000) + ega->firstline_draw = ega->displine; + ega->lastline_draw = ega->displine; + if (ega->vres) { + old_ma = ega->ma; - ega->displine++; - if (ega->interlace) - ega->displine++; - if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) - ega->stat &= ~8; - ega->vslines++; - if (ega->displine > 500) - ega->displine = 0; - } - else - { - timer_advance_u64(&ega->timer, ega->dispontime); - if (ega->dispon) - ega->stat &= ~1; - ega->linepos = 0; - if (ega->sc == (ega->crtc[11] & 31)) - ega->con = 0; - if (ega->dispon) - { - if (ega->sc == (ega->crtc[9] & 31)) - { - ega->sc = 0; - if (ega->sc == (ega->crtc[11] & 31)) - ega->con = 0; + ega->displine <<= 1; + ega->y_add <<= 1; - ega->maback += (ega->rowoffset << 3); - if (ega->interlace) - ega->maback += (ega->rowoffset << 3); - ega->maback &= ega->vrammask; - ega->ma = ega->maback; - } - else - { - ega->sc++; - ega->sc &= 31; - ega->ma = ega->maback; - } - } - ega->vc++; - ega->vc &= 1023; - if (ega->vc == ega->split) - { - ega->ma = ega->maback = 0; - if (ega->attrregs[0x10] & 0x20) - ega->scrollcache = 0; - } - if (ega->vc == ega->dispend) - { - ega->dispon=0; - if (ega->crtc[10] & 0x20) ega->cursoron = 0; - else ega->cursoron = ega->blink & 16; - if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15)) - fullchange = 2; - ega->blink++; + ega->render(ega); + ega->displine++; - if (fullchange) - fullchange--; - } - if (ega->vc == ega->vsyncstart) - { - ega->dispon = 0; - ega->stat |= 8; - if (ega->seqregs[1] & 8) x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9) * 2; - else x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9); + ega->ma = old_ma; + ega->render(ega); - if (ega->interlace && !ega->oddeven) ega->lastline++; - if (ega->interlace && ega->oddeven) ega->firstline--; + ega->y_add >>= 1; + ega->displine >>= 1; + } else + ega->render(ega); + } + ega_render_overscan_right(ega); - xs_temp = x; - ys_temp = ega->lastline - ega->firstline + 1; + if (ega->lastline < ega->displine) + ega->lastline = ega->displine; + } - if ((xs_temp > 0) && (ys_temp > 1)) { - if (xs_temp < 64) - xs_temp = 640; - if (ys_temp < 32) - ys_temp = 200; + ega->displine++; + if (ega->interlace) + ega->displine++; + if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) + ega->stat &= ~8; + ega->vslines++; + if (ega->displine > 500) + ega->displine = 0; + } else { + timer_advance_u64(&ega->timer, ega->dispontime); - x_add = enable_overscan ? 8 : 0; - y_add = enable_overscan ? overscan_y : 0; - x_add_ex = enable_overscan ? 16 : 0; - y_add_ex = y_add << 1; + if (ega->dispon) + ega->stat &= ~1; + ega->hdisp_on = 0; - if ((xsize > 2032) || ((ysize + y_add_ex) > 2048)) { - x_add = x_add_ex = 0; - y_add = y_add_ex = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; + ega->linepos = 0; + if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount)) + ega->con = 0; + if (ega->dispon) { + if (ega->linedbl && !ega->linecountff) { + ega->linecountff = 1; + ega->ma = ega->maback; + } if (ega->sc == (ega->crtc[9] & 31)) { + ega->linecountff = 0; + ega->sc = 0; - if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { - xsize = xs_temp; - ysize = ys_temp; + ega->maback += (ega->rowoffset << 3); + if (ega->interlace) + ega->maback += (ega->rowoffset << 3); + ega->maback &= ega->vrammask; + ega->ma = ega->maback; + } else { + ega->linecountff = 0; + ega->sc++; + ega->sc &= 31; + ega->ma = ega->maback; + } + } + ega->vc++; + ega->vc &= 1023; + if (ega->vc == ega->split) { + ega->ma = ega->maback = 0; + ega->sc = 0; + if (ega->attrregs[0x10] & 0x20) + ega->scrollcache = 0; + } + if (ega->vc == ega->dispend) { + ega->dispon = 0; + blink_delay = (ega->crtc[11] & 0x60) >> 5; + if (ega->crtc[10] & 0x20) + ega->cursoron = 0; + else if (blink_delay == 2) + ega->cursoron = ((ega->blink % 96) >= 48); + else + ega->cursoron = ega->blink & (16 + (16 * blink_delay)); - if (ega->vres) - set_screen_size(xsize + x_add_ex, (ysize << 1) + y_add_ex); - else - set_screen_size(xsize + x_add_ex, ysize + y_add_ex); + if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15)) + fullchange = 2; + ega->blink = (ega->blink + 1) & 0x7f; - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (fullchange) + fullchange--; + } + if (ega->vc == ega->vsyncstart) { + ega->dispon = 0; + ega->stat |= 8; + x = ega->hdisp; - if (enable_overscan && !suppress_overscan) { - if ((x >= 160) && ((ega->lastline - ega->firstline + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top. */ - for (i = 0; i < y_add; i++) { - q = &buffer32->line[i & 0x7ff][32]; + if (ega->interlace && !ega->oddeven) + ega->lastline++; + if (ega->interlace && ega->oddeven) + ega->firstline--; - for (j = 0; j < (xsize + x_add_ex); j++) - q[j] = ega->overscan_color; - } + wx = x; - /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ - for (i = 0; i < y_add_ex; i++) { - q = &buffer32->line[(ysize + y_add + i) & 0x7ff][32]; + if (ega->vres) { + wy = (ega->lastline - ega->firstline) << 1; + ega_doblit(ega->firstline_draw << 1, (ega->lastline_draw + 1) << 1, wx, wy, ega); + } else { + wy = ega->lastline - ega->firstline; + ega_doblit(ega->firstline_draw, ega->lastline_draw + 1, wx, wy, ega); + } - for (j = 0; j < (xsize + x_add_ex); j++) - q[j] = ega->overscan_color; - } + frames++; - for (i = y_add_ex; i < (ysize + y_add); i ++) { - q = &buffer32->line[i & 0x7ff][32]; + ega->firstline = 2000; + ega->lastline = 0; - for (j = 0; j < x_add; j++) { - q[j] = ega->overscan_color; - q[xsize + x_add + j] = ega->overscan_color; - } - } - } - } + ega->firstline_draw = 2000; + ega->lastline_draw = 0; - video_blit_memtoscreen(32, 0, ega->firstline, ega->lastline + 1 + y_add_ex, xsize + x_add_ex, ega->lastline - ega->firstline + 1 + y_add_ex); + ega->oddeven ^= 1; + + changeframecount = ega->interlace ? 3 : 2; + ega->vslines = 0; + + if (ega->interlace && ega->oddeven) + ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1); + else + ega->ma = ega->maback = ega->ma_latch; + ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; + + ega->ma <<= 2; + ega->maback <<= 2; + ega->ca <<= 2; + } + if (ega->vc == ega->vtotal) { + ega->vc = 0; + ega->sc = 0; + ega->dispon = 1; + ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; + + ega->scrollcache = (ega->attrregs[0x13] & 0x0f); + if (!(ega->gdcreg[6] & 1) && !(ega->attrregs[0x10] & 1)) { /*Text mode*/ + if (ega->seqregs[1] & 1) + ega->scrollcache &= 0x07; + else { + ega->scrollcache++; + if (ega->scrollcache > 8) + ega->scrollcache = 0; } + } else + ega->scrollcache &= 0x07; - frames++; - - ega->video_res_x = wx; - ega->video_res_y = wy + 1; - if (!(ega->gdcreg[6] & 1)) /*Text mode*/ - { - ega->video_res_x /= (ega->seqregs[1] & 1) ? 8 : 9; - ega->video_res_y /= (ega->crtc[9] & 31) + 1; - ega->video_bpp = 0; - } - else - { - if (ega->crtc[9] & 0x80) - ega->video_res_y /= 2; - if (!(ega->crtc[0x17] & 1)) - ega->video_res_y *= 2; - ega->video_res_y /= (ega->crtc[9] & 31) + 1; - if (ega->seqregs[1] & 8) - ega->video_res_x /= 2; - ega->video_bpp = (ega->gdcreg[5] & 0x20) ? 2 : 4; - } + if (ega->seqregs[1] & 8) + ega->scrollcache <<= 1; - ega->firstline = 2000; - ega->lastline = 0; + ega->x_add = (overscan_x >> 1) - ega->scrollcache; - ega->maback = ega->ma = (ega->crtc[0xc] << 8)| ega->crtc[0xd]; - ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; - ega->ma <<= 2; - ega->maback <<= 2; - ega->ca <<= 2; - changeframecount = 2; - ega->vslines = 0; - } - if (ega->vc == ega->vtotal) - { - ega->vc = 0; - ega->sc = ega->crtc[8] & 0x1f; - ega->dispon = 1; - ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; - ega->scrollcache = ega->attrregs[0x13] & 7; - } - if (ega->sc == (ega->crtc[10] & 31)) - ega->con = 1; - } + ega->linecountff = 0; + } + if (ega->sc == (ega->crtc[10] & 31)) + ega->con = 1; + } } -void ega_write(uint32_t addr, uint8_t val, void *p) +void +ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) { - ega_t *ega = (ega_t *)p; - uint8_t vala, valb, valc, vald; - int writemask2 = ega->writemask; + int y_add = (enable_overscan) ? overscan_y : 0; + int x_add = (enable_overscan) ? overscan_x : 0; + int y_start = (enable_overscan) ? 0 : (overscan_y >> 1); + int x_start = (enable_overscan) ? 0 : (overscan_x >> 1); + int bottom = (overscan_y >> 1) + (ega->crtc[8] & 0x1f); + uint32_t *p; + int i, j; + int xs_temp, ys_temp; - egawrites++; - sub_cycles(video_timing_write_b); - - if (addr >= 0xB0000) addr &= 0x7fff; - else addr &= 0xffff; + if (ega->vres) { + y_add <<= 1; + y_start <<= 1; + bottom <<= 1; + } - if (ega->chain2_write) - { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - if (addr & 0x4000) - addr |= 1; - addr &= ~0x4000; - } + if ((wx <= 0) || (wy <= 0)) { + video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); + return; + } - addr <<= 2; + if (y1 > y2) { + video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add); + return; + } - if (addr >= ega->vram_limit) + if (ega->vres) + ega->y_add <<= 1; + + xs_temp = wx; + ys_temp = wy + 1; + if (ega->vres) + ys_temp++; + if (xs_temp < 64) + xs_temp = 640; + if (ys_temp < 32) + ys_temp = 200; + + if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { + /* Screen res has changed.. fix up, and let them know. */ + xsize = xs_temp; + ysize = ys_temp; + + if ((xsize > 1984) || (ysize > 2016)) { + /* 2048x2048 is the biggest safe render texture, to account for overscan, + we suppress overscan starting from x 1984 and y 2016. */ + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; + + set_screen_size(xsize + x_add, ysize + y_add); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if ((wx >= 160) && ((wy + 1) >= 120)) { + /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ + for (i = 0; i < ega->y_add; i++) { + p = &buffer32->line[i & 0x7ff][0]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = ega->overscan_color; + } + + for (i = 0; i < bottom; i++) { + p = &buffer32->line[(ysize + ega->y_add + i) & 0x7ff][0]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = ega->overscan_color; + } + } + + video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); + + if (ega->vres) + ega->y_add >>= 1; +} + + +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++; + sub_cycles(video_timing_write_b); + + if (addr >= 0xB0000) addr &= 0x7fff; + else addr &= 0xffff; + + if (ega->chain2_write) { + writemask2 &= ~0xa; + 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; + if (!(ega->gdcreg[6] & 1)) + fullchange = 2; - switch (ega->writemode) - { - case 1: - 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) - val = ega_rotate[ega->gdcreg[3] & 7][val]; - - if (ega->gdcreg[8] == 0xff && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) - { - 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 - { - if (ega->gdcreg[1] & 1) vala = (ega->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (ega->gdcreg[1] & 2) valb = (ega->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (ega->gdcreg[1] & 4) valc = (ega->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (ega->gdcreg[1] & 8) vald = (ega->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - switch (ega->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - 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 (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 (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 (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; - } - } - break; - case 2: - if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) - { - 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 - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (ega->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - 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 (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 (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 (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; - } - } - break; - } + switch (ega->writemode) { + case 1: + 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) + val = ega_rotate[ega->gdcreg[3] & 7][val]; + + if ((ega->gdcreg[8] == 0xff) && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) { + 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 { + if (ega->gdcreg[1] & 1) vala = (ega->gdcreg[0] & 1) ? 0xff : 0; + else vala = val; + if (ega->gdcreg[1] & 2) valb = (ega->gdcreg[0] & 2) ? 0xff : 0; + else valb = val; + if (ega->gdcreg[1] & 4) valc = (ega->gdcreg[0] & 4) ? 0xff : 0; + else valc = val; + if (ega->gdcreg[1] & 8) vald = (ega->gdcreg[0] & 8) ? 0xff : 0; + else vald = val; + switch (ega->gdcreg[3] & 0x18) { + case 0: /*Set*/ + 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 (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 (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 (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; + } + } + break; + case 2: + if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) { + 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 { + vala = ((val & 1) ? 0xff : 0); + valb = ((val & 2) ? 0xff : 0); + valc = ((val & 4) ? 0xff : 0); + vald = ((val & 8) ? 0xff : 0); + switch (ega->gdcreg[3] & 0x18) { + case 0: /*Set*/ + 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 (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 (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 (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; + } + } + break; + } } -uint8_t ega_read(uint32_t addr, void *p) +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++; - sub_cycles(video_timing_read_b); - if (addr >= 0xb0000) addr &= 0x7fff; - else addr &= 0xffff; + ega_t *ega = (ega_t *)p; + uint8_t temp, temp2, temp3, temp4; + int readplane = ega->readplane; - if (ega->chain2_read) - { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - if (addr & 0x4000) - addr |= 1; - addr &= ~0x4000; - } + egareads++; + sub_cycles(video_timing_read_b); + if (addr >= 0xb0000) addr &= 0x7fff; + else addr &= 0xffff; - addr <<= 2; + if (ega->chain2_read) { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + if (addr & 0x4000) + addr |= 1; + addr &= ~0x4000; + } - if (addr >= ega->vram_limit) - return 0xff; + addr <<= 2; - ega->la = ega->vram[addr]; - ega->lb = ega->vram[addr | 0x1]; - ega->lc = ega->vram[addr | 0x2]; - ega->ld = ega->vram[addr | 0x3]; - if (ega->readmode) - { - temp = ega->la; - temp ^= (ega->colourcompare & 1) ? 0xff : 0; - temp &= (ega->colournocare & 1) ? 0xff : 0; - temp2 = ega->lb; - temp2 ^= (ega->colourcompare & 2) ? 0xff : 0; - temp2 &= (ega->colournocare & 2) ? 0xff : 0; - temp3 = ega->lc; - temp3 ^= (ega->colourcompare & 4) ? 0xff : 0; - temp3 &= (ega->colournocare & 4) ? 0xff : 0; - temp4 = ega->ld; - temp4 ^= (ega->colourcompare & 8) ? 0xff : 0; - temp4 &= (ega->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } - return ega->vram[addr | readplane]; + if (addr >= ega->vram_limit) + return 0xff; + + ega->la = ega->vram[addr]; + ega->lb = ega->vram[addr | 0x1]; + ega->lc = ega->vram[addr | 0x2]; + ega->ld = ega->vram[addr | 0x3]; + if (ega->readmode) { + temp = ega->la; + temp ^= (ega->colourcompare & 1) ? 0xff : 0; + temp &= (ega->colournocare & 1) ? 0xff : 0; + temp2 = ega->lb; + temp2 ^= (ega->colourcompare & 2) ? 0xff : 0; + temp2 &= (ega->colournocare & 2) ? 0xff : 0; + temp3 = ega->lc; + temp3 ^= (ega->colourcompare & 4) ? 0xff : 0; + temp3 &= (ega->colournocare & 4) ? 0xff : 0; + temp4 = ega->ld; + temp4 ^= (ega->colourcompare & 8) ? 0xff : 0; + temp4 &= (ega->colournocare & 8) ? 0xff : 0; + return ~(temp | temp2 | temp3 | temp4); + } + return ega->vram[addr | readplane]; } -void ega_init(ega_t *ega, int monitor_type, int is_mono) +void +ega_init(ega_t *ega, int monitor_type, int is_mono) { - int c, d, e; - - ega->vram = malloc(0x40000); - ega->vrammask = 0x3ffff; - - for (c = 0; c < 256; c++) - { - e = c; - for (d = 0; d < 8; d++) - { - ega_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } + int c, d, e; - for (c = 0; c < 4; c++) - { - for (d = 0; d < 4; d++) - { - edatlookup[c][d] = 0; - if (c & 1) edatlookup[c][d] |= 1; - if (d & 1) edatlookup[c][d] |= 2; - if (c & 2) edatlookup[c][d] |= 0x10; - if (d & 2) edatlookup[c][d] |= 0x20; - } - } + ega->vram = malloc(0x40000); + ega->vrammask = 0x3ffff; - if (is_mono) - { - for (c = 0; c < 256; c++) - { - switch (monitor_type >> 4) - { - case DISPLAY_GREEN: - switch ((c >> 3) & 3) - { - case 0: - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20); - break; - case 1: - pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d); - break; - } - break; - case DISPLAY_AMBER: - switch ((c >> 3) & 3) - { - case 0: - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00); - break; - case 1: - pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34); - break; - } - break; - case DISPLAY_WHITE: default: - switch ((c >> 3) & 3) - { - case 0: - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83); - break; - case 1: - pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed); - break; - } - break; - } - } - } - else - { - for (c = 0; c < 256; c++) - { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); - pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); - if ((c & 0x17) == 6) - pallook16[c] = makecol32(0xaa, 0x55, 0); - } - } - ega->pallook = pallook16; - - egaswitches = monitor_type & 0xf; - - ega->vram_limit = 256 * 1024; - ega->vrammask = ega->vram_limit - 1; - - old_overscan_color = 0; - - ega->miscout |= 0x22; - ega->oddeven_page = 0; - - ega->seqregs[4] |= 2; - ega->extvram = 1; - - update_overscan = 0; - - ega->crtc[0] = 63; - ega->crtc[6] = 255; - -#ifdef JEGA - ega->is_jega = 0; -#endif - - timer_add(&ega->timer, ega_poll, ega, 1); -} - - -static void *ega_standalone_init(const device_t *info) -{ - ega_t *ega = malloc(sizeof(ega_t)); - int monitor_type; - - memset(ega, 0, sizeof(ega_t)); - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); - - overscan_x = 16; - overscan_y = 28; - - switch(info->local) { - case EGA_IBM: - default: - rom_init(&ega->bios_rom, BIOS_IBM_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_COMPAQ: - rom_init(&ega->bios_rom, BIOS_CPQ_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_SUPEREGA: - rom_init(&ega->bios_rom, BIOS_SEGA_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; + for (c = 0; c < 256; c++) { + e = c; + for (d = 0; d < 8; d++) { + ega_rotate[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); } + } - if (ega->bios_rom.rom[0x3ffe] == 0xaa && ega->bios_rom.rom[0x3fff] == 0x55) - { - int c; + for (c = 0; c < 4; c++) { + for (d = 0; d < 4; d++) { + edatlookup[c][d] = 0; + if (c & 1) edatlookup[c][d] |= 1; + if (d & 1) edatlookup[c][d] |= 2; + if (c & 2) edatlookup[c][d] |= 0x10; + if (d & 2) edatlookup[c][d] |= 0x20; + } + } - for (c = 0; c < 0x2000; c++) - { - uint8_t temp = ega->bios_rom.rom[c]; - ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c]; - ega->bios_rom.rom[0x3fff - c] = temp; - } - } + if (is_mono) { + for (c = 0; c < 256; c++) { + if (((c >> 3) & 3) == 0) + pallook64[c] = pallook16[c] = makecol32(0, 0, 0); + else switch (monitor_type >> 4) { + case DISPLAY_GREEN: + switch ((c >> 3) & 3) { + case 1: + pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c); + break; + case 2: + pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20); + break; + case 3: + pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d); + break; + } + break; + case DISPLAY_AMBER: + switch ((c >> 3) & 3) { + case 1: + pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00); + break; + case 2: + pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00); + break; + case 3: + pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34); + break; + } + break; + case DISPLAY_WHITE: default: + switch ((c >> 3) & 3) { + case 1: + pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0); + break; + case 2: + pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83); + break; + case 3: + pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed); + break; + } + break; + } + } + } else { + for (c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); + if ((c & 0x17) == 6) + pallook16[c] = makecol32(0xaa, 0x55, 0); + } + } - monitor_type = device_get_config_int("monitor_type"); - ega_init(ega, monitor_type, (monitor_type & 0x0F) == 0x0B); + ega->pallook = pallook16; - ega->vram_limit = device_get_config_int("memory") * 1024; - ega->vrammask = ega->vram_limit - 1; + egaswitches = monitor_type & 0xf; - mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); - io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - return ega; + ega->vram_limit = 256 * 1024; + ega->vrammask = ega->vram_limit - 1; + + old_overscan_color = 0; + + ega->miscout |= 0x22; + ega->oddeven_page = 0; + + ega->seqregs[4] |= 2; + ega->extvram = 1; + + update_overscan = 0; + + ega->crtc[0] = 63; + ega->crtc[6] = 255; + + timer_add(&ega->timer, ega_poll, ega, 1); } -static int ega_standalone_available(void) +static void * +ega_standalone_init(const device_t *info) { - return rom_present(BIOS_IBM_PATH); + ega_t *ega = malloc(sizeof(ega_t)); + int monitor_type, c; + + memset(ega, 0, sizeof(ega_t)); + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); + + overscan_x = 16; + overscan_y = 28; + ega->x_add = 8; + ega->y_add = 14; + + switch(info->local) { + case EGA_IBM: + default: + rom_init(&ega->bios_rom, BIOS_IBM_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_COMPAQ: + rom_init(&ega->bios_rom, BIOS_CPQ_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_SUPEREGA: + rom_init(&ega->bios_rom, BIOS_SEGA_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + } + + if ((ega->bios_rom.rom[0x3ffe] == 0xaa) && (ega->bios_rom.rom[0x3fff] == 0x55)) { + for (c = 0; c < 0x2000; c++) { + uint8_t temp = ega->bios_rom.rom[c]; + ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c]; + ega->bios_rom.rom[0x3fff - c] = temp; + } + } + + monitor_type = device_get_config_int("monitor_type"); + ega_init(ega, monitor_type, (monitor_type & 0x0F) == 0x0B); + + 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); + io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + + return ega; } -static int cpqega_standalone_available(void) +static int +ega_standalone_available(void) { - return rom_present(BIOS_CPQ_PATH); + return rom_present(BIOS_IBM_PATH); } -static int sega_standalone_available(void) +static int +cpqega_standalone_available(void) { - return rom_present(BIOS_SEGA_PATH); + return rom_present(BIOS_CPQ_PATH); } -static void ega_close(void *p) +static int +sega_standalone_available(void) { - ega_t *ega = (ega_t *)p; - - free(ega->vram); - free(ega); + return rom_present(BIOS_SEGA_PATH); } -static void ega_speed_changed(void *p) +static void +ega_close(void *p) { - ega_t *ega = (ega_t *)p; - - ega_recalctimings(ega); + ega_t *ega = (ega_t *)p; + + free(ega->vram); + free(ega); +} + + +static void +ega_speed_changed(void *p) +{ + ega_t *ega = (ega_t *)p; + + ega_recalctimings(ega); } @@ -1173,17 +1111,3 @@ const device_t sega_device = NULL, ega_config }; - -#ifdef JEGA -const device_t jega_device = -{ - "AX JEGA", - DEVICE_ISA, - EGA_SUPEREGA, - ega_standalone_init, ega_close, NULL, - sega_standalone_available, - ega_speed_changed, - NULL, - ega_config -}; -#endif diff --git a/src/video/vid_ega.h b/src/video/vid_ega.h index 30944c64a..841d86ced 100644 --- a/src/video/vid_ega.h +++ b/src/video/vid_ega.h @@ -6,33 +6,21 @@ * * This file is part of the 86Box distribution. * - * Emulation of the EGA, Chips & Technologies SuperEGA, and - * AX JEGA graphics cards. + * Emulation of the EGA and Chips & Technologies SuperEGA + * graphics cards. * - * Version: @(#)vid_ega.h 1.0.7 2018/03/18 + * Version: @(#)vid_ega.h 1.0.8 2019/10/03 * * Authors: Sarah Walker, * Miran Grca, - * akm, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 akm. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #ifndef VIDEO_EGA_H # define VIDEO_EGA_H -#ifdef JEGA -# define SBCS 0 -# define DBCS 1 -# define ID_LEN 6 -# define NAME_LEN 8 -# define SBCS19_LEN 256 * 19 -# define DBCS16_LEN 65536 * 32 -#endif - - #if defined(EMU_MEM_H) && defined(EMU_ROM_H) typedef struct ega_t { mem_mapping_t mapping; @@ -57,11 +45,11 @@ typedef struct ega_t { oddeven_page, oddeven_chain, vc, sc, dispon, hdisp_on, cursoron, blink, linepos, vslines, linecountff, oddeven, - lowres, interlace, lindebl, rowcount, + lowres, interlace, linedbl, lindebl, rowcount, vtotal, dispend, vsyncstart, split, - hdisp, htotal, hdisp_time, rowoffset, + hdisp, hdisp_old, htotal, hdisp_time, rowoffset, vblankstart, scrollcache, firstline, lastline, - firstline_draw, lastline_draw, + firstline_draw, lastline_draw, x_add, y_add, displine, video_res_x, video_res_y, video_bpp; uint32_t charseta, charsetb, ma_latch, ma, @@ -74,13 +62,7 @@ typedef struct ega_t { double clock; -#ifdef JEGA - uint8_t RMOD1, RMOD2, RDAGS, RDFFB, RDFSB, RDFAP, RPESL, RPULP, RPSSC, RPSSU, RPSSL; - uint8_t RPPAJ; - uint8_t RCMOD, RCCLH, RCCLL, RCCSL, RCCEL, RCSKW, ROMSL, RSTAT; - int is_jega, font_index; - int chr_left, chr_wide; -#endif + void (*render)(struct ega_t *svga); } ega_t; #endif @@ -90,10 +72,6 @@ extern const device_t ega_device; extern const device_t cpqega_device; extern const device_t sega_device; #endif -#ifdef JEGA -extern uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ -extern uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */ -#endif extern int update_overscan; diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index b80434521..46b0948ea 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -8,13 +8,13 @@ * * EGA renderers. * - * Version: @(#)vid_ega_render.c 1.0.5 2018/01/24 + * Version: @(#)vid_ega_render.c 1.0.6 2019/10/03 * * Author: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -30,522 +30,398 @@ #include "vid_ega_render.h" -int ega_display_line(ega_t *ega) +int +ega_display_line(ega_t *ega) { - int y_add = (enable_overscan) ? (overscan_y >> 1) : 0; - unsigned int dl = ega->displine; - if (ega->crtc[9] & 0x1f) - { - dl -= (ega->crtc[8] & 0x1f); + int y_add = (enable_overscan) ? (overscan_y >> 1) : 0; + unsigned int dl = ega->displine; + + if (ega->crtc[9] & 0x1f) + dl -= (ega->crtc[8] & 0x1f); + + dl += y_add; + dl &= 0x7ff; + return dl; +} + + +void +ega_render_blank(ega_t *ega) +{ + int x, xx; + + if ((ega->displine + ega->y_add) < 0) + return; + + for (x = 0; x < ega->hdisp; x++) { + switch (ega->seqregs[1] & 9) { + case 0: + for (xx = 0; xx < 9; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 9) + xx] = 0; + break; + case 1: + for (xx = 0; xx < 8; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 8) + xx] = 0; + break; + case 8: + for (xx = 0; xx < 18; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 18) + xx] = 0; + break; + case 9: + for (xx = 0; xx < 16; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 16) + xx] = 0; + break; } - dl += y_add; - dl &= 0x7ff; - return dl; + } } -void ega_render_blank(ega_t *ega) + +void +ega_render_overscan_left(ega_t *ega) { - int x_add = (enable_overscan) ? 8 : 0; - int dl = ega_display_line(ega); - int x, xx; + int i; - for (x = 0; x < ega->hdisp; x++) - { - switch (ega->seqregs[1] & 9) - { - case 0: - for (xx = 0; xx < 9; xx++) buffer32->line[dl][(x * 9) + xx + 32 + x_add] = 0; - break; - case 1: - for (xx = 0; xx < 8; xx++) buffer32->line[dl][(x * 8) + xx + 32 + x_add] = 0; - break; - case 8: - for (xx = 0; xx < 18; xx++) buffer32->line[dl][(x * 18) + xx + 32 + x_add] = 0; - break; - case 9: - for (xx = 0; xx < 16; xx++) buffer32->line[dl][(x * 16) + xx + 32 + x_add] = 0; - break; - } - } + if (ega->scrblank || (ega->hdisp == 0)) + return; + + for (i = 0; i < ega->x_add; i++) + buffer32->line[ega->displine + ega->y_add][i] = ega->overscan_color; } -void ega_render_text_standard(ega_t *ega, int drawcursor) + +void +ega_render_overscan_right(ega_t *ega) { - int x, xx; - int x_add = (enable_overscan) ? 8 : 0; - int dl = ega_display_line(ega); - - 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); + int i, right; - 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 (ega->scrblank || (ega->hdisp == 0)) + return; - dat = ega->vram[charaddr + (ega->sc << 2)]; - if (ega->seqregs[1] & 8) - { - if (ega->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - buffer32->line[dl][((x << 4) + 32 + (xx << 1) + x_add) & 2047] = - buffer32->line[dl][((x << 4) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - buffer32->line[dl][((x * 18) + 32 + (xx << 1) + x_add) & 2047] = - buffer32->line[dl][((x * 18) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) - buffer32->line[dl][((x * 18) + 32 + 16 + x_add) & 2047] = - buffer32->line[dl][((x * 18) + 32 + 17 + x_add) & 2047] = bg; - else - buffer32->line[dl][((x * 18) + 32 + 16 + x_add) & 2047] = - 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++) - buffer32->line[dl][((x << 3) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - buffer32->line[dl][((x * 9) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) - buffer32->line[dl][((x * 9) + 32 + 8 + x_add) & 2047] = bg; - else - buffer32->line[dl][((x * 9) + 32 + 8 + x_add) & 2047] = (dat & 1) ? fg : bg; - } - } - ega->ma += 4; - ega->ma &= ega->vrammask; - } + right = (overscan_x >> 1) + ega->scrollcache; + for (i = 0; i < right; i++) + buffer32->line[ega->displine + ega->y_add][ega->x_add + ega->hdisp + i] = ega->overscan_color; } -#ifdef JEGA -static __inline int is_kanji1(uint8_t chr) -{ - return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); -} -static __inline int is_kanji2(uint8_t chr) -{ - return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); -} - -void ega_jega_render_blit_text(ega_t *ega, int x, int dl, int start, int width, uint16_t dat, int cw, uint32_t fg, uint32_t bg) -{ - int x_add = (enable_overscan) ? 8 : 0; - - int xx = 0; - int xxx = 0; - - if (ega->seqregs[1] & 8) - { - for (xx = start; xx < (start + width); xx++) - for (xxx = 0; xxx < cw; xxx++) - buffer32->line[dl][(((x * width) + 32 + (xxx << 1) + ((xx << 1) * cw)) & 2047) + x_add] = - buffer32->line[dl][(((x * width) + 33 + (xxx << 1) + ((xx << 1) * cw)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = start; xx < (start + width); xx++) - buffer32->line[dl][(((x * width) + 32 + xxx + (xx * cw)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; - } -} - -void ega_render_text_jega(ega_t *ega, int drawcursor) +void +ega_render_text_40(ega_t *ega) { - int dl = ega_display_line(ega); - uint8_t chr, attr; - uint16_t dat = 0, dat2; - int x; - uint32_t fg = 0, bg = 0; + uint32_t *p; + int x, xx; + int drawcursor, xinc; + uint8_t chr, attr, dat; + uint32_t charaddr; + int fg, bg; - /* Temporary for DBCS. */ - unsigned int chr_left = 0; - unsigned int bsattr = 0; - int chr_wide = 0; - uint32_t bg_ex = 0; - uint32_t fg_ex = 0; + if ((ega->displine + ega->y_add) < 0) + return; - int blocks = ega->hdisp; - int fline; + if (ega->firstline_draw == 2000) + ega->firstline_draw = ega->displine; + ega->lastline_draw = ega->displine; - unsigned int pad_y, exattr; + if (fullchange) { + p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; + xinc = (ega->seqregs[1] & 1) ? 16 : 18; - 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]; + for (x = 0; x < ega->hdisp; x += xinc) { + 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 (chr_wide == 0) - { - if (ega->RMOD2 & 0x80) - { - fg_ex = ega->pallook[ega->egapal[attr & 15]]; + if (attr & 8) charaddr = ega->charsetb + (chr * 128); + else charaddr = ega->charseta + (chr * 128); - if (attr & 0x80 && ega->attrregs[0x10] & 8) - { - bg_ex = ega->pallook[ega->egapal[(attr >> 4) & 7]]; - } - else - { - bg_ex = ega->pallook[ega->egapal[attr >> 4]]; - } - } - else - { - if (attr & 0x40) - { - /* Reversed in JEGA mode */ - bg_ex = ega->pallook[ega->egapal[attr & 15]]; - fg_ex = ega->pallook[0]; - } - else - { - /* Reversed in JEGA mode */ - fg_ex = ega->pallook[ega->egapal[attr & 15]]; - bg_ex = ega->pallook[0]; - } - } + 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 (drawcursor) - { - bg = fg_ex; - fg = bg_ex; - } - else - { - fg = fg_ex; - bg = bg_ex; - } - - if (attr & 0x80 && ega->attrregs[0x10] & 8) - { - if (ega->blink & 16) - fg = bg; - } - - /* Stay drawing if the char code is DBCS and not at last column. */ - if (is_kanji1(dat) && (blocks > 1)) - { - /* Set the present char/attr code to the next loop. */ - chr_left = chr; - chr_wide = 1; - } - else - { - /* The char code is ANK (8 dots width). */ - dat = jfont_sbcs_19[chr*19+(ega->sc)]; /* w8xh19 font */ - ega_jega_render_blit_text(ega, x, dl, 0, 8, dat, 1, fg, bg); - if (bsattr & 0x20) - { - /* Vertical line. */ - dat = 0x18; - ega_jega_render_blit_text(ega, x, fline, 0, 8, dat, 1, fg, bg); - } - if (ega->sc == 18 && bsattr & 0x10) - { - /* Underline. */ - dat = 0xff; - ega_jega_render_blit_text(ega, x, fline, 0, 8, dat, 1, fg, bg); - } - chr_wide = 0; - blocks--; - } + if (attr & 0x80 && ega->attrregs[0x10] & 8) { + bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; + if (ega->blink & 16) + fg = bg; } - else - { - /* The char code may be in DBCS. */ - pad_y = ega->RPSSC; - exattr = 0; - - /* Note: The second column should be applied its basic attribute. */ - if (ega->RMOD2 & 0x40) - { - /* If JEGA Extended Attribute is enabled. */ - exattr = attr; - if ((exattr & 0x30) == 0x30) pad_y = ega->RPSSL; /* Set top padding of lower 2x character. */ - else if (exattr & 0x30) pad_y = ega->RPSSU; /* Set top padding of upper 2x character. */ - } - - if (ega->sc >= pad_y && ega->sc < 16 + pad_y) - { - /* Check the char code is in Wide charset of Shift-JIS. */ - if (is_kanji2(chr)) - { - fline = ega->sc - pad_y; - chr_left <<= 8; - /* Fix vertical position. */ - chr |= chr_left; - /* Horizontal wide font (Extended Attribute). */ - if (exattr & 0x20) - { - if (exattr & 0x10) fline = (fline >> 1) + 8; - else fline = fline >> 1; - } - /* Vertical wide font (Extended Attribute). */ - if (exattr & 0x40) - { - dat = jfont_dbcs_16[chr * 32 + fline * 2]; - if (!(exattr & 0x08)) - dat = jfont_dbcs_16[chr * 32 + fline * 2 + 1]; - /* Draw 8 dots. */ - ega_jega_render_blit_text(ega, x, dl, 0, 8, dat, 2, fg, bg); - } - else - { - /* Get the font pattern. */ - dat = jfont_dbcs_16[chr * 32 + fline * 2]; - dat <<= 8; - dat |= jfont_dbcs_16[chr * 32 + fline * 2 + 1]; - /* Bold (Extended Attribute). */ - if (exattr &= 0x80) - { - dat2 = dat; - dat2 >>= 1; - dat |= dat2; - /* Original JEGA colours the last row with the next column's attribute. */ - } - /* Draw 16 dots */ - ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); - } - } - else - { - /* Ignore wide char mode, put blank. */ - dat = 0; - ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); - } - } - else if (ega->sc == (17 + pad_y) && (bsattr & 0x10)) - { - /* Underline. */ - dat = 0xffff; - ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); - } - else - { - /* Draw blank */ - dat = 0; - ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); - } - - if (bsattr & 0x20) - { - /* Vertical line draw at last. */ - dat = 0x0180; - ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); - } - - chr_wide = 0; - blocks -= 2; /* Move by 2 columns. */ - } - - ega->ma += 4; - ega->ma &= ega->vrammask; } + + dat = ega->vram[charaddr + (ega->sc << 2)]; + if (ega->seqregs[1] & 1) { + for (xx = 0; xx < 16; xx += 2) + p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; + } else { + for (xx = 0; xx < 16; xx += 2) + p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; + if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) + p[16] = p[17] = bg; + else + p[16] = p[17] = (dat & 1) ? fg : bg; + } + ega->ma += 4; + p += xinc; } -} -#endif - -void ega_render_2bpp(ega_t *ega) -{ - int x; - int dl = ega_display_line(ega); - 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); - - 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; - - buffer32->line[dl][(x << 4) + 14 + offset] = buffer32->line[ega->displine][(x << 4) + 15 + offset] = ega->pallook[ega->egapal[edat[1] & 3]]; - buffer32->line[dl][(x << 4) + 12 + offset] = buffer32->line[ega->displine][(x << 4) + 13 + offset] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; - buffer32->line[dl][(x << 4) + 10 + offset] = buffer32->line[ega->displine][(x << 4) + 11 + offset] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]]; - buffer32->line[dl][(x << 4) + 8 + offset] = buffer32->line[ega->displine][(x << 4) + 9 + offset] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]]; - buffer32->line[dl][(x << 4) + 6 + offset] = buffer32->line[ega->displine][(x << 4) + 7 + offset] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]]; - buffer32->line[dl][(x << 4) + 4 + offset] = buffer32->line[ega->displine][(x << 4) + 5 + offset] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]]; - buffer32->line[dl][(x << 4) + 2 + offset] = buffer32->line[ega->displine][(x << 4) + 3 + offset] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]]; - buffer32->line[dl][(x << 4) + offset] = buffer32->line[ega->displine][(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]]; - } + ega->ma &= ega->vrammask; + } } -void ega_render_4bpp_lowres(ega_t *ega) + +void +ega_render_text_80(ega_t *ega) { - int x_add = (enable_overscan) ? 8 : 0; - int dl = ega_display_line(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); + uint32_t *p; + int x, xx; + int drawcursor, xinc; + uint8_t chr, attr, dat; + uint32_t charaddr; + int fg, bg; - 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; + if ((ega->displine + ega->y_add) < 0) + return; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - buffer32->line[dl][(x << 4) + 14 + offset + x_add] = buffer32->line[dl][(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 4) + 12 + offset + x_add] = buffer32->line[dl][(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - buffer32->line[dl][(x << 4) + 10 + offset + x_add] = buffer32->line[dl][(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 4) + 8 + offset + x_add] = buffer32->line[dl][(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - buffer32->line[dl][(x << 4) + 6 + offset + x_add] = buffer32->line[dl][(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 4) + 4 + offset + x_add] = buffer32->line[dl][(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - buffer32->line[dl][(x << 4) + 2 + offset + x_add] = buffer32->line[dl][(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 4) + offset + x_add] = buffer32->line[dl][(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + if (ega->firstline_draw == 2000) + ega->firstline_draw = ega->displine; + ega->lastline_draw = ega->displine; + + if (fullchange) { + p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; + xinc = (ega->seqregs[1] & 1) ? 8 : 9; + + for (x = 0; x < ega->hdisp; x += xinc) { + 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) { + 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] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1F) != 0xC0 || !(ega->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + ega->ma += 4; + p += xinc; } + ega->ma &= ega->vrammask; + } } -void ega_render_4bpp_highres(ega_t *ega) + +void +ega_render_2bpp(ega_t *ega) { - int x_add = (enable_overscan) ? 8 : 0; - int dl = ega_display_line(ega); - int x; - 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; + int x, dl = ega->displine + ega->y_add; + uint8_t edat[2]; + uint32_t addr; - 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->displine + ega->y_add) < 0) + return; - 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; + for (x = 0; x <= ega->hdisp; x++) { + addr = ega->ma; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - buffer32->line[dl][(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - buffer32->line[dl][(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - buffer32->line[dl][(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - buffer32->line[dl][(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; - buffer32->line[dl][(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + 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); + + 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; + + buffer32->line[dl][(x << 4) + 14 + ega->x_add] = + buffer32->line[dl][(x << 4) + 15 + ega->x_add] = ega->pallook[ega->egapal[edat[1] & 3]]; + buffer32->line[dl][(x << 4) + 12 + ega->x_add] = + buffer32->line[dl][(x << 4) + 13 + ega->x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; + buffer32->line[dl][(x << 4) + 10 + ega->x_add] = + buffer32->line[dl][(x << 4) + 11 + ega->x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]]; + buffer32->line[dl][(x << 4) + 8 + ega->x_add] = + buffer32->line[dl][(x << 4) + 9 + ega->x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]]; + buffer32->line[dl][(x << 4) + 6 + ega->x_add] = + buffer32->line[dl][(x << 4) + 7 + ega->x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]]; + buffer32->line[dl][(x << 4) + 4 + ega->x_add] = + buffer32->line[dl][(x << 4) + 5 + ega->x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]]; + buffer32->line[dl][(x << 4) + 2 + ega->x_add] = + buffer32->line[dl][(x << 4) + 3 + ega->x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]]; + buffer32->line[dl][(x << 4) + ega->x_add] = + buffer32->line[dl][(x << 4) + 1 + ega->x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]]; + } +} + + +void +ega_render_4bpp_lowres(ega_t *ega) +{ + int dl = ega->displine + ega->y_add; + int x, oddeven; + uint8_t dat, edat[4]; + uint32_t addr; + + if ((ega->displine + ega->y_add) < 0) + return; + + for (x = 0; x <= ega->hdisp; x++) { + addr = ega->ma; + 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; + + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + buffer32->line[dl][(x << 4) + 14 + ega->x_add] = + buffer32->line[dl][(x << 4) + 15 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 4) + 12 + ega->x_add] = + buffer32->line[dl][(x << 4) + 13 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + buffer32->line[dl][(x << 4) + 10 + ega->x_add] = + buffer32->line[dl][(x << 4) + 11 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 4) + 8 + ega->x_add] = + buffer32->line[dl][(x << 4) + 9 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + buffer32->line[dl][(x << 4) + 6 + ega->x_add] = + buffer32->line[dl][(x << 4) + 7 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 4) + 4 + ega->x_add] = + buffer32->line[dl][(x << 4) + 5 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + buffer32->line[dl][(x << 4) + 2 + ega->x_add] = + buffer32->line[dl][(x << 4) + 3 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 4) + ega->x_add] = + buffer32->line[dl][(x << 4) + 1 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + } +} + + +void +ega_render_4bpp_highres(ega_t *ega) +{ + int dl = ega->displine + ega->y_add; + int x, oddeven; + uint8_t dat, edat[4]; + uint32_t addr; + + if ((ega->displine + ega->y_add) < 0) + return; + + for (x = 0; x <= ega->hdisp; x++) { + addr = ega->ma; + 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; + + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + buffer32->line[dl][(x << 3) + 7 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 3) + 6 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + buffer32->line[dl][(x << 3) + 5 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 3) + 4 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + buffer32->line[dl][(x << 3) + 3 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 3) + 2 + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + buffer32->line[dl][(x << 3) + 1 + ega->x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; + buffer32->line[dl][(x << 3) + ega->x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; + } } diff --git a/src/video/vid_ega_render.h b/src/video/vid_ega_render.h index 57cb8313b..3a0c8f092 100644 --- a/src/video/vid_ega_render.h +++ b/src/video/vid_ega_render.h @@ -8,12 +8,12 @@ * * EGA renderers. * - * Version: @(#)vid_ega_render.h 1.0.2 2018/01/24 + * Version: @(#)vid_ega_render.h 1.0.3 2019/10/03 * * Author: Sarah Walker, * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ extern int firstline_draw, lastline_draw; @@ -28,10 +28,12 @@ extern int scrollcache; extern uint8_t edatlookup[4][4]; void ega_render_blank(ega_t *ega); -void ega_render_text_standard(ega_t *ega, int drawcursor); -#ifdef JEGA -void ega_render_text_jega(ega_t *ega, int drawcursor); -#endif + +void ega_render_overscan_left(ega_t *ega); +void ega_render_overscan_right(ega_t *ega); + +void ega_render_text_40(ega_t *ega); +void ega_render_text_80(ega_t *ega); void ega_render_2bpp(ega_t *ega); diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 2fcbd189c..66250d248 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -35,6 +35,7 @@ #include "../plat.h" #include "video.h" #include "vid_svga.h" +#include "vid_svga_render.h" #include "vid_icd2061.h" #include "vid_stg_ramdac.h" @@ -364,6 +365,66 @@ void et4000w32p_recalctimings(svga_t *svga) svga->hdisp /= 3; break; } + + svga->render = svga_render_blank; + if (!svga->scrblank && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) /*40 column*/ + svga->render = svga_render_text_40; + else + svga->render = svga_render_text_80; + } else { + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: /*256+ colours*/ + switch (svga->bpp) { + case 8: + svga->map8 = svga->pallook; + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; + case 15: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 24: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + } + break; + } + } + } } void et4000w32p_recalcmapping(et4000w32p_t *et4000) @@ -1075,26 +1136,22 @@ void et4000w32p_hwcursor_draw(svga_t *svga, int displine) { int x, offset; uint8_t dat; - int y_add, x_add; offset = svga->hwcursor_latch.xoff; - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) { dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 32] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 32] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 33 + x_add] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 33 + x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x + 1] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x + 1] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 34] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 34] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x + 2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x + 2] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 35] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine + y_add][svga->hwcursor_latch.x + x_add + x + 35] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x + 3] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x + 3] ^= 0xFFFFFF; dat >>= 2; offset += 4; } diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index ffc16776c..c7b19dcc9 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -406,7 +406,7 @@ ht216_hwcursor_draw(svga_t *svga, int displine) { int x; uint32_t dat[2]; - int offset = svga->hwcursor_latch.x + 32; + int offset = svga->hwcursor_latch.x + svga->x_add; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 4; @@ -1140,13 +1140,13 @@ ht216_force_redraw(void *p) static const device_config_t v7_vga_1024i_config[] = { { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, + "memory", "Memory size", CONFIG_SELECTION, "", 512, { { - "512 kB", 512 + "256 kB", 256 }, { - "1 MB", 1024 + "512 kB", 512 }, { "" @@ -1175,7 +1175,7 @@ const device_t v7_vga_1024i_device = { "Video 7 VGA 1024i", DEVICE_ISA, - 0x7010, + 0x7140, v7_vga_1024i_init, ht216_close, NULL, diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index fb2038768..b8fd1b868 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1069,12 +1069,8 @@ void s3_hwcursor_draw(svga_t *svga, int displine) uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add, x_add; uint32_t fg, bg; - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - switch (svga->bpp) { case 15: @@ -1118,9 +1114,9 @@ void s3_hwcursor_draw(svga_t *svga, int displine) if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) - buffer32->line[displine + y_add][offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) - buffer32->line[displine + y_add][offset + 32 + x_add] ^= 0xffffff; + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } offset++; @@ -1383,7 +1379,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x51: - if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805)) + if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); else s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); @@ -1391,7 +1387,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; - if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805)) + if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); else s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 65d8e3d1f..1e1bf4dad 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -3407,12 +3407,8 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add, x_add; uint32_t fg, bg; - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -3451,7 +3447,7 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) if (offset >= svga->hwcursor_latch.x) { if (dat[0] & 0x8000) - buffer32->line[displine + y_add][offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; } offset++; @@ -3467,9 +3463,9 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) - buffer32->line[displine + y_add][offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) - buffer32->line[displine + y_add][offset + 32 + x_add] ^= 0xffffff; + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } offset++; @@ -3720,10 +3716,8 @@ static void s3_virge_overlay_draw(svga_t *svga, int displine) int x; uint32_t *p; uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - int y_add = enable_overscan ? 16 : 0; - int x_add = enable_overscan ? 8 : 0; - p = &(buffer32->line[displine + y_add][offset + 32 + x_add]); + p = &(buffer32->line[displine][offset + svga->x_add]); if ((offset + virge->streams.sec_w) > virge->streams.pri_w) x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 104cb14a2..83d98802e 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -38,8 +38,6 @@ #include "vid_svga_render.h" -#define svga_output 0 - void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); extern int cyc_total; @@ -72,6 +70,23 @@ svga_set_override(svga_t *svga, int val) if (svga->override && !val) svga->fullchange = changeframecount; svga->override = val; + + if (!val) { + /* Override turned off, restore overscan X and Y per the CRTC. */ + if (enable_overscan) { + overscan_y = (svga->rowcount + 1) << 1; + + if (overscan_y < 16) + overscan_y = 16; + } + + overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; + + if (svga->seqregs[1] & 8) + overscan_x <<= 1; + } else + overscan_x = overscan_y = 16; + /* Override turned off, fix overcan X and Y to 16. */ } @@ -255,6 +270,8 @@ svga_out(uint16_t addr, uint8_t val, void *p) ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) svga_recalctimings(svga); break; + case 0x3d8: + break; } } @@ -470,6 +487,7 @@ svga_recalctimings(svga_t *svga) case 0x40: case 0x60: /*256+ colours*/ switch (svga->bpp) { case 8: + svga->map8 = svga->pallook; if (svga->lowres) svga->render = svga_render_8bpp_lowres; else @@ -509,14 +527,22 @@ svga_recalctimings(svga_t *svga) svga->rowcount = svga->crtc[9] & 31; if (enable_overscan) { overscan_y = (svga->rowcount + 1) << 1; - if (svga->seqregs[1] & 8) /*Low res (320)*/ - overscan_y <<= 1; + if (overscan_y < 16) overscan_y = 16; } + + overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; + + if (svga->seqregs[1] & 8) + overscan_x <<= 1; + if (svga->recalctimings_ex) svga->recalctimings_ex(svga); + svga->y_add = (overscan_y >> 1) - (svga->crtc[8] & 0x1f); + svga->x_add = (overscan_x >> 1); + if (svga->vblankstart < svga->dispend) svga->dispend = svga->vblankstart; @@ -546,7 +572,7 @@ void svga_poll(void *p) { svga_t *svga = (svga_t *)p; - uint32_t x; + uint32_t x, blink_delay; int wx, wy; if (!svga->linepos) { @@ -587,7 +613,7 @@ svga_poll(void *p) svga->linepos = 1; if (svga->dispon) { - svga->hdisp_on=1; + svga->hdisp_on = 1; svga->ma &= svga->vram_display_mask; if (svga->firstline == 2000) { @@ -600,12 +626,15 @@ svga_poll(void *p) svga->interlace ? 3 : 2; } - if (!svga->override) + if (!svga->override) { + svga_render_overscan_left(svga); svga->render(svga); + svga_render_overscan_right(svga); + } if (svga->overlay_on) { if (!svga->override && svga->overlay_draw) - svga->overlay_draw(svga, svga->displine); + svga->overlay_draw(svga, svga->displine + svga->y_add); svga->overlay_on--; if (svga->overlay_on && svga->interlace) svga->overlay_on--; @@ -613,7 +642,7 @@ svga_poll(void *p) if (svga->dac_hwcursor_on) { if (!svga->override && svga->dac_hwcursor_draw) - svga->dac_hwcursor_draw(svga, svga->displine); + svga->dac_hwcursor_draw(svga, svga->displine + svga->y_add); svga->dac_hwcursor_on--; if (svga->dac_hwcursor_on && svga->interlace) svga->dac_hwcursor_on--; @@ -621,7 +650,7 @@ svga_poll(void *p) if (svga->hwcursor_on) { if (!svga->override && svga->hwcursor_draw) - svga->hwcursor_draw(svga, svga->displine); + svga->hwcursor_draw(svga, svga->displine + svga->y_add); svga->hwcursor_on--; if (svga->hwcursor_on && svga->interlace) svga->hwcursor_on--; @@ -647,7 +676,7 @@ svga_poll(void *p) svga->hdisp_on = 0; svga->linepos = 0; - if (svga->sc == (svga->crtc[11] & 31)) + if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount)) svga->con = 0; if (svga->dispon) { if (svga->linedbl && !svga->linecountff) { @@ -681,15 +710,18 @@ svga_poll(void *p) if (svga->vc == svga->dispend) { if (svga->vblank_start) svga->vblank_start(svga); - svga->dispon=0; + svga->dispon = 0; + blink_delay = (svga->crtc[11] & 0x60) >> 5; if (svga->crtc[10] & 0x20) svga->cursoron = 0; + else if (blink_delay == 2) + svga->cursoron = ((svga->blink % 96) >= 48); else - svga->cursoron = svga->blink & 16; + svga->cursoron = svga->blink & (16 + (16 * blink_delay)); if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) svga->fullchange = 2; - svga->blink++; + svga->blink = (svga->blink + 1) & 0x7f; for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { if (svga->changedvram[x]) @@ -711,7 +743,7 @@ svga_poll(void *p) wx = x; wy = svga->lastline - svga->firstline; - if (!svga->override && (wx > 0) && (wy > 0)) + if (!svga->override/* && (wx > 0) && (wy > 0)*/) svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); svga->firstline = 2000; @@ -737,10 +769,30 @@ svga_poll(void *p) } if (svga->vc == svga->vtotal) { svga->vc = 0; - svga->sc = svga->crtc[8] & 0x1f; + svga->sc = 0; svga->dispon = 1; svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - svga->scrollcache = svga->attrregs[0x13] & 7; + + svga->scrollcache = (svga->attrregs[0x13] & 0x0f); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 1) + svga->scrollcache &= 0x07; + else { + svga->scrollcache++; + if (svga->scrollcache > 8) + svga->scrollcache = 0; + } + } else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) || + (svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres)) + svga->scrollcache &= 0x07; + else + svga->scrollcache = (svga->scrollcache & 0x06) >> 1; + + if (svga->seqregs[1] & 8) + svga->scrollcache <<= 1; + + svga->x_add = (overscan_x >> 1) - svga->scrollcache; + svga->linecountff = 0; svga->hwcursor_on = 0; @@ -784,6 +836,8 @@ svga_init(svga_t *svga, void *p, int memsize, overscan_x = 16; overscan_y = 32; + svga->x_add = 8; + svga->y_add = 16; svga->crtc[0] = 63; svga->crtc[6] = 255; @@ -818,6 +872,8 @@ svga_init(svga_t *svga, void *p, int memsize, svga->ramdac_type = RAMDAC_6BIT; + svga->map8 = svga->pallook; + return 0; } @@ -1150,7 +1206,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p) if (addr >= svga->vram_max) return 0xff; - addr &= svga->vram_mask; + addr &= svga->vram_mask; } if (!(svga->gdcreg[5] & 8)) { @@ -1204,21 +1260,24 @@ svga_read_linear(uint32_t addr, void *p) void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) { - int y_add = (enable_overscan) ? overscan_y : 0; - int x_add = (enable_overscan) ? 16 : 0; + int ox, y_add, x_add, y_start, x_start, bottom; uint32_t *p; int i, j; int xs_temp, ys_temp; - if ((xsize > 2032) || (ysize > 2032)) { - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; + y_add = (enable_overscan) ? overscan_y : 0; + x_add = (enable_overscan) ? overscan_x : 0; + y_start = (enable_overscan) ? 0 : (overscan_y >> 1); + x_start = (enable_overscan) ? 0 : (overscan_x >> 1); + bottom = (overscan_y >> 1) + (svga->crtc[8] & 0x1f); + + if ((wx <= 0) || (wy <= 0)) { + video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); + return; + } if (y1 > y2) { - video_blit_memtoscreen(32, 0, 0, 0, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add); return; } @@ -1234,42 +1293,39 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) xsize = xs_temp; ysize = ys_temp; - set_screen_size(xsize+x_add,ysize+y_add); + if ((xsize > 1984) || (ysize > 2016)) { + /* 2048x2048 is the biggest safe render texture, to account for overscan, + we suppress overscan starting from x 1984 and y 2016. */ + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; + + set_screen_size(xsize + x_add, ysize + y_add); if (video_force_resize_get()) video_force_resize_set(0); } - if (enable_overscan && !suppress_overscan) { - if ((wx >= 160) && ((wy + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &buffer32->line[i & 0x7ff][32]; + if ((wx >= 160) && ((wy + 1) >= 120)) { + /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ + for (i = 0; i < svga->y_add; i++) { + p = &buffer32->line[i & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga->overscan_color; - } + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } - /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &buffer32->line[(ysize + (y_add >> 1) + i) & 0x7ff][32]; + for (i = 0; i < bottom; i++) { + p = &buffer32->line[(ysize + svga->y_add + i) & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga->overscan_color; - } - - for (i = (y_add >> 1); i < (ysize + (y_add >> 1)); i ++) { - p = &buffer32->line[i & 0x7ff][32]; - - for (j = 0; j < 8; j++) { - p[j] = svga->overscan_color; - p[xsize + (x_add >> 1) + j] = svga->overscan_color; - } - } + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; } } - video_blit_memtoscreen(32, 0, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); } @@ -1414,6 +1470,7 @@ uint16_t svga_readw_common(uint32_t addr, uint8_t linear, void *p) { svga_t *svga = (svga_t *)p; + int memory_map_mode; if (!svga->fast) return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8); @@ -1422,8 +1479,14 @@ svga_readw_common(uint32_t addr, uint8_t linear, void *p) sub_cycles(video_timing_read_w); - if (!linear) - addr = (addr & svga->banked_mask) + svga->read_bank; + if (!linear) { + memory_map_mode = (svga->gdcreg[6] >> 2) & 3; + if ((memory_map_mode == 1) && (svga->adv_flags & FLAG_EXTRA_BANKS)) + addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; + else + addr = (addr & svga->banked_mask) + svga->write_bank; + } + addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xffff; @@ -1450,6 +1513,7 @@ uint32_t svga_readl_common(uint32_t addr, uint8_t linear, void *p) { svga_t *svga = (svga_t *)p; + int memory_map_mode; if (!svga->fast) { return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8) | @@ -1460,8 +1524,14 @@ svga_readl_common(uint32_t addr, uint8_t linear, void *p) sub_cycles(video_timing_read_l); - if (!linear) - addr = (addr & svga->banked_mask) + svga->read_bank; + if (!linear) { + memory_map_mode = (svga->gdcreg[6] >> 2) & 3; + if ((memory_map_mode == 1) && (svga->adv_flags & FLAG_EXTRA_BANKS)) + addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; + else + addr = (addr & svga->banked_mask) + svga->write_bank; + } + addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xffffffff; diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index 5bca424da..e47a3dc2e 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -48,7 +48,7 @@ typedef struct svga_t vc, sc, linepos, vslines, linecountff, oddeven, con, cursoron, blink, scrollcache, firstline, lastline, firstline_draw, lastline_draw, - displine, fullchange, + displine, fullchange, x_add, y_add, pan, vram_display_mask, vidclock, hwcursor_on, dac_hwcursor_on, overlay_on; @@ -70,7 +70,7 @@ typedef struct svga_t extra_banks[2], banked_mask, ca, overscan_color, - pallook[256]; + *map8, pallook[256]; PALETTE vgapal; diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 1350ae51a..4e02268d3 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -28,1050 +28,934 @@ #include "vid_svga_render.h" -void svga_render_blank(svga_t *svga) +void +svga_render_blank(svga_t *svga) { - int x, xx; - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; + int x, xx; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x < svga->hdisp; x++) - { - switch (svga->seqregs[1] & 9) - { - case 0: - for (xx = 0; xx < 9; xx++) buffer32->line[svga->displine + y_add][(x * 9) + xx + 32 + x_add] = 0; - break; - case 1: - for (xx = 0; xx < 8; xx++) buffer32->line[svga->displine + y_add][(x * 8) + xx + 32 + x_add] = 0; - break; - case 8: - for (xx = 0; xx < 18; xx++) buffer32->line[svga->displine + y_add][(x * 18) + xx + 32 + x_add] = 0; - break; - case 9: - for (xx = 0; xx < 16; xx++) buffer32->line[svga->displine + y_add][(x * 16) + xx + 32 + x_add] = 0; - break; - } - } + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x < svga->hdisp; x++) { + switch (svga->seqregs[1] & 9) { + case 0: + for (xx = 0; xx < 9; xx++) + buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 9) + xx] = 0x00000000; + break; + case 1: + for (xx = 0; xx < 8; xx++) + buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 8) + xx] = 0x00000000; + break; + case 8: + for (xx = 0; xx < 18; xx++) + buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 18) + xx] = 0x00000000; + break; + case 9: + for (xx = 0; xx < 16; xx++) + buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 16) + xx] = 0x00000000; + break; + } + } } -void svga_render_text_40(svga_t *svga) + +void +svga_render_overscan_left(svga_t *svga) +{ + int i; + + if (svga->scrblank || (svga->hdisp == 0)) + return; + + for (i = 0; i < svga->x_add; i++) + buffer32->line[svga->displine + svga->y_add][i] = svga->overscan_color; +} + + +void +svga_render_overscan_right(svga_t *svga) +{ + int i, right; + + if (svga->scrblank || (svga->hdisp == 0)) + return; + + right = (overscan_x >> 1) + svga->scrollcache; + for (i = 0; i < right; i++) + buffer32->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp + i] = svga->overscan_color; +} + + +void +svga_render_text_40(svga_t *svga) { - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; + uint32_t *p; + int x, xx; + int drawcursor, xinc; + uint8_t chr, attr, dat; + uint32_t charaddr; + int fg, bg; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + xinc = (svga->seqregs[1] & 1) ? 16 : 18; + + for (x = 0; x < svga->hdisp; x += xinc) { + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + + if (attr & 8) charaddr = svga->charsetb + (chr * 128); + else charaddr = svga->charseta + (chr * 128); + + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + dat = svga->vram[charaddr + (svga->sc << 2)]; + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 16; xx += 2) + p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; + } else { + for (xx = 0; xx < 16; xx += 2) + p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; + if ((chr & ~0x1f) != 0xc0 || !(svga->attrregs[0x10] & 4)) + p[16] = p[17] = bg; + else + p[16] = p[17] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; + } + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_text_80(svga_t *svga) +{ + uint32_t *p; + int x, xx; + int drawcursor, xinc; + uint8_t chr, attr, dat; + uint32_t charaddr; + int fg, bg; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + xinc = (svga->seqregs[1] & 1) ? 8 : 9; + + for (x = 0; x < svga->hdisp; x += xinc) { + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + + if (attr & 8) charaddr = svga->charsetb + (chr * 128); + else charaddr = svga->charseta + (chr * 128); + + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + dat = svga->vram[charaddr + (svga->sc << 2)]; + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; + } + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_text_80_ksc5601(svga_t *svga) +{ + uint32_t *p; + int x, xx; + int drawcursor, xinc; + uint8_t chr, attr, dat, nextchr; + uint32_t charaddr; + int fg, bg; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + xinc = (svga->seqregs[1] & 1) ? 8 : 9; + + for (x = 0; x < svga->hdisp; x += xinc) { + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; + nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { + if (((chr == 0xc9) || (chr == 0xfe)) && ((nextchr > 0xa0) && (nextchr < 0xff))) + dat = fontdatksc5601_user[((chr == 0xfe) ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; + else if (nextchr & 0x80) + dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; + else + dat = 0xff; + } else { + if (attr & 8) charaddr = svga->charsetb + (chr * 128); + else charaddr = svga->charseta + (chr * 128); + + dat = svga->vram[charaddr + (svga->sc << 2)]; + } + + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if (((chr & ~0x1f) != 0xc0) || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; + + if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + if (((chr == 0xc9) || (chr == 0xfe)) && ((nextchr > 0xa0) && (nextchr < 0xff))) + dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; + else if(nextchr & 0x80) + dat = fontdatksc5601[((chr & 0x7f) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; + else + dat = 0xff; + + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if (((chr & ~0x1f) != 0xc0) || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + + svga->ma += 4; + p += xinc; + x += xinc; + } + } + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_2bpp_lowres(svga_t *svga) +{ + int changed_offset, x; + uint32_t *p; + uint8_t dat[2]; + + if ((svga->displine + svga->y_add) < 0) + return; + + changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 16) { + dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]; + dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1]; + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; + + p += 16; + } + } +} + + +void +svga_render_2bpp_highres(svga_t *svga) +{ + int changed_offset, x; + uint32_t *p; + uint8_t dat[2]; + + if ((svga->displine + svga->y_add) < 0) + return; + + changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]; + dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1]; + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; + + p += 8; + } + } +} + + +void +svga_render_4bpp_lowres(svga_t *svga) +{ + int x; + uint32_t *p; + uint8_t edat[4]; + uint8_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 16) { + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]); + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 16; + } + } +} + + +void +svga_render_4bpp_highres(svga_t *svga) +{ + int changed_offset, x; + uint32_t *p; + uint8_t edat[4]; + uint8_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]); + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 8; + } + } +} + + +void +svga_render_8bpp_lowres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + + p[0] = p[1] = svga->map8[dat & 0xff]; + p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + + svga->ma += 4; + p += 8; + } + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_8bpp_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + p[0] = svga->map8[dat & 0xff]; + p[1] = svga->map8[(dat >> 8) & 0xff]; + p[2] = svga->map8[(dat >> 16) & 0xff]; + p[3] = svga->map8[(dat >> 24) & 0xff]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + p[4] = svga->map8[dat & 0xff]; + p[5] = svga->map8[(dat >> 8) & 0xff]; + p[6] = svga->map8[(dat >> 16) & 0xff]; + p[7] = svga->map8[(dat >> 24) & 0xff]; + + svga->ma += 8; + p += 8; + } + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_15bpp_lowres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 4) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + + p[(x << 1)] = p[(x << 1) + 1] = video_15to32[dat & 0xffff]; + + p[(x << 1) + 2] = p[(x << 1) + 3] = video_15to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + + p[(x << 1) + 4] = p[(x << 1) + 5] = video_15to32[dat & 0xffff]; + + p[(x << 1) + 6] = p[(x << 1) + 7] = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_15bpp_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[x + 2] = video_15to32[dat & 0xffff]; + p[x + 3] = video_15to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + p[x + 4] = video_15to32[dat & 0xffff]; + p[x + 5] = video_15to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + p[x + 6] = video_15to32[dat & 0xffff]; + p[x + 7] = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_15bpp_mix_lowres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 4) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[(x << 1)] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + + dat >>= 16; + p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + + dat >>= 16; + p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_15bpp_mix_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_16bpp_lowres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 4) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[(x << 1)] = p[(x << 1) + 1] = video_16to32[dat & 0xffff]; + p[(x << 1) + 2] = p[(x << 1) + 3] = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[(x << 1) + 4] = p[(x << 1) + 5] = video_16to32[dat & 0xffff]; + p[(x << 1) + 6] = p[(x << 1) + 7] = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_16bpp_highres(svga_t *svga) +{ + int x; + uint32_t *p; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 8) { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[x + 2] = video_16to32[dat & 0xffff]; + p[x + 3] = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + p[x + 4] = video_16to32[dat & 0xffff]; + p[x + 5] = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + p[x + 6] = video_16to32[dat & 0xffff]; + p[x + 7] = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_24bpp_lowres(svga_t *svga) +{ + int x; + uint32_t fg; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x++) { + fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); + svga->ma += 3; + svga->ma &= svga->vram_display_mask; + buffer32->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = + buffer32->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = fg; + } + } +} + + +void +svga_render_24bpp_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x += 4) { + dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + p[x] = dat & 0xffffff; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); + p[x + 1] = dat & 0xffffff; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); + p[x + 2] = dat & 0xffffff; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); + p[x + 3] = dat & 0xffffff; + + svga->ma += 12; + } + svga->ma &= svga->vram_display_mask; + } +} + + +void +svga_render_32bpp_lowres(svga_t *svga) +{ + int x; + uint32_t fg; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= svga->hdisp; x++) { + fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + buffer32->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = + buffer32->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = fg; + } + } +} + + +void +svga_render_32bpp_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->fullchange) - { - uint32_t *p = &buffer32->line[svga->displine + y_add][32 + x_add]; - int x, xx; - int drawcursor; - uint8_t chr, attr, dat; - uint32_t charaddr; - int fg, bg; - int xinc = (svga->seqregs[1] & 1) ? 16 : 18; - - for (x = 0; x < svga->hdisp; x += xinc) - { - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; - if (attr & 8) charaddr = svga->charsetb + (chr * 128); - else charaddr = svga->charseta + (chr * 128); + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (drawcursor) - { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } - else - { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) - { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } - - dat = svga->vram[charaddr + (svga->sc << 2)]; - if (svga->seqregs[1] & 1) - { - for (xx = 0; xx < 16; xx += 2) - p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; - } - else - { - for (xx = 0; xx < 16; xx += 2) - p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) - p[16] = p[17] = bg; - else - p[16] = p[17] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; - } - svga->ma &= svga->vram_display_mask; - } + for (x = 0; x <= svga->hdisp; x++) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + p[x] = dat & 0xffffff; + } + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + } } -void svga_render_text_80(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; +void +svga_render_ABGR8888_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->fullchange) - { - uint32_t *p = &buffer32->line[svga->displine + y_add][32 + x_add]; - int x, xx; - int drawcursor; - uint8_t chr, attr, dat; - uint32_t charaddr; - int fg, bg; - int xinc = (svga->seqregs[1] & 1) ? 8 : 9; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x < svga->hdisp; x += xinc) - { - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; - - - if (attr & 8) charaddr = svga->charsetb + (chr * 128); - else charaddr = svga->charseta + (chr * 128); - - if (drawcursor) - { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } - else - { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) - { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } - - dat = svga->vram[charaddr + (svga->sc << 2)]; - if (svga->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; - } - svga->ma &= svga->vram_display_mask; - } + for (x = 0; x <= svga->hdisp; x++) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + } + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + } } -void svga_render_text_80_ksc5601(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; +void +svga_render_RGBA8888_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->fullchange) - { - uint32_t *p = &buffer32->line[svga->displine + y_add][32 + x_add]; - int x, xx; - int drawcursor; - uint8_t chr, attr, dat, nextchr; - uint32_t charaddr; - int fg, bg; - int xinc = (svga->seqregs[1] & 1) ? 8 : 9; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x < svga->hdisp; x += xinc) - { - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; - - - if (drawcursor) - { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } - else - { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) - { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } - - if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) - { - if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; - else if(nextchr & 0x80) - dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; - else - dat = 0xff; - } - else - { - if (attr & 8) charaddr = svga->charsetb + (chr * 128); - else charaddr = svga->charseta + (chr * 128); - - dat = svga->vram[charaddr + (svga->sc << 2)]; - } - if (svga->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; - - if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) - { - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; - - if (drawcursor) - { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } - else - { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) - { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } - - if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; - else if(nextchr & 0x80) - dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; - else - dat = 0xFF; - if (svga->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - - svga->ma += 4; - p += xinc; - x += xinc; - } - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_2bpp_lowres(svga_t *svga) -{ - int changed_offset; - - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - - if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) - { - int x; - int offset = ((8 - svga->scrollcache) << 1) + 16; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 16) - { - uint8_t dat[2]; - - dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]; - dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1]; - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - - p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; - p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; - p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; - p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; - p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; - p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; - p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; - p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; - - p += 16; - } - } -} - -void svga_render_2bpp_highres(svga_t *svga) -{ - int changed_offset; - - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - - if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) - { - int x; - int offset = (8 - svga->scrollcache) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint8_t dat[2]; - - dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]; - dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1]; - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - - p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; - p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; - p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; - p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; - p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; - p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; - p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; - p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; - - p += 8; - } - } -} - -void svga_render_4bpp_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = ((8 - svga->scrollcache) << 1) + 16; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 16) - { - uint8_t edat[4]; - uint8_t dat; - - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]); - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - - p += 16; - } - } -} - -void svga_render_4bpp_highres(svga_t *svga) -{ - int changed_offset; - - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - - if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) - { - int x; - int offset = (8 - svga->scrollcache) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint8_t edat[4]; - uint8_t dat; - - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]); - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - - p += 8; - } - } -} - -void svga_render_8bpp_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - (svga->scrollcache & 6)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - - p[0] = p[1] = svga->pallook[dat & 0xff]; - p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff]; - p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff]; - p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff]; - - svga->ma += 4; - p += 8; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_8bpp_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat; - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->pallook[dat & 0xff]; - p[1] = svga->pallook[(dat >> 8) & 0xff]; - p[2] = svga->pallook[(dat >> 16) & 0xff]; - p[3] = svga->pallook[(dat >> 24) & 0xff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->pallook[dat & 0xff]; - p[5] = svga->pallook[(dat >> 8) & 0xff]; - p[6] = svga->pallook[(dat >> 16) & 0xff]; - p[7] = svga->pallook[(dat >> 24) & 0xff]; - - svga->ma += 8; - p += 8; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_8bpp_gs_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - (svga->scrollcache & 6)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - - p[0] = p[1] = video_8togs[dat & 0xff]; - p[2] = p[3] = video_8togs[(dat >> 8) & 0xff]; - p[4] = p[5] = video_8togs[(dat >> 16) & 0xff]; - p[6] = p[7] = video_8togs[(dat >> 24) & 0xff]; - - svga->ma += 4; - p += 8; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_8bpp_gs_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat; - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = video_8togs[dat & 0xff]; - p[1] = video_8togs[(dat >> 8) & 0xff]; - p[2] = video_8togs[(dat >> 16) & 0xff]; - p[3] = video_8togs[(dat >> 24) & 0xff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = video_8togs[dat & 0xff]; - p[5] = video_8togs[(dat >> 8) & 0xff]; - p[6] = video_8togs[(dat >> 16) & 0xff]; - p[7] = video_8togs[(dat >> 24) & 0xff]; - - svga->ma += 8; - p += 8; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_8bpp_rgb_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - (svga->scrollcache & 6)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - - p[0] = p[1] = video_8to32[dat & 0xff]; - p[2] = p[3] = video_8to32[(dat >> 8) & 0xff]; - p[4] = p[5] = video_8to32[(dat >> 16) & 0xff]; - p[6] = p[7] = video_8to32[(dat >> 24) & 0xff]; - - svga->ma += 4; - p += 8; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_8bpp_rgb_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat; - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = video_8to32[dat & 0xff]; - p[1] = video_8to32[(dat >> 8) & 0xff]; - p[2] = video_8to32[(dat >> 16) & 0xff]; - p[3] = video_8to32[(dat >> 24) & 0xff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = video_8to32[dat & 0xff]; - p[5] = video_8to32[(dat >> 8) & 0xff]; - p[6] = video_8to32[(dat >> 16) & 0xff]; - p[7] = video_8to32[(dat >> 24) & 0xff]; - - svga->ma += 8; - p += 8; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_15bpp_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - (svga->scrollcache & 6)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 4) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - - p[x] = video_15to32[dat & 0xffff]; - p[x + 1] = video_15to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - - p[x + 2] = video_15to32[dat & 0xffff]; - p[x + 3] = video_15to32[dat >> 16]; - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_15bpp_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = video_15to32[dat & 0xffff]; - p[x + 1] = video_15to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = video_15to32[dat & 0xffff]; - p[x + 3] = video_15to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = video_15to32[dat & 0xffff]; - p[x + 5] = video_15to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = video_15to32[dat & 0xffff]; - p[x + 7] = video_15to32[dat >> 16]; - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_15bpp_mix_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - (svga->scrollcache & 6)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 4) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - - dat >>= 16; - p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - - dat >>= 16; - p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_15bpp_mix_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_16bpp_lowres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - (svga->scrollcache & 6)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 4) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - - p[x] = video_16to32[dat & 0xffff]; - p[x + 1] = video_16to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - - p[x + 2] = video_16to32[dat & 0xffff]; - p[x + 3] = video_16to32[dat >> 16]; - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_16bpp_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 8) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = video_16to32[dat & 0xffff]; - p[x + 1] = video_16to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = video_16to32[dat & 0xffff]; - p[x + 3] = video_16to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = video_16to32[dat & 0xffff]; - p[x + 5] = video_16to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = video_16to32[dat & 0xffff]; - p[x + 7] = video_16to32[dat >> 16]; - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_24bpp_lowres(svga_t *svga) -{ - int x, offset; - uint32_t fg; - - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - offset = (8 - (svga->scrollcache & 6)) + 24; - - for (x = 0; x <= svga->hdisp; x++) - { - fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); - svga->ma += 3; - svga->ma &= svga->vram_display_mask; - buffer32->line[svga->displine + y_add][(x << 1) + offset + x_add] = buffer32->line[svga->displine + y_add][(x << 1) + 1 + offset + x_add] = fg; - } - } -} - -void svga_render_24bpp_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x += 4) - { - uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[x] = dat & 0xffffff; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); - p[x + 1] = dat & 0xffffff; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); - p[x + 2] = dat & 0xffffff; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); - p[x + 3] = dat & 0xffffff; - - svga->ma += 12; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_32bpp_lowres(svga_t *svga) -{ - int x, offset; - uint32_t fg; - - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) - { - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - offset = (8 - (svga->scrollcache & 6)) + 24; - - for (x = 0; x <= svga->hdisp; x++) - { - fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - buffer32->line[svga->displine + y_add][(x << 1) + offset + x_add] = buffer32->line[svga->displine + y_add][(x << 1) + 1 + offset + x_add] = fg; - } - } -} - -/*72% - 91%*/ -void svga_render_32bpp_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x++) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = dat & 0xffffff; - } - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_ABGR8888_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x++) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - } - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_RGBA8888_highres(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) - { - int x; - int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; - uint32_t *p = &buffer32->line[svga->displine + y_add][offset + x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - for (x = 0; x <= svga->hdisp; x++) - { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = dat >> 8; - } - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - } + for (x = 0; x <= svga->hdisp; x++) { + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + p[x] = dat >> 8; + } + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + } } diff --git a/src/video/vid_svga_render.h b/src/video/vid_svga_render.h index f619d3520..a99e25e16 100644 --- a/src/video/vid_svga_render.h +++ b/src/video/vid_svga_render.h @@ -28,6 +28,8 @@ extern int scrollcache; extern uint8_t edatlookup[4][4]; void svga_render_blank(svga_t *svga); +void svga_render_overscan_left(svga_t *svga); +void svga_render_overscan_right(svga_t *svga); void svga_render_text_40(svga_t *svga); void svga_render_text_80(svga_t *svga); void svga_render_text_80_ksc5601(svga_t *svga); diff --git a/src/video/vid_table.c b/src/video/vid_table.c index e3937a71d..d86e61686 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -210,7 +210,7 @@ void video_reset_close(void) { video_inform(VIDEO_FLAG_TYPE_NONE, &timing_default); - was_reset = 1; + was_reset = 0; } diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index be9305330..c366fae12 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -681,10 +681,6 @@ void tgui_hwcursor_draw(svga_t *svga, int displine) uint32_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add, x_add; - - y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 8; @@ -696,9 +692,9 @@ void tgui_hwcursor_draw(svga_t *svga, int displine) if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x80000000)) - buffer32->line[displine + y_add][offset + 32 + x_add] = (dat[1] & 0x80000000) ? 0xffffff : 0; + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x80000000) ? 0xffffff : 0; else if (dat[1] & 0x80000000) - buffer32->line[displine + y_add][offset + 32 + x_add] ^= 0xffffff; + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } offset++; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index b03ae4f66..2685aa2ac 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -7352,8 +7352,6 @@ static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uin void voodoo_callback(void *p) { voodoo_t *voodoo = (voodoo_t *)p; - int y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) { @@ -7383,12 +7381,12 @@ void voodoo_callback(void *p) if (draw_voodoo->dirty_line[draw_line]) { - uint32_t *p = &buffer32->line[voodoo->line + y_add][32 + x_add]; + uint32_t *p = &buffer32->line[voodoo->line + 8][8]; uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width]; int x; draw_voodoo->dirty_line[draw_line] = 0; - + if (voodoo->line < voodoo->dirty_line_low) { voodoo->dirty_line_low = voodoo->line; @@ -7396,7 +7394,11 @@ void voodoo_callback(void *p) } if (voodoo->line > voodoo->dirty_line_high) voodoo->dirty_line_high = voodoo->line; - + + /* Draw left overscan. */ + for (x = 0; x < 8; x++) + buffer32->line[voodoo->line + 8][x] = 0x00000000; + if (voodoo->scrfilter && voodoo->scrfilterEnabled) { uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */ @@ -7418,6 +7420,10 @@ void voodoo_callback(void *p) p[x] = draw_voodoo->video_16to32[src[x]]; } } + + /* Draw right overscan. */ + for (x = 0; x < 8; x++) + buffer32->line[voodoo->line + 8][voodoo->h_disp + x + 8] = 0x00000000; } } } diff --git a/src/video/video.c b/src/video/video.c index 375ac3049..16806cfd6 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -48,12 +48,16 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. */ +#define PNG_DEBUG 0 +#include +#include #include #include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -66,6 +70,7 @@ #include "vid_svga.h" +volatile int screenshots = 0; bitmap_t *buffer32 = NULL; uint8_t fontdat[2048][8]; /* IBM CGA font */ uint8_t fontdatm[2048][16]; /* IBM MDA font */ @@ -253,6 +258,26 @@ static struct { static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); +#ifdef ENABLE_VIDEO_LOG +int sdl_do_log = ENABLE_VIDEO_LOG; + + +static void +video_log(const char *fmt, ...) +{ + va_list ap; + + if (video_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define video_log(fmt, ...) +#endif + + static void blit_thread(void *param) { @@ -305,10 +330,120 @@ video_wait_for_buffer(void) } +static png_structp png_ptr; +static png_infop info_ptr; + + +static void +video_take_screenshot(const wchar_t *fn, int startx, int starty, int w, int h) +{ + int i, x, y; + png_bytep *b_rgb = NULL; + FILE *fp = NULL; + uint32_t temp = 0x00000000; + + /* create file */ + fp = plat_fopen((wchar_t *) fn, (wchar_t *) L"wb"); + if (!fp) { + video_log("[video_take_screenshot] File %ls could not be opened for writing", fn); + return; + } + + /* initialize stuff */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) { + video_log("[video_take_screenshot] png_create_write_struct failed"); + fclose(fp); + return; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + video_log("[video_take_screenshot] png_create_info_struct failed"); + fclose(fp); + return; + } + + png_init_io(png_ptr, fp); + + png_set_IHDR(png_ptr, info_ptr, w, h, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * h); + if (b_rgb == NULL) { + video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory"); + fclose(fp); + return; + } + + for (y = 0; y < h; ++y) { + b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); + for (x = 0; x < w; ++x) { + if (video_grayscale || invert_display) + video_transform_copy(&temp, &(buffer32->line[y + starty][x + startx]), 1); + else + temp = buffer32->line[y + starty][x + startx]; + + b_rgb[y][(x) * 3 + 0] = (temp >> 16) & 0xff; + b_rgb[y][(x) * 3 + 1] = (temp >> 8) & 0xff; + b_rgb[y][(x) * 3 + 2] = temp & 0xff; + } + } + + png_write_info(png_ptr, info_ptr); + + png_write_image(png_ptr, b_rgb); + + png_write_end(png_ptr, NULL); + + /* cleanup heap allocation */ + for (i = 0; i < h; i++) + if (b_rgb[i]) free(b_rgb[i]); + + if (b_rgb) free(b_rgb); + + if (fp) fclose(fp); +} + + +static void +video_screenshot(int x, int y, int w, int h) +{ + wchar_t path[1024], fn[128]; + + memset(fn, 0, sizeof(fn)); + memset(path, 0, sizeof(path)); + + plat_append_filename(path, usr_path, SCREENSHOT_PATH); + + if (! plat_dir_check(path)) + plat_dir_create(path); + + wcscat(path, L"\\"); + + plat_tempfile(fn, NULL, L".png"); + wcscat(path, fn); + + video_log("taking screenshot to: %S\n", path); + + video_take_screenshot((const wchar_t *) path, x, y, w, h); + png_destroy_write_struct(&png_ptr, &info_ptr); +} + + void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { - if (h <= 0) return; + if (screenshots) { + video_screenshot(x, y, w, h); + screenshots--; + video_log("screenshot taken, %i left\n", screenshots); + } + + if ((w <= 0) || (h <= 0)) + return; video_wait_for_blit(); @@ -652,7 +787,8 @@ video_init(void) } /* Account for overscan. */ - buffer32 = create_bitmap(2048, 2048); + // buffer32 = create_bitmap(2048 + 64, 2048 + 64); + buffer32 = create_bitmap(4096 + 64, 4096 + 64); for (c = 0; c < 64; c++) { cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; @@ -691,7 +827,7 @@ video_init(void) video_15to32 = malloc(4 * 65536); for (c = 0; c < 65536; c++) - video_15to32[c] = calc_15to32(c); + video_15to32[c] = calc_15to32(c & 0x7fff); video_16to32 = malloc(4 * 65536); for (c = 0; c < 65536; c++) diff --git a/src/video/video.h b/src/video/video.h index 77a3a5733..e633c603b 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -83,6 +83,7 @@ extern int egareads, egawrites; extern int changeframecount; +extern volatile int screenshots; extern bitmap_t *buffer32; extern PALETTE cgapal, cgapal_mono[6]; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index ce8fd696e..6d676fa81 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -186,15 +186,6 @@ endif ifndef DINPUT DINPUT := n endif -ifndef D3DX - D3DX := y - ifeq ($(ARM), y) - D3DX := n - endif - ifeq ($(ARM64), y) - D3DX := n - endif -endif ifndef OPENAL OPENAL := y endif @@ -274,7 +265,7 @@ else TOOL_PREFIX := i686-w64-mingw32- endif CPP := ${TOOL_PREFIX}g++ -CC := ${TOOL_PREFIX}gcc +CC := gcc WINDRES := windres STRIP := strip ifeq ($(ARM64), y) @@ -435,10 +426,6 @@ ifeq ($(DINPUT), y) OPTS += -DUSE_DINPUT endif -ifeq ($(D3DX), y) -OPTS += -DUSE_D3DX -endif - # Options for the DEV branch. ifeq ($(DEV_BRANCH), y) OPTS += -DDEV_BRANCH @@ -733,9 +720,6 @@ ifeq ($(DINPUT), y) else LIBS += -lxinput endif -ifeq ($(D3DX), y) -LIBS += -ld3dx9 -endif ifeq ($(STATIC), y) LIBS += -static diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 78854ae40..23a9678e2 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -186,15 +186,6 @@ endif ifndef DINPUT DINPUT := n endif -ifndef D3DX - D3DX := y - ifeq ($(ARM), y) - D3DX := n - endif - ifeq ($(ARM64), y) - D3DX := n - endif -endif ifndef OPENAL OPENAL := y endif @@ -441,10 +432,6 @@ ifeq ($(DINPUT), y) OPTS += -DUSE_DINPUT endif -ifeq ($(D3DX), y) -OPTS += -DUSE_D3DX -endif - # Options for the DEV branch. ifeq ($(DEV_BRANCH), y) OPTS += -DDEV_BRANCH @@ -739,9 +726,6 @@ ifeq ($(DINPUT), y) else LIBS += -lxinput endif -ifeq ($(D3DX), y) -LIBS += -ld3dx9 -endif ifeq ($(STATIC), y) LIBS += -static diff --git a/src/win/win.c b/src/win/win.c index d0097f79a..ac91ac436 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.57 2019/03/06 + * Version: @(#)win.c 1.0.58 2019/10/19 * * Authors: Sarah Walker, * Miran Grca, @@ -33,6 +33,7 @@ #include "../86box.h" #include "../config.h" #include "../device.h" +#include "../keyboard.h" #include "../mouse.h" #include "../video/video.h" #define GLOBAL @@ -84,28 +85,27 @@ static const struct { void (*resize)(int x, int y); int (*pause)(void); void (*enable)(int enable); - void (*screenshot)(const wchar_t *fn); } vid_apis[2][RENDERERS_NUM] = { { - { "DDraw", 1, (int(*)(void*))ddraw_init, ddraw_close, NULL, ddraw_pause, ddraw_enable, ddraw_take_screenshot }, + { "DDraw", 1, (int(*)(void*))ddraw_init, ddraw_close, NULL, ddraw_pause, ddraw_enable }, #ifdef USE_D2D - { "D2D", 1, (int(*)(void*))d2d_init, d2d_close, NULL, d2d_pause, d2d_enable, d2d_take_screenshot }, + { "D2D", 1, (int(*)(void*))d2d_init, d2d_close, NULL, d2d_pause, d2d_enable }, #endif - { "D3D", 1, (int(*)(void*))d3d_init, d3d_close, d3d_resize, d3d_pause, d3d_enable, d3d_take_screenshot }, - { "SDL", 1, (int(*)(void*))sdl_init, sdl_close, NULL, sdl_pause, sdl_enable, sdl_take_screenshot } + { "D3D", 1, (int(*)(void*))d3d_init, d3d_close, d3d_resize, d3d_pause, d3d_enable }, + { "SDL", 1, (int(*)(void*))sdl_init, sdl_close, NULL, sdl_pause, sdl_enable } #ifdef USE_VNC - ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL, vnc_take_screenshot } + ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL } #endif }, { - { "DDraw", 1, (int(*)(void*))ddraw_init_fs, ddraw_close, NULL, ddraw_pause, ddraw_enable, ddraw_take_screenshot }, + { "DDraw", 1, (int(*)(void*))ddraw_init_fs, ddraw_close, NULL, ddraw_pause, ddraw_enable }, #ifdef USE_D2D - { "D2D", 1, (int(*)(void*))d2d_init_fs, d2d_close, NULL, d2d_pause, d2d_enable, d2d_take_screenshot }, + { "D2D", 1, (int(*)(void*))d2d_init_fs, d2d_close, NULL, d2d_pause, d2d_enable }, #endif - { "D3D", 1, (int(*)(void*))d3d_init_fs, d3d_close, NULL, d3d_pause, d3d_enable, d3d_take_screenshot }, - { "SDL", 1, (int(*)(void*))sdl_init_fs, sdl_close, sdl_resize, sdl_pause, sdl_enable, sdl_take_screenshot } + { "D3D", 1, (int(*)(void*))d3d_init_fs, d3d_close, NULL, d3d_pause, d3d_enable }, + { "SDL", 1, (int(*)(void*))sdl_init_fs, sdl_close, sdl_resize, sdl_pause, sdl_enable } #ifdef USE_VNC - ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL, vnc_take_screenshot } + ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL } #endif }, }; @@ -815,6 +815,8 @@ plat_setfullscreen(int on) startblit(); video_wait_for_blit(); + plat_vidapi_enable(0); + win_mouse_close(); /* Close the current mode, and open the new one. */ @@ -825,10 +827,15 @@ plat_setfullscreen(int on) win_mouse_init(); + plat_vidapi_enable(1); + /* Release video and make it redraw the screen. */ endblit(); device_force_redraw(); + /* Send a CTRL break code so CTRL does not get stuck. */ + keyboard_input(0, 0x01D); + /* Finally, handle the host's mouse cursor. */ /* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ show_cursor(video_fullscreen ? 0 : -1); @@ -838,30 +845,10 @@ plat_setfullscreen(int on) void take_screenshot(void) { - wchar_t path[1024], fn[128]; - struct tm *info; - time_t now; - - if (!vid_api_inited || !vid_apis[video_fullscreen][vid_api].screenshot) return; - win_log("Screenshot: video API is: %i\n", vid_api); - if ((vid_api < 0) || (vid_api >= RENDERERS_NUM)) return; - - memset(fn, 0, sizeof(fn)); - memset(path, 0, sizeof(path)); - - (void)time(&now); - info = localtime(&now); - - plat_append_filename(path, usr_path, SCREENSHOT_PATH); - - if (! plat_dir_check(path)) - plat_dir_create(path); - - wcscat(path, L"\\"); - - wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); - wcscat(path, fn); - vid_apis[video_fullscreen][vid_api].screenshot((const wchar_t *) path); + startblit(); + screenshots++; + endblit(); + device_force_redraw(); } diff --git a/src/win/win_d2d.cpp b/src/win/win_d2d.cpp index 3a5ed202b..655cf0591 100644 --- a/src/win/win_d2d.cpp +++ b/src/win/win_d2d.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft Direct2D. * - * Version: @(#)win_d2d.cpp 1.0.3 2019/03/09 + * Version: @(#)win_d2d.cpp 1.0.4 2019/10/12 * * Authors: David Hrdlička, * @@ -505,18 +505,6 @@ d2d_pause(void) } -void -d2d_take_screenshot(const wchar_t *fn) -{ - // Saving a screenshot of a Direct2D render target is harder than - // one would think. Keeping this stubbed for the moment - // -ryu - - d2d_log("Direct2D: d2d_take_screenshot(%s)\n", fn); - return; -} - - void d2d_enable(int enable) { diff --git a/src/win/win_d2d.h b/src/win/win_d2d.h index d76c4bdd0..0933d9e34 100644 --- a/src/win/win_d2d.h +++ b/src/win/win_d2d.h @@ -8,11 +8,11 @@ * * Definitions for the Direct2D rendering module. * - * Version: @(#)win_d2d.h 1.0.0 2018/07/19 + * Version: @(#)win_d2d.h 1.0.1 2019/10/12 * * Authors: David Hrdlička, * - * Copyright 2018 David Hrdlička. + * Copyright 2018,2019 David Hrdlička. */ #ifndef WIN_D2D_H # define WIN_D2D_H @@ -25,7 +25,6 @@ extern void d2d_close(void); extern int d2d_init(HWND h); extern int d2d_init_fs(HWND h); extern int d2d_pause(void); -extern void d2d_take_screenshot(const wchar_t *fn); extern void d2d_enable(int enable); #ifdef __cplusplus diff --git a/src/win/win_d3d.cpp b/src/win/win_d3d.cpp index 6e5a6f8ef..974b17341 100644 --- a/src/win/win_d3d.cpp +++ b/src/win/win_d3d.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft Direct3D 9. * - * Version: @(#)win_d3d.cpp 1.0.12 2019/03/09 + * Version: @(#)win_d3d.cpp 1.0.13 2019/10/12 * * Authors: Sarah Walker, * Miran Grca, @@ -145,6 +145,7 @@ d3d_size(RECT w_rect, double *l, double *t, double *r, double *b, int w, int h) static void d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) { +#if 0 HRESULT hr = D3D_OK; HRESULT hbsr = D3D_OK; VOID* pVoid; @@ -152,6 +153,7 @@ d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) RECT w_rect; int yy; double l = 0, t = 0, r = 0, b = 0; + RECT lock_rect; if (!d3d_enabled) { video_blit_complete(); @@ -163,33 +165,28 @@ d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) return; /*Nothing to do*/ } - if (hr == D3D_OK && !(y1 == 0 && y2 == 0)) { - RECT lock_rect; + lock_rect.top = y1; + lock_rect.left = 0; + lock_rect.bottom = y2; + lock_rect.right = 2047; - lock_rect.top = y1; - lock_rect.left = 0; - lock_rect.bottom = y2; - lock_rect.right = 2047; - - hr = d3dTexture->LockRect(0, &dr, &lock_rect, 0); - if (hr == D3D_OK) { - for (yy = y1; yy < y2; yy++) { - if (buffer32) { - if (video_grayscale || invert_display) - video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(buffer32->line[yy + y][x]), w); - else - memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(buffer32->line[yy + y][x]), w * 4); - } + hr = d3dTexture->LockRect(0, &dr, &lock_rect, 0); + if (hr == D3D_OK) { + for (yy = y1; yy < y2; yy++) { + if (buffer32) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(buffer32->line[yy + y][x]), w); + else + memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(buffer32->line[yy + y][x]), w * 4); } - - video_blit_complete(); - d3dTexture->UnlockRect(0); - } else { - video_blit_complete(); - return; } - } else + video_blit_complete(); + d3dTexture->UnlockRect(0); + } else { + video_blit_complete(); + return; + } d3d_verts[0].tu = d3d_verts[2].tu = d3d_verts[3].tu = 0; d3d_verts[0].tv = d3d_verts[3].tv = d3d_verts[4].tv = 0; @@ -258,6 +255,115 @@ d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) PostMessage(hwndMain, WM_RESETD3D, 0, 0); +#else + HRESULT hr = D3D_OK; + HRESULT hbsr = D3D_OK; + VOID* pVoid; + D3DLOCKED_RECT dr; + RECT r, w_rect; + int yy; + double l = 0, t = 0, rr = 0, b = 0; + + if (!d3d_enabled) { + video_blit_complete(); + return; + } + + if ((y1 == y2) || (h <= 0)) { + video_blit_complete(); + return; /*Nothing to do*/ + } + + r.top = y1; + r.left = 0; + r.bottom = y2; + r.right = 2047; + + hr = d3dTexture->LockRect(0, &dr, &r, 0); + if (hr == D3D_OK) { + for (yy = y1; yy < y2; yy++) { + if (buffer32) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(buffer32->line[yy + y][x]), w); + else + memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(buffer32->line[yy + y][x]), w * 4); + } + } + } + + video_blit_complete(); + d3dTexture->UnlockRect(0); + } else { + video_blit_complete(); + return; + } + + d3d_verts[0].tu = d3d_verts[2].tu = d3d_verts[3].tu = 0;//0.5 / 2048.0; + d3d_verts[0].tv = d3d_verts[3].tv = d3d_verts[4].tv = 0;//0.5 / 2048.0; + d3d_verts[1].tu = d3d_verts[4].tu = d3d_verts[5].tu = (float)w / 2048.0; + d3d_verts[1].tv = d3d_verts[2].tv = d3d_verts[5].tv = (float)h / 2048.0; + d3d_verts[0].color = d3d_verts[1].color = d3d_verts[2].color = + d3d_verts[3].color = d3d_verts[4].color = d3d_verts[5].color = + d3d_verts[6].color = d3d_verts[7].color = d3d_verts[8].color = + d3d_verts[9].color = d3d_verts[10].color = d3d_verts[11].color = 0xffffff; + + GetClientRect(d3d_device_window, &w_rect); + d3d_size(w_rect, &l, &t, &rr, &b, w, h); + + d3d_verts[0].x = l; + d3d_verts[0].y = t; + d3d_verts[1].x = rr; + d3d_verts[1].y = b; + d3d_verts[2].x = l; + d3d_verts[2].y = b; + d3d_verts[3].x = l; + d3d_verts[3].y = t; + d3d_verts[4].x = rr; + d3d_verts[4].y = t; + d3d_verts[5].x = rr; + d3d_verts[5].y = b; + d3d_verts[6].x = d3d_verts[8].x = d3d_verts[9].x = rr - 40.5; + d3d_verts[6].y = d3d_verts[9].y = d3d_verts[10].y = t + 8.5; + d3d_verts[7].x = d3d_verts[10].x = d3d_verts[11].x = rr - 8.5; + d3d_verts[7].y = d3d_verts[8].y = d3d_verts[11].y = t + 14.5; + + if (hr == D3D_OK) + hr = v_buffer->Lock(0, 0, (void**)&pVoid, 0); // lock the vertex buffer + if (hr == D3D_OK) + memcpy(pVoid, d3d_verts, sizeof(d3d_verts)); // copy the vertices to the locked buffer + if (hr == D3D_OK) + hr = v_buffer->Unlock(); // unlock the vertex buffer + + if (hr == D3D_OK) + hbsr = hr = d3ddev->BeginScene(); + + if (hr == D3D_OK) { + if (hr == D3D_OK) + hr = d3ddev->SetTexture(0, d3dTexture); + + if (hr == D3D_OK) + hr = d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); + + if (hr == D3D_OK) + hr = d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX)); + + if (hr == D3D_OK) + hr = d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); + + if (hr == D3D_OK) + hr = d3ddev->SetTexture(0, NULL); + } + + if (hbsr == D3D_OK) + hr = d3ddev->EndScene(); + + if (hr == D3D_OK) + hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL); + + if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) + PostMessage(d3d_hwnd, WM_RESETD3D, 0, 0); +#endif } @@ -404,9 +510,14 @@ d3d_init_objects(void) } +static int old_capture = 0; + + int d3d_init(HWND h) { + RECT rect; + d3d_hwnd = h; d3d = Direct3DCreate9(D3D_SDK_VERSION); @@ -434,6 +545,16 @@ d3d_init(HWND h) d3d_init_objects(); + mouse_capture = old_capture; + + if (mouse_capture) { + GetWindowRect(hwndRender, &rect); + + ClipCursor(&rect); + } + + d3d_device_window = NULL; + video_setblit(d3d_blit); d3d_enabled = 1; @@ -446,6 +567,7 @@ int d3d_init_fs(HWND h) { WCHAR title[200]; + RECT rect; d3d_w = GetSystemMetrics(SM_CXSCREEN); d3d_h = GetSystemMetrics(SM_CYSCREEN); @@ -491,9 +613,22 @@ d3d_init_fs(HWND h) D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev))) fatal("CreateDevice failed\n"); - + d3d_init_objects(); + /* Redirect RawInput to this new window. */ + plat_set_input(d3d_device_window); + + SetFocus(d3d_device_window); + + old_capture = mouse_capture; + + GetWindowRect(d3d_device_window, &rect); + + ClipCursor(&rect); + + mouse_capture = 1; + video_setblit(d3d_blit_fs); d3d_enabled = 1; @@ -518,7 +653,7 @@ d3d_close_objects(void) void d3d_close(void) -{ +{ video_setblit(NULL); if (d3d_enabled) @@ -536,6 +671,12 @@ d3d_close(void) } if (d3d_device_window != NULL) { + plat_set_input(hwndMain); + + ShowWindow(hwndRender, TRUE); + + SetFocus(hwndMain); + DestroyWindow(d3d_device_window); d3d_device_window = NULL; } @@ -631,164 +772,6 @@ d3d_pause(void) } -#ifndef USE_D3DX -static void -SavePNG(wchar_t *szFilename, D3DSURFACE_DESC *surfaceDesc, D3DLOCKED_RECT *d3dlr) -{ - BITMAPINFO bmpInfo; - HDC hdc; - LPVOID pBuf = NULL; - LPVOID pBuf2 = NULL; - png_bytep *b_rgb = NULL; - int i; - - /* create file */ - FILE *fp = plat_fopen(szFilename, (wchar_t *) L"wb"); - if (!fp) { - ddraw_log("[SavePNG] File %ls could not be opened for writing", szFilename); - return; - } - - /* initialize stuff */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - - if (!png_ptr) { - ddraw_log("[SavePNG] png_create_write_struct failed"); - fclose(fp); - return; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - ddraw_log("[SavePNG] png_create_info_struct failed"); - fclose(fp); - return; - } - - png_init_io(png_ptr, fp); - - hdc = GetDC(NULL); - - ZeroMemory(&bmpInfo, sizeof(BITMAPINFO)); - bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - - GetDIBits(hdc, hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS); - - if (bmpInfo.bmiHeader.biSizeImage <= 0) - bmpInfo.bmiHeader.biSizeImage = - bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8; - - pBuf = malloc(bmpInfo.bmiHeader.biSizeImage); - if (pBuf == NULL) { - ddraw_log("[SavePNG] Unable to Allocate Bitmap Memory"); - fclose(fp); - return; - } - - if (ys2 <= 250) { - pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage << 1); - if (pBuf2 == NULL) { - ddraw_log("[SavePNG] Unable to Allocate Secondary Bitmap Memory"); - free(pBuf); - fclose(fp); - return; - } - - } - - ddraw_log("save png w=%i h=%i\n", bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); - - bmpInfo.bmiHeader.biCompression = BI_RGB; - - GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS); - - if (pBuf2) { - bmpInfo.bmiHeader.biSizeImage <<= 1; - bmpInfo.bmiHeader.biHeight <<= 1; - } - - png_set_IHDR(png_ptr, info_ptr, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * bmpInfo.bmiHeader.biHeight); - if (b_rgb == NULL) { - ddraw_log("[SavePNG] Unable to Allocate RGB Bitmap Memory"); - free(pBuf2); - free(pBuf); - fclose(fp); - return; - } - - for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++) { - b_rgb[i] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); - } - - if (pBuf2) { - DoubleLines((uint8_t *) pBuf2, (uint8_t *) pBuf); - bgra_to_rgb(b_rgb, (uint8_t *) pBuf2, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); - } else - bgra_to_rgb(b_rgb, (uint8_t *) pBuf, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); - - png_write_info(png_ptr, info_ptr); - - png_write_image(png_ptr, b_rgb); - - png_write_end(png_ptr, NULL); - - /* cleanup heap allocation */ - if (hdc) ReleaseDC(NULL,hdc); - - for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++) - if (b_rgb[i]) free(b_rgb[i]); - - if (b_rgb) free(b_rgb); - - if (pBuf2) free(pBuf2); - - if (pBuf) free(pBuf); - - if (fp) fclose(fp); -} -#endif - - -void -d3d_take_screenshot(const wchar_t *fn) -{ -#ifdef USE_D3DX - LPDIRECT3DSURFACE9 d3dSurface = NULL; - - if (! d3dTexture) return; - - d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &d3dSurface); - D3DXSaveSurfaceToFile(fn, D3DXIFF_PNG, d3dSurface, NULL, NULL); - - d3dSurface->Release(); - d3dSurface = NULL; -#else - /* TODO: how to take screenshot without d3dx? - just a stub for now */ - LPDIRECT3DSURFACE9 d3dSurface = NULL; - D3DSURFACE_DESC surfaceDesc; - D3DLOCKED_RECT d3dlr; - BYTE *pSurfaceBuffer; - - if (! d3dTexture) return; - - d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &d3dSurface); - d3dSurface->GetDesc(&surfaceDesc); - d3dSurface->LockRect(&d3dlr, 0, D3DLOCK_DONOTWAIT); - pSurfaceBuffer = (BYTE *) d3dlr.pBits + d3dlr.Pitch * (surfaceDesc.Height - 1); - - D3DXSaveSurfaceToFile(fn, D3DXIFF_PNG, d3dSurface, NULL, NULL); - - d3dSurface->Release(); - d3dSurface = NULL; -#endif -} - - void d3d_enable(int enable) { diff --git a/src/win/win_d3d.h b/src/win/win_d3d.h index 8a869ab31..d8f21dfc0 100644 --- a/src/win/win_d3d.h +++ b/src/win/win_d3d.h @@ -8,20 +8,19 @@ * * Direct3D 9 rendererer and screenshots taking. * - * Version: @(#)win_d3d.h 1.0.3 2017/11/12 + * Version: @(#)win_d3d.h 1.0.4 2019/10/12 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #ifndef WIN_D3D_H # define WIN_D3D_H # define UNICODE # define BITMAP WINDOWS_BITMAP # include -# include # undef BITMAP @@ -36,7 +35,6 @@ extern void d3d_reset(void); extern void d3d_reset_fs(void); extern int d3d_pause(void); extern void d3d_resize(int x, int y); -extern void d3d_take_screenshot(const wchar_t *fn); extern void d3d_enable(int enable); #ifdef __cplusplus diff --git a/src/win/win_ddraw.cpp b/src/win/win_ddraw.cpp index 1f4ac469d..35772613c 100644 --- a/src/win/win_ddraw.cpp +++ b/src/win/win_ddraw.cpp @@ -11,7 +11,7 @@ * NOTES: This code should be re-merged into a single init() with a * 'fullscreen' argument, indicating FS mode is requested. * - * Version: @(#)win_ddraw.cpp 1.0.14 2019/03/09 + * Version: @(#)win_ddraw.cpp 1.0.15 2019/10/12 * * Authors: Sarah Walker, * Miran Grca, @@ -29,9 +29,6 @@ #include #undef BITMAP -#define PNG_DEBUG 0 -#include - #define HAVE_STDARG_H #include "../86box.h" #include "../device.h" @@ -50,14 +47,9 @@ static LPDIRECTDRAWSURFACE4 lpdds_pri = NULL, static LPDIRECTDRAWCLIPPER lpdd_clipper = NULL; static DDSURFACEDESC2 ddsd; static HWND ddraw_hwnd; -static HBITMAP hbitmap; -static int ddraw_w, ddraw_h, - xs, ys, ys2; +static int ddraw_w, ddraw_h; static volatile int ddraw_enabled = 0; -static png_structp png_ptr; -static png_infop info_ptr; - #ifdef ENABLE_DDRAW_LOG int ddraw_do_log = ENABLE_DDRAW_LOG; @@ -79,180 +71,6 @@ ddraw_log(const char *fmt, ...) #endif -static void -CopySurface(IDirectDrawSurface4 *pDDSurface) -{ - HDC hdc, hmemdc; - HBITMAP hprevbitmap; - DDSURFACEDESC2 ddsd2; - - pDDSurface->GetDC(&hdc); - hmemdc = CreateCompatibleDC(hdc); - ZeroMemory(&ddsd2 ,sizeof( ddsd2 )); // better to clear before using - ddsd2.dwSize = sizeof( ddsd2 ); //initialize with size - pDDSurface->GetSurfaceDesc(&ddsd2); - hbitmap = CreateCompatibleBitmap( hdc ,xs ,ys); - hprevbitmap = (HBITMAP) SelectObject( hmemdc, hbitmap ); - BitBlt(hmemdc,0 ,0 ,xs ,ys ,hdc ,0 ,0,SRCCOPY); - SelectObject(hmemdc,hprevbitmap); // restore the old bitmap - DeleteDC(hmemdc); - pDDSurface->ReleaseDC(hdc); -} - - -static void -bgra_to_rgb(png_bytep *b_rgb, uint8_t *bgra, int width, int height) -{ - int i, j; - uint8_t *r, *b; - - if (video_grayscale || invert_display) - *bgra = video_color_transform(*bgra); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - r = &b_rgb[(height - 1) - i][j * 3]; - b = &bgra[((i * width) + j) * 4]; - r[0] = b[2]; - r[1] = b[1]; - r[2] = b[0]; - } - } -} - - -static void -DoubleLines(uint8_t *dst, uint8_t *src) -{ - int i = 0; - - for (i = 0; i < ys; i++) { - memcpy(dst + (i * xs * 8), src + (i * xs * 4), xs * 4); - memcpy(dst + ((i * xs * 8) + (xs * 4)), src + (i * xs * 4), xs * 4); - } -} - - -static void -SavePNG(const wchar_t *szFilename, HBITMAP hBitmap) -{ - BITMAPINFO bmpInfo; - HDC hdc; - LPVOID pBuf = NULL; - LPVOID pBuf2 = NULL; - png_bytep *b_rgb = NULL; - int i; - - /* create file */ - FILE *fp = plat_fopen((wchar_t *) szFilename, (wchar_t *) L"wb"); - if (!fp) { - ddraw_log("[SavePNG] File %ls could not be opened for writing", szFilename); - return; - } - - /* initialize stuff */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - - if (!png_ptr) { - ddraw_log("[SavePNG] png_create_write_struct failed"); - fclose(fp); - return; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - ddraw_log("[SavePNG] png_create_info_struct failed"); - fclose(fp); - return; - } - - png_init_io(png_ptr, fp); - - hdc = GetDC(NULL); - - ZeroMemory(&bmpInfo, sizeof(BITMAPINFO)); - bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - - GetDIBits(hdc, hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS); - - if (bmpInfo.bmiHeader.biSizeImage <= 0) - bmpInfo.bmiHeader.biSizeImage = - bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8; - - pBuf = malloc(bmpInfo.bmiHeader.biSizeImage); - if (pBuf == NULL) { - ddraw_log("[SavePNG] Unable to Allocate Bitmap Memory"); - fclose(fp); - return; - } - - if (ys2 <= 250) { - pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage << 1); - if (pBuf2 == NULL) { - ddraw_log("[SavePNG] Unable to Allocate Secondary Bitmap Memory"); - free(pBuf); - fclose(fp); - return; - } - - } - - ddraw_log("save png w=%i h=%i\n", bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); - - bmpInfo.bmiHeader.biCompression = BI_RGB; - - GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS); - - if (pBuf2) { - bmpInfo.bmiHeader.biSizeImage <<= 1; - bmpInfo.bmiHeader.biHeight <<= 1; - } - - png_set_IHDR(png_ptr, info_ptr, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * bmpInfo.bmiHeader.biHeight); - if (b_rgb == NULL) { - ddraw_log("[SavePNG] Unable to Allocate RGB Bitmap Memory"); - free(pBuf2); - free(pBuf); - fclose(fp); - return; - } - - for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++) { - b_rgb[i] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); - } - - if (pBuf2) { - DoubleLines((uint8_t *) pBuf2, (uint8_t *) pBuf); - bgra_to_rgb(b_rgb, (uint8_t *) pBuf2, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); - } else - bgra_to_rgb(b_rgb, (uint8_t *) pBuf, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); - - png_write_info(png_ptr, info_ptr); - - png_write_image(png_ptr, b_rgb); - - png_write_end(png_ptr, NULL); - - /* cleanup heap allocation */ - if (hdc) ReleaseDC(NULL,hdc); - - for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++) - if (b_rgb[i]) free(b_rgb[i]); - - if (b_rgb) free(b_rgb); - - if (pBuf2) free(pBuf2); - - if (pBuf) free(pBuf); - - if (fp) fclose(fp); -} - - static void ddraw_fs_size_default(RECT w_rect, RECT *r_dest) { @@ -495,42 +313,6 @@ ddraw_blit(int x, int y, int y1, int y2, int w, int h) } -void -ddraw_take_screenshot(const wchar_t *fn) -{ -#if 0 - xs = xsize; - ys = ys2 = ysize; - - /* For EGA/(S)VGA, the size is NOT adjusted for overscan. */ - if ((overscan_y > 16) && enable_overscan) { - xs += overscan_x; - ys += overscan_y; - } - - /* For CGA, the width is adjusted for overscan, but the height is not. */ - if (overscan_y == 16) { - if (ys2 <= 250) - ys += (overscan_y >> 1); - else - ys += overscan_y; - } -#endif - - xs = get_actual_size_x(); - ys = ys2 = get_actual_size_y(); - - if (ysize <= 250) { - ys >>= 1; - ys2 >>= 1; - } - - CopySurface(lpdds_back2); - - SavePNG(fn, hbitmap); -} - - int ddraw_init(HWND h) { diff --git a/src/win/win_ddraw.h b/src/win/win_ddraw.h index 155cb3d24..5e8696d47 100644 --- a/src/win/win_ddraw.h +++ b/src/win/win_ddraw.h @@ -8,13 +8,13 @@ * * Definitions for the DirectDraw 9 rendering module. * - * Version: @(#)win_ddraw.h 1.0.1 2017/11/12 + * Version: @(#)win_ddraw.h 1.0.2 2019/10/12 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #ifndef WIN_DDRAW_H # define WIN_DDRAW_H @@ -32,7 +32,6 @@ extern int ddraw_init(HWND h); extern int ddraw_init_fs(HWND h); extern void ddraw_close(void); extern int ddraw_pause(void); -extern void ddraw_take_screenshot(const wchar_t *fn); extern void ddraw_enable(int enable); #ifdef __cplusplus diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 22a67731c..d05e9fdeb 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -12,7 +12,7 @@ * we will not use that, but, instead, use a new window which * coverrs the entire desktop. * - * Version: @(#)win_sdl.c 1.0.6 2019/03/09 + * Version: @(#)win_sdl.c 1.0.7 2019/10/12 * * Authors: Fred N. van Kempen, * Michael Dring, @@ -55,9 +55,6 @@ #include #include -#define PNG_DEBUG 0 -#include - #include #include #include @@ -90,9 +87,6 @@ static int cur_w, cur_h; static volatile int sdl_enabled = 0; static SDL_mutex* sdl_mutex = NULL; -static png_structp png_ptr; -static png_infop info_ptr; - /* Pointers to the real functions. */ static void (*sdl_GetVersion)(SDL_version *ver); @@ -522,94 +516,6 @@ sdl_init_fs(HWND h) } -void -sdl_take_screenshot(const wchar_t *fn) -{ - int i, res, x, y, width = 0, height = 0; - unsigned char* rgba = NULL; - png_bytep *b_rgb = NULL; - FILE *fp = NULL; - - sdl_GetWindowSize(sdl_win, &width, &height); - - /* create file */ - fp = plat_fopen((wchar_t *) fn, (wchar_t *) L"wb"); - if (!fp) { - sdl_log("[sdl_take_screenshot] File %ls could not be opened for writing", fn); - return; - } - - /* initialize stuff */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - - if (!png_ptr) { - sdl_log("[sdl_take_screenshot] png_create_write_struct failed"); - fclose(fp); - return; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - sdl_log("[sdl_take_screenshot] png_create_info_struct failed"); - fclose(fp); - return; - } - - png_init_io(png_ptr, fp); - - png_set_IHDR(png_ptr, info_ptr, width, height, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - rgba = (unsigned char *) malloc(width * height * 4); - if (rgba == NULL) { - sdl_log("[sdl_take_screenshot] Unable to Allocate RGBA Bitmap Memory"); - fclose(fp); - return; - } - - res = sdl_RenderReadPixels(sdl_render, NULL, SDL_PIXELFORMAT_ABGR8888, rgba, width * 4); - if (res) { - sdl_log("[sdl_take_screenshot] Error reading render pixels\n"); - fclose(fp); - return; - } - - b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * height); - if (b_rgb == NULL) { - sdl_log("[sdl_take_screenshot] Unable to Allocate RGB Bitmap Memory"); - free(rgba); - fclose(fp); - return; - } - - for (y = 0; y < height; ++y) { - b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); - for (x = 0; x < width; ++x) { - b_rgb[y][(x) * 3 + 0] = rgba[(y * width + x) * 4 + 0]; - b_rgb[y][(x) * 3 + 1] = rgba[(y * width + x) * 4 + 1]; - b_rgb[y][(x) * 3 + 2] = rgba[(y * width + x) * 4 + 2]; - } - } - - png_write_info(png_ptr, info_ptr); - - png_write_image(png_ptr, b_rgb); - - png_write_end(png_ptr, NULL); - - /* cleanup heap allocation */ - for (i = 0; i < height; i++) - if (b_rgb[i]) free(b_rgb[i]); - - if (b_rgb) free(b_rgb); - - if (rgba) free(rgba); - - if (fp) fclose(fp); -} - - int sdl_pause(void) { diff --git a/src/win/win_sdl.h b/src/win/win_sdl.h index c0e10ea93..9a0645455 100644 --- a/src/win/win_sdl.h +++ b/src/win/win_sdl.h @@ -8,13 +8,13 @@ * * Definitions for the libSDL2 rendering module. * - * Version: @(#)win_sdl.h 1.0.0 2018/05/26 + * Version: @(#)win_sdl.h 1.0.1 2019/10/12 * * Authors: Fred N. van Kempen, * Michael Dring, * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2018 Michael Dring. + * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2018,2019 Michael Dring. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -57,7 +57,5 @@ extern int sdl_pause(void); extern void sdl_resize(int x, int y); extern void sdl_enable(int enable); -extern void sdl_take_screenshot(const wchar_t *fn); - #endif /*WIN_SDL_H*/