Sitelet https://github.com/86Box/86Box/pull/6183
Skip to content

Add Initial Support for VBoxVGA Emulation in 86Box - #6183

Open
CE1CECL wants to merge 3 commits into
86Box:masterfrom
ChrisEric1:master
Open

CE1CECL wants to merge 3 commits into
86Box:masterfrom
ChrisEric1:master

Conversation

@CE1CECL

@CE1CECL CE1CECL commented Sep 17, 2025 •

Copy link
Copy Markdown

Summary

This Adds support for VirtualBox's older VGA Card that used to be emulated with 3D support until v6.1 of VirtualBox
Currently the code is a clang-format-16 mess, because this PR was actually started about a year ago by myself. (Update: 12/07/2025: I redid the whole thing to do what must be done to work in 86Box's current state, the rewrite from VBox's Code wasn't needed, and broke Bochs's version more than anything)
As of 09-17-2025, VBox Additions MUST be older than 4.0.0 due to SSE[?] not implemented yet.
VBoxGuestAdditions_3.2.28.iso work the best!

Checklist

  • Closes N/A
  • I have discussed this with core contributors already
  • This pull request doesn't require changes to the ROM set (yet)

References

This is the commit & file I used the most which helped me out with this a lot.

@DCFUKSURMOM

Copy link
Copy Markdown

Based

@jriwanek

jriwanek commented Nov 8, 2025

Copy link
Copy Markdown
Member

@CE1CECL This needs updated to current codebase

@jriwanek

jriwanek commented Nov 8, 2025 •

Copy link
Copy Markdown
Member

was that formatted using clang-format --style=file? because that doesn't look like our code style

(Also, you should be using clang-format, not clang-format-16)

@CE1CECL

CE1CECL commented Nov 8, 2025

Copy link
Copy Markdown
Author

was that formatted using clang-format --style=file? because that doesn't look like our code style

(Also, you should be using clang-format, not clang-format-16)

It was with --style=file but I don't have a clang-format, I just have clang-format-16, I assume it would usually be a symlink?

@jriwanek

jriwanek commented Nov 8, 2025

Copy link
Copy Markdown
Member

I dunno, but yeah, that's not our code style, also the clang-format off markers got removed. At this point, I advise starting again, but from our current code base, this currently doesn't compile, and even headers are reordered.

Signed-off-by: Christopher Lentocha <christopherericlentocha@gmail.com>
@CE1CECL

CE1CECL commented Dec 7, 2025 •

Copy link
Copy Markdown
Author

Ok, I ended up redoing the entire file from scratch, due to compiler errors and it was too hard to diff from the original commit by this point, while undoing the ordering of headers fixed it, I had to take the time to do it.
I also noticed (even without any new changes from this PR), this still doesn't work on non-ISA PCs emulated in 86Box (not sure why, this is a PCI emulated device but may rely on something, anyways), the color would not even, in Windows XP (or 7 PE), change out of 4 BPP even with the basic driver in Windows. Most of this was done using the 1 Misc PC, being Microsoft VPC (under 86Box) and 32 BPP works fine, though VBox Tools 4.1 or later don't even install the video driver without the guest driver existing. But as the v4.0 driver still doesn't work (it only lists up to 800x600 at 4 BPP & 32 BPP, which the 32 BPP makes the screen black and freezes the guest), VBox v3.x Tools is still recommended (Linked above). Also this doesn't Implement HGSMI (Host-Guest Shared Memory Interface), so the Linux kernel module vboxvideo.ko won't work, as it was merged into staging too late (2017).
Tested using Windows XP SP3 x86 VL (en_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-73974.iso) & Windows 7 Updated 2011 SP1 x86 (en_windows_7_enterprise_with_sp1_x64_dvd_u_677651.iso) & Plop Linux (ploplinux-25.2-S-i486.iso).
Also note WDDM won't work either, it was introduced in VBox Tools v4.0, and requires HGSMI 100%. VBox Tools v3.2 and older only have XPDM.
Its also worth mentioning I did split my changes into 2 commits, one with clang-format from the upstream without anything else, and putting my stuff after, so anyone can see what I did.

@CE1CECL

CE1CECL commented Dec 7, 2025 •

Copy link
Copy Markdown
Author

