From 3f6126f72dd83e34b01543fa84c259f51027f396 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 May 2024 01:45:22 +0200 Subject: [PATCH] Bochs VBE fixes, fixes #4410. --- src/video/vid_bochs_vbe.c | 80 ++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index 603e455d1..a4459ce4c 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -124,6 +124,7 @@ typedef struct bochs_vbe_t { mem_mapping_t linear_mapping; mem_mapping_t linear_mapping_2; + uint32_t ma_latch_old; void * i2c; void * ddc; @@ -322,10 +323,10 @@ bochs_vbe_recalctimings(svga_t* svga) svga->hblankend = mode.hdisplay + (mode.htotal - mode.hdisplay - 1); svga->vblankstart = svga->dispend; /* no vertical overscan. */ svga->rowcount = 0; + svga->hoverride = 1; if (dev->vbe_regs[VBE_DISPI_INDEX_BPP] != 4) { svga->fb_only = 1; svga->adv_flags |= FLAG_NO_SHIFT3; - } else { svga->fb_only = 0; svga->adv_flags &= ~FLAG_NO_SHIFT3; @@ -334,26 +335,29 @@ bochs_vbe_recalctimings(svga_t* svga) svga->bpp = dev->vbe_regs[VBE_DISPI_INDEX_BPP]; if (svga->bpp == 4) { - svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] >> 3; + svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); } else { - svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * (svga->bpp / 8); + svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + - (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * (svga->bpp / 8)); + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); } - - if ((svga->ma_latch + dev->vbe_regs[VBE_DISPI_INDEX_YRES] * svga->rowoffset) > - svga->vram_max) { - dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0; - svga->ma_latch = (svga->bpp == 4) ? (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3) : - (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * (svga->bpp / 8)); - if ((svga->ma_latch + dev->vbe_regs[VBE_DISPI_INDEX_YRES] * svga->rowoffset) > - svga->vram_max) { - svga->ma_latch = 0; - dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0; + if (svga->ma_latch != dev->ma_latch_old) { + if (svga->bpp == 4) { + svga->maback = (svga->maback - (dev->ma_latch_old << 2)) + + (svga->ma_latch << 2); + } else { + svga->maback = (svga->maback - (dev->ma_latch_old)) + + (svga->ma_latch); + dev->ma_latch_old = svga->ma_latch; } } + + if (svga->bpp == 4) + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (svga->vram_max * 2) / dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH]; + else + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (svga->vram_max / ((svga->bpp == 15) ? 2 : (svga->bpp / 8))) / dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH]; svga->split = 0xffffff; switch (svga->bpp) { @@ -381,6 +385,7 @@ bochs_vbe_recalctimings(svga_t* svga) svga->fb_only = 0; svga->packed_4bpp = 0; svga->adv_flags &= ~FLAG_NO_SHIFT3; + svga->hoverride = 0; } } @@ -417,8 +422,10 @@ bochs_vbe_inw(const uint16_t addr, void *priv) case VBE_DISPI_INDEX_DDC: if (dev->vbe_regs[dev->vbe_index] & (1 << 7)) { ret = dev->vbe_regs[dev->vbe_index] & ((1 << 7) | 0x3); - ret |= i2c_gpio_get_scl(dev->i2c) << 2; - ret |= i2c_gpio_get_sda(dev->i2c) << 3; + if ((ret & 0x01) && i2c_gpio_get_scl(dev->i2c)) + ret |= 0x04; + if ((ret & 0x02) && i2c_gpio_get_sda(dev->i2c)) + ret |= 0x08; } else ret = 0x000f; break; @@ -466,7 +473,30 @@ bochs_vbe_outw(const uint16_t addr, const uint16_t val, void *priv) case VBE_DISPI_INDEX_X_OFFSET: case VBE_DISPI_INDEX_Y_OFFSET: dev->vbe_regs[dev->vbe_index] = val; - svga_recalctimings(&dev->svga); + if (dev->vbe_index == VBE_DISPI_INDEX_X_OFFSET || dev->vbe_index == VBE_DISPI_INDEX_Y_OFFSET) { + svga_t *svga = &dev->svga; + if (svga->bpp == 4) { + svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; + svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); + } else { + svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); + svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); + } + if (svga->ma_latch != dev->ma_latch_old) { + if (svga->bpp == 4) { + svga->maback = (svga->maback - (dev->ma_latch_old << 2)) + + (svga->ma_latch << 2); + } else { + svga->maback = (svga->maback - (dev->ma_latch_old)) + + (svga->ma_latch); + dev->ma_latch_old = svga->ma_latch; + } + } + } + else + svga_recalctimings(&dev->svga); break; case VBE_DISPI_INDEX_BANK: @@ -788,6 +818,21 @@ bochs_vbe_init(const device_t *info) 0xc0000, 0x10000, 0xffff, 0x0000, MEM_MAPPING_EXTERNAL); + if (dev->id5_val == VBE_DISPI_ID4) { + /* Patch the BIOS to match the PCI ID. */ + dev->bios_rom.rom[0x010c] = 0xee; + dev->bios_rom.rom[0x8dff] -= (0xee - 0x34); + + dev->bios_rom.rom[0x010d] = 0x80; + dev->bios_rom.rom[0x8dff] -= (0x80 - 0x12); + + dev->bios_rom.rom[0x010e] = 0xef; + dev->bios_rom.rom[0x8dff] -= (0xef - 0x11); + + dev->bios_rom.rom[0x010f] = 0xbe; + dev->bios_rom.rom[0x8dff] -= (0xbe - 0x11); + } + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_bochs); svga_init(info, &dev->svga, dev, dev->vram_size, @@ -826,6 +871,7 @@ bochs_vbe_init(const device_t *info) dev->i2c = i2c_gpio_init("ddc_bochs"); dev->ddc = ddc_init(i2c_gpio_get_bus(dev->i2c)); + dev->svga.packed_chain4 = 1; pci_add_card(PCI_ADD_NORMAL, bochs_vbe_pci_read, bochs_vbe_pci_write, dev, &dev->slot);