For those wondering, this breaks Plop Linux's GRUB interface & Windows from changing into 32 BPP:
Screenshot 2025-12-07 094217
While this doesn't:
Screenshot 2025-12-07 094225
Adding to my last comment.

@CE1CECL
CE1CECL marked this pull request as ready for review December 7, 2025 14:46
Copilot AI review requested due to automatic review settings December 7, 2025 14:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds initial support for VirtualBox's legacy VBoxVGA emulation to 86Box by extending the existing Bochs VBE SVGA driver. The implementation introduces VirtualBox-specific VBE Display Interface (VBE_DISPI) IDs and a new configuration register interface (VBE_DISPI_INDEX_CFG) that allows guest software to query device capabilities such as VRAM size and 3D support.

Key changes include:

  • Addition of VirtualBox-specific VBE_DISPI ID constants (VBE_DISPI_ID_VBOX_VIDEO, VBE_DISPI_ID_HGSMI, VBE_DISPI_ID_ANYX, VBE_DISPI_ID_CFG) for device identification
  • Implementation of a configuration interface register (VBE_DISPI_INDEX_CFG) with read handlers for querying version, VRAM size, 3D support, and VMSVGA capabilities
  • Expansion of memory configuration options from 4-16 MB to 1-512 MB to match VirtualBox's flexibility
  • Extensive code reformatting to improve consistency and readability

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/video/vid_bochs_vbe.c Outdated
ret = 0x000f;
break;
case VBE_DISPI_INDEX_CFG:
switch (dev->vbe_regs[dev->vbe_index] & 0x1000) {

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mask 0x1000 is incorrect for matching VBE_DISPI_CFG_ID values. The VBE_DISPI_CFG_ID constants range from 0x0000 to 0x0004, so masking with 0x1000 will always result in 0x0000 or 0x1000, never matching cases VBE_DISPI_CFG_ID_VRAM_SIZE (0x0001), VBE_DISPI_CFG_ID_3D (0x0002), VBE_DISPI_CFG_ID_VMSVGA (0x0003), or VBE_DISPI_CFG_ID_VMSVGA_DX (0x0004).

The mask should likely be 0xFFFF or a value that preserves the lower bits. Looking at VirtualBox's implementation, this should read the value without masking, or mask with 0xFFFF to get the full 16-bit value.

Suggested change
switch (dev->vbe_regs[dev->vbe_index] & 0x1000) {
switch (dev->vbe_regs[dev->vbe_index] & 0xFFFF) {

Copilot uses AI. Check for mistakes.

@CE1CECL CE1CECL Dec 7, 2025 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 0x1000 comes from VBE_DISPI_CFG_MASK_ID as is defined here in the VBox source. It isn't correct, either way, it should be 0x0FFF (I got 0x1000 from

#define VBE_DISPI_CFG_MASK_SUPPORT      0x1000 /* Query whether the identifier is supported. */

By mistake)

Comment thread src/video/vid_bochs_vbe.c
ret = 1;
break;
case VBE_DISPI_CFG_ID_VRAM_SIZE:
ret = dev->vram_size;

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value should be cast to uint16_t or the function should handle potential overflow. The dev->vram_size is a uint32_t (can be up to 512 MB based on config options), but ret is a uint16_t. This will truncate the value, returning incorrect VRAM size information.

For example, 512 MB (0x20000000) truncated to uint16_t becomes 0x0000. The correct approach would be to either:

  1. Return the full 32-bit value if the protocol supports it, or
  2. Return VRAM size in a different unit (e.g., MB or 64K blocks) that fits in 16 bits
Suggested change
ret = dev->vram_size;
ret = dev->vram_size >> 16;

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VBox Doesn't do this in this register.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then either VBox has a bug or there's some other difference going on here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VirtualBox does VRAM size return in the dword handler, so you need an inl() handler in 86Box - 86Box uses separate handlers for byte, word, and dword.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed I did overlook what Copilot said before,
ret in 86Box is uint16_t, while val in VBox is uint32_t
Both of the ->vram_size in both of VBox & 86Box are both uint32_t
Will fix as soon as I can.

Comment thread src/video/vid_bochs_vbe.c
default:
break;
case VBE_DISPI_INDEX_ID:
if ((val == VBE_DISPI_ID0) || (val == VBE_DISPI_ID1) || (val == VBE_DISPI_ID2) || (val == VBE_DISPI_ID3) || (val == VBE_DISPI_ID4) || (val == VBE_DISPI_ID_VBOX_VIDEO) || (val == VBE_DISPI_ID_ANYX) || (val == VBE_DISPI_ID_CFG))

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VBE_DISPI_ID_HGSMI (0xBE01) constant is defined at line 77 but is missing from the ID validation check. The condition checks for VBE_DISPI_ID_VBOX_VIDEO (0xBE00), VBE_DISPI_ID_ANYX (0xBE02), and VBE_DISPI_ID_CFG (0xBE03), but omits VBE_DISPI_ID_HGSMI which is part of the VirtualBox VGA device ID sequence.

Add || (val == VBE_DISPI_ID_HGSMI) to the condition to allow this ID to be set.

Suggested change
if ((val == VBE_DISPI_ID0) || (val == VBE_DISPI_ID1) || (val == VBE_DISPI_ID2) || (val == VBE_DISPI_ID3) || (val == VBE_DISPI_ID4) || (val == VBE_DISPI_ID_VBOX_VIDEO) || (val == VBE_DISPI_ID_ANYX) || (val == VBE_DISPI_ID_CFG))
if ((val == VBE_DISPI_ID0) || (val == VBE_DISPI_ID1) || (val == VBE_DISPI_ID2) || (val == VBE_DISPI_ID3) || (val == VBE_DISPI_ID4) || (val == VBE_DISPI_ID_VBOX_VIDEO) || (val == VBE_DISPI_ID_HGSMI) || (val == VBE_DISPI_ID_ANYX) || (val == VBE_DISPI_ID_CFG))

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not implemented, adding it for XP makes it BSOD.

Comment thread src/video/vid_bochs_vbe.c
(val == VBE_DISPI_ID4))
else if ((addr == 0x1cf) || (addr == 0x1d0))
switch (dev->vbe_index) {
default:

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VBE_DISPI_INDEX_CFG register needs a write handler to store the configuration ID value. Currently, writes to this register fall through to the default case which does nothing. The guest driver writes the config ID (e.g., VBE_DISPI_CFG_ID_VRAM_SIZE) to this register, then reads it back to get the corresponding value.

Add a case handler:

case VBE_DISPI_INDEX_CFG:
    dev->vbe_regs[dev->vbe_index] = val;
    break;

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it by adding all registers to the write list:

            default:
                dev->vbe_regs[dev->vbe_index] = val;
                break;

Comment thread src/video/vid_bochs_vbe.c
#define CVT_MIN_VSYNC_BP 550.0

/* 3) Nominal HSync width (% of line period) - default 8 */
/* 3) Nominal HSync width (% of line period) - default 8 */

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] These comments have extra indentation that is inconsistent with the rest of the code. The comments should be aligned with the code at the same level (no leading spaces before the /*). This appears to be a formatting error introduced during the refactor.

Suggested change
/* 3) Nominal HSync width (% of line period) - default 8 */
/* 3) Nominal HSync width (% of line period) - default 8 */

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-format issue

Comment thread src/video/vid_bochs_vbe.c
ret = (dev->id5_val == VBE_DISPI_ID5) ? 0x11 : 0xbe;
break;
case 0x04:
ret = (dev->pci_conf_status & 0b11100011) | 0x80;

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Binary literal 0b11100011 should be written as 0xE3 for consistency. Binary literals are not commonly used in this codebase, and using hexadecimal notation is more conventional for bit masks in hardware emulation code.

Suggested change
ret = (dev->pci_conf_status & 0b11100011) | 0x80;
ret = (dev->pci_conf_status & 0xE3) | 0x80;

Copilot uses AI. Check for mistakes.
Comment thread src/video/vid_bochs_vbe.c
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
CVT_J_FACTOR
#define CVT_M_PRIME CVT_M_FACTOR *CVT_K_FACTOR / 256

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Missing space around the * operator. Should be CVT_M_FACTOR * CVT_K_FACTOR / 256 for consistency with the spacing in the line below and general C style conventions.

Suggested change
#define CVT_M_PRIME CVT_M_FACTOR *CVT_K_FACTOR / 256
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-format issue

Signed-off-by: Christopher Lentocha <christopherericlentocha@gmail.com>
@Cacodemon345

Copy link
Copy Markdown
Contributor

What's the current status of the code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